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.
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.
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.
- 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.
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.
Released in version 2.6.1.
Fixed memory leaks, removed MediaDevice polling, addressed security vulnerabilities, and removed deprecated dependencies.
Moved the library source to another GitHub repository. Releases aren't uploaded to the Twilio CDN.
To install the module, use npm
: @twilio/voice-sdk.
To allow connections to the new DNS names and IP addresses, update any Content Security Policies (CSP) 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.
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);
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:
- device.register, which registers the
Device
instance to receive incoming calls. - device.connect, which places an outbound call.
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.
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*/4async function getAccessToken(): string;56const token = await getAccessToken();7const options = { ... };8const device = new Device(token, options);910device.on(Device.EventName.TokenWillExpire, async () => {11const newToken = await getAccessToken();12device.updateToken(newToken);13});
- Removed
Device.Status
. Refactored asDevice.State
. - Removed the
Device
busy
status. To check if the Device is busy, use the device.isBusy getter method. - Renamed the
ready
status toDevice.State.Registered
. - Renamed the
offline
status toDevice.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.
- To review these parameters, see Call.AcceptOptions and Device.ConnectOptions.
- The
Device.ConnectOptions
type extends theCall.AcceptOptions
type. - The option types take
MediaStreamConstraints
as opposed toMediaTrackConstraints
. To learn more, see the MediaStreamConstraints resource in the Mozilla documentation.
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 code | New error code | Error description |
---|---|---|
31003 | 53405 | Ice connection failure |
31201 | 31402 | Unable to acquire user media |
31208 | 31401 | User denies access to user media |
31901 | 53000 | Websocket 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?: 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;23type LogLevelDesc =4| 0 | 1 | 2 | 3 | 4 | 55| '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?: 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:
1getLocalStream(): MediaStream | undefined;2getRemoteStream(): 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:
1const call = device.connect();2...3call.mute(false); // unmutes the call