Skip to contentSkip to navigationSkip to topbar
On this page

Migration to Voice JavaScript SDK 2.0


The SDK 2.x version includes the new features, bug fixes, and security patches. This migration guide covers up to version 2.7.2.

(information)

SDK v1 has reached end of life

To learn more, see the Voice JavaScript SDK: Changelog. To use Voice JavaScript SDK 2.x, Flex users must upgrade to Flex UI 2.x and can skip this guide.

(warning)

Migrate from Capability to Access tokens

If you're currently using Capability Tokens with the Voice JavaScript SDK, migrate to Access Tokens as soon as possible. See our Capability Tokens Migration Guide for more information.


New Features and Improvements

new-features-and-improvements page anchor

Modern design patterns

modern-design-patterns page anchor
  • To keep your code concise when asynchronous actions occur, Library APIs use Promises.
  • To keep your app UI current, use the returned Promise when registering for incoming calls or making an outgoing call.

Support for modern JavaScript frameworks

support-for-modern-javascript-frameworks page anchor

Released in versions 2.6.0 and 2.7.0.

Released in version 2.2.0.

Twilio in-band websocket messaging. The SDK supports sending messages to and receiving messages from backend services through the existing websocket connection.

Replaced generic error codes with more descriptive error codes and objects.

Released in version 2.5.0.

Added library support for VDI environments, such as Citrix HDX.

Improved performance and security

improved-performance-and-security page anchor

Released in version 2.6.1.

Fixed memory leaks, removed MediaDevice polling, addressed security vulnerabilities, and removed deprecated dependencies.


Import the library into your project

import-the-library-into-your-project page anchor

Moved the library source to another GitHub repository(link takes you to an external page). Releases aren't uploaded to the Twilio CDN.

To install the module, use npm: @twilio/voice-sdk(link takes you to an external page).


To allow connections to the new DNS names and IP addresses, update any Content Security Policies (CSP)(link takes you to an external page) or other network security configurations that your app uses.

Renamed the Connection class to the Call class. This shouldn't affect any public API. Some internal method names have been updated. Update any code that accesses internal methods.

Removal of the Device singleton

removal-of-the-device-singleton page anchor

Changed Device behavior from a singleton in 2.x.

To create a Device in 2.x, write the code as follows:

const device = new Device(token, deviceOptions);

Removed support for the device.setup method. To create a new Device, invoke its constructor:

const device = new Device(token, deviceOptions);

Device configurations after construction

device-configurations-after-construction page anchor

The device.setup method doesn't update the Device instance after it has been created. To update any of the Device instance options, use device.updateOptions(deviceOptions).

The SDK performs setup only when necessary. This decreases time to a ready application state and only makes network connections when needed.

The Device constructor works synchronously and doesn't open a signaling channel. The signaling websocket opens when you invoke either of the following methods:

To monitor the Device instance registration status, your app needs the Device instance to emit the following events:

If you make an outbound call but haven't registered for inbound calls, invoke Call.status and observe the signaling connection status.

Keep the AccessToken up to date

keep-the-accesstoken-up-to-date page anchor
(warning)

Migrate from Capability to Access tokens

If you're currently using Capability Tokens with the Voice JavaScript SDK, migrate to Access Tokens as soon as possible. See our Capability Tokens Migration Guide for more information.

Update the AccessToken with the device.updateToken(accessToken: AccessToken) method.

Prior to registering for inbound calls with device.register() or making an outbound call with device.connect(), listen to the tokenWillExpireEvent to validate the AccessToken.

To help use this feature, consider the following example:

1
/**
2
* This function fetches an AccessToken from your backend services.
3
*/
4
async function getAccessToken(): string;
5
6
const token = await getAccessToken();
7
const options = { ... };
8
const device = new Device(token, options);
9
10
device.on(Device.EventName.TokenWillExpire, async () => {
11
const newToken = await getAccessToken();
12
device.updateToken(newToken);
13
});
  • Removed Device.Status. Refactored as Device.State.
  • Removed the Device busy status. To check if the Device is busy, use the device.isBusy getter method.
  • Renamed the ready status to Device.State.Registered.
  • Renamed the offline status to Device.State.Unregistered.

The statuses of ready and offline indicate registration status rather than signaling connection status.

Changed the methods to accept incoming calls or make outgoing calls use the same parameters.

Improved error descriptions. For backward compatibility, error objects include the previous error format in the error.twilioError property.

Replaced some generic error codes with more specific and precise error codes. The changed error codes are listed in the following table:

Former error codeNew error codeError description
3100353405Ice connection failure
3120131402Unable to acquire user media
3120831401User denies access to user media
3190153000Websocket timeout during preflight

Removed the DeviceOptions property enableRingingState in 2.0. Enabled ringing states by default.

For full functionality, this requires setting answerOnBridge in your TwiML. However, without answerOnBridge, the Call goes through the new ringing state before transitioning to open. When you enable answerOnBridge, the ringing state begins when the recipient's phone begins ringing. When the recipient answers the call and establishes the media, the status transitions to open.

Removed raising a cancel event in response to a local call.ignore(). Instead, Twilio only raises it when the remote end cancels the call.


  • A plus (+) sign denotes an addition to the SDK with 2.x.
  • A dash (-) denotes a removal from the SDK with 2.x.

audioConstraints

audioconstraints page anchor
-audioConstraints?: MediaTrackConstraints | boolean;

Moved functionality to the device.connect and call.accept methods.

1
-codecPreferences?: Connection.Codec[];
2
+codecPreferences?: Call.Codec[];

To reflect the Call class rename, this option's functionality remains unchanged, but changes the type.

-debug?: boolean;

The logLevel option covers this functionality.

-enableIceRestart?: boolean;

Twilio enables this functionality by default.

-fakeLocalDTMF?: boolean;

Twilio enables this functionality by default.

+enumerateDevices?: any;

This parameter enables VDI support.

+getUserMedia?: any;

This parameter enables VDI support.

1
+logLevel?: LogLevelDesc;
2
3
type LogLevelDesc =
4
| 0 | 1 | 2 | 3 | 4 | 5
5
| 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent'
6
| 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'SILENT';

This parameter allows for finer control over logged messages. This option supersedes the functionality that Device.Options.debug and Device.Options.warnings provided in a standardized way.

-region?: string;

Changed to use edge not the region name.

-rtcConfiguration?: RTCConfiguration;

Moved this functionality to device.connect and call.accept methods.

maxCallSignalingTimeoutMs

maxcallsignalingtimeoutms page anchor
+maxCallSignalingTimeoutMs?: number;

Enabled the new Signaling Reconnection feature in this parameter.

+RTCPeerConnection?: any;

Enabled VDI support for this parameter.

-warnings?: boolean;

Covered this functionality in the logLevel option.

+tokenRefreshMs?: number;

Adjusted the event timing of the tokenWillExpire event in this parameter.


  • A plus (+) sign denotes an addition to the SDK with 2.x.
  • A dash (-) denotes a removal from the SDK with 2.x.
-cancelEvent(connection: Connection): void;

Removed how the device object emits a cancel event for canceled incoming calls. To emit a cancel event, attach a listener to the Call.Event.Cancel event.

-connectEvent(connection: Connection): void;

Removed how the device object emits a connect event when establishing an outgoing call. To emit a connect event, use the return value from device.connect.

+destroyedEvent(): void;

Added a new API method that raises when you destroy a Device.

-disconnectEvent(connection: Connection): void;

Added the Call.Event.Disconnect method to provide this functionality.

1
-errorEvent(connection: Connection): void;
2
+errorEvent(error: TwilioError, call?: Call): void;

Changed the listener signature for this event. When the error is call related, it emits a call as the second parameter. Other signaling errors surface as the first parameter to this event.

1
-incomingEvent(connection: Connection): void;
2
+incomingEvent(call: Call): void;

Kept the event functionality unchanged. It renames the parameters as the Connection class to Call.

1
-offlineEvent(device: Device): void;
2
+unregisteredEvent(): void;

Renamed this event to Device.Event.Unregistered.

1
-readyEvent(device: Device): void;
2
+registeredEvent(): void;

Renamed this event to Device.Event.Registered.

+registeringEvent(): void;

Added a new API method that raises when the Device has started the registration process, in effect after Device.register has been invoked.

+tokenWillExpireEvent(device: Device): void;

Added a new API method that raises when the token passed to the Device which shall expire. To configure this event's time interval and its expiry, see Device.Options.tokenRefreshMs.


  • A plus (+) sign denotes an addition to the SDK with 2.x.
  • A dash (-) denotes a removal from the SDK with 2.x.
1
-connections: Connection[];
2
+calls: Call[];

Renamed to reflect the class name change.

-isInitialized: boolean;

Changed the application code to observe the registration status of the Device, either through the registration events or Device.state.

-readonly sounds: Partial<Record<Device.SoundName, (value?: boolean) => void>> = {};

Added Device.audio to access any sound-related functionality.

1
-constructor(): Device;
2
-constructor(token: string, options?: Device.Options): Device;
3
-constructor(token?: string, options?: Device.Options): Device;
4
+constructor(token: string, options: Device.Options = {}): Device;

To construct a Device, it requires a token.

-activeConnection(): Connection | null | undefined;

Changed the application code to track of all calls made or received.

The device.connect() API returns outgoing calls:

const outgoingCall = await device.connect();

Changed the Device.EventName.Incoming event to emit incoming calls.

device.on(Device.EventName.Incoming, (incomingCall) => ...);
1
-cancel(handler: (connection: Connection) => any): this;
2
-connect(handler: (connection: Connection) => any): this;
3
-disconnect(handler: (connection: Connection) => any): this;
4
-error(handler: (error: Connection) => any): this;
5
-incoming(handler: (connection: Connection) => any): this;
6
-offline(handler: (device: Device) => any): this;
7
-ready(handler: (device: Device) => any): this;

Removed deprecated event handler setter methods.

1
-connect(params?: Record<string, string>, audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): Connection;
2
-connect(paramsOrHandler?: Record<string, string> | ((connection: Connection) => any), audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): Connection | null;
3
+async connect(options: Device.ConnectOptions = {}): Promise<Call>;

Consolidated all options into an options object parameter. See device.connect.

-region(): string;

Deprecated connecting by region. Use the Device.edge method.

-setup(token: string, options: Device.Options = {}): this;

Changed how the Device sets up when making an outgoing call or registering for incoming calls.

1
-status(): Device.Status;
2
+get state(): Device.State;

Renamed to device.state.

+get home(): string | null;

Added an API method.

+get identity(): string | null;

Added an API method.

+get isBusy(): boolean;

Added an API method.

1
-registerPresence(): this;
2
+async register(): Promise<void>;

Changed registration to an asynchronous action. The API surfaces it with a Promise.

1
-unregisterPresence(): this;
2
+async unregister(): Promise<void>;

Changed registration to an asynchronous action. The API surfaces it with a Promise.

+updateOptions(options: Device.Options = {}): void;

Added a new API that updates the options of a device after the device has been constructed.


Renamed the class from Connection to Call.

  • A plus (+) sign denotes an addition to the SDK with 2.x.
  • A dash (-) denotes a removal from the SDK with 2.x.
1
-readonly callerInfo: Connection.CallerInfo | null;
2
+readonly callerInfo: Call.CallerInfo | null;

Changed the property's type annotation to reflect the class name change.

1
-get direction(): Connection.CallDirection;
2
+get direction(): Call.CallDirection;

Changed the return value's type annotation to reflect the class name change.

-mediaStream: IPeerConnection;

Removed this private class member from the public API. To fetch the MediaStream objects associated with a call, use the following methods:

1
getLocalStream(): MediaStream | undefined;
2
getRemoteStream(): MediaStream | undefined;
1
-accept(handler: (connection: this) => void): void;
2
-disconnect(handler: (connection: this) => void): void;
3
-cancel(handler: () => void): void;
4
-error(handler: (error: Connection.Error) => void): void;
5
-ignore(handler: () => void): void;
6
-mute(handler: (isMuted: boolean, connection: this) => void): void;
7
-reject(handler: () => void): void;
8
-volume(handler: (inputVolume: number, outputVolume: number) => void): void;

Removed setting event handlers. Use the Call.on or Call.addListener methods.

1
-accept(audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): void;
2
+accept(options?: Call.AcceptOptions);

Consolidated Call options into a single object parameter. See call.accept.

-cancel(): void;

Removed deprecated API. To disconnect from an outgoing call at any time, use call.disconnect.

1
-postFeedback(score?: Connection.FeedbackScore, issue?: Connection.FeedbackIssue): Promise<void>;
2
+postFeedback(score?: Call.FeedbackScore, issue?: Call.FeedbackIssue): Promise<void>;

Kept the functionality of this API. Renamed the method parameters to reflect the Call class name change.

1
-status(): Connection.State;
2
+status(): Call.State;

Renamed the type of the return value. This reflects the Call class name change.

-unmute(): void;

Removed this deprecated API. To achieve the same result, use the following:

1
const call = device.connect();
2
...
3
call.mute(false); // unmutes the call