Make an outbound call with Twilio
The following flow diagram shows the sequence of operations performed once an agent starts an outbound call from the Fusion application:

- When the agent starts an outbound call from the Fusion application by clicking
on the phone number, the
onOutgoingEventevent is fired. - The
onOutgoingEventevent listener in your media toolbar application receives this event and starts the outbound call by calling the Twiliodevice.connectAPI by passing the phone number to be dialed. - Twilio starts the outbound call and returns the
Callobject. - The
newCommEventaction is called from your media toolbar application. - The Fusion application shows the dialing panel once the
newCommEventaction is received
To make an outbound call using Twilio , we need to call the connect method of the Twilio
Device object. The code looks like this:
const device = new Device(token);
let call = await device.connect({
params: {
To: '+15551234567'
}
});
This example shows an try to create a new connection with the Twilio application that you
associated with the Access Token used when instantiating the Device
instance. This method returns a Promise with the Call
object. You can track this Call object to monitor or change the active
call. You can listen to user actions by listening to the to the accept,
disconnect and cancel events on the Call
object.
You can update the makeOutboundCall method in
VendorHandler class for this as shown in the following example:
public async makeOutboundCall(phoneNumber: string, eventId: string): Promise<void> {
const params = {
To: phoneNumber,
};
if (this.device) {
this.call = await this.device.connect({ params });
const callId = this.call.parameters.CallSid
this.call.on("accept", () => { this.integrationEventsHandler.outboundCallAcceptedHandler(callId) });
this.call.on("disconnect", () => { this.integrationEventsHandler.callHangupHandler(callId) });
this.call.on("cancel", () => { this.integrationEventsHandler.callRejectedHandler(callId) });
}
}
Complete code
Here's the complete code of the vendorHandler.ts file for starting
an outbound call:
import { Call, Device } from '@twilio/voice-sdk';
import { ICtiVendorHandler } from './ICtiVendorHandler';
import { IntegrationEventsHandler } from '../integrationEventsHandler';
export class VendorHandler implements ICtiVendorHandler {
private twilio: any;
private device: Device | null;
private integrationEventsHandler: IntegrationEventsHandler;
private call: Call | null;
public idAndToken: any;
constructor(integrationEventsHandler: IntegrationEventsHandler) {
this.twilio = (window as any).Twilio;
this.device = null;
this.idAndToken = null;
this.integrationEventsHandler = integrationEventsHandler;
this.call = null;
}
public async makeAgentAvailable(): Promise<void> {
this.idAndToken = await this.getIdAndToken();
this.device = new this.twilio.Device(this.idAndToken.token, {
logLevel: 1,
codecPreferences: ["opus", "pcmu"],
enableRingingState: true
});
let resolve: Function;
let reject: Function;
if (this.device) {
this.device.on("registered", () => {
console.log("Registration completed ...")
resolve();
});
this.device.on("error", (deviceError) => {
console.error("Registration Failed ...", deviceError);
reject();
});
this.device.on("incoming", this.incomingCallCallback);
this.device.register();
}
return new Promise((res: Function, rej: Function) => {
resolve = res;
reject = rej;
});
}
public incomingCallCallback = (call: Call) => {
this.integrationEventsHandler.incomingCallHandler(call.parameters.From, call.parameters.CallSid);
this.call = call;
}
public async makeAgentUnavailable(): Promise<void> {
let resolve: Function;
let reject: Function;
if (this.device) {
this.device.on("unregister", () => {
console.log("Successfully UnRegistered ...")
resolve();
});
this.device.on("error", (deviceError) => {
console.error("Failed to unregister ...", deviceError);
reject();
});
this.device.unregister();
}
return new Promise((res: Function, rej: Function) => {
resolve = res;
reject = rej;
});
}
public async makeOutboundCall(phoneNumber: string, eventId: string): Promise<void> {
const params = {
To: phoneNumber,
};
if (this.device) {
this.call = await this.device.connect({ params });
const callId = this.call.parameters.CallSid
this.call.on("accept", () => { this.integrationEventsHandler.outboundCallAcceptedHandler(callId) });
this.call.on("disconnect", () => { this.integrationEventsHandler.callHangupHandler(callId) });
this.call.on("cancel", () => { this.integrationEventsHandler.callRejectedHandler(callId) });
}
}
public async acceptCall(): Promise<void> {
if (this.call) {
this.call.accept();
}
}
public async rejectCall(): Promise<void> {
if (this.call) {
this.call.reject();
}
}
public async hangupCall(): Promise<void> {
if (this.call) {
this.call.disconnect();
}
}
private async getIdAndToken(): Promise<any> {
const headers: Headers = (new Headers()) as Headers;
headers.set('Accept', 'application/json');
const request: Request = new Request('https://twilio-voice-stream.com/token', {
method: 'GET',
headers: headers
}) as Request;
const idAndToken: Response = await fetch(request);
this.idAndToken = await idAndToken.json();
return this.idAndToken;
}
}
Verify your progress
After finishing these steps, use OJET server to start you application and sign in to your Fusion application. Open the media toolbar and make your agent available for calls by clicking on the Agent Availability button. To start an outbound call, open the contact from your Fusion application and click the phone number, which starts the outbound call.