This migration guide covers up to version 2.7.2. Please refer to the Voice JavaScript SDK: Changelog page for more details if you are upgrading to a newer version.
The newest version of the SDK will always have the latest and greatest features, bug fixes, and security patches. We're always adding new capabilities - below is shortlist of notable investments we've made in versions 2.x.
The SDK has been updated to use more modern design patterns. Library APIs now use Promises where asynchronous actions occur to help keep your code concise and clean. When registering for incoming calls or making an outgoing call, you can now use the returned Promise to keep your application UI up-to-date.
Twilio in-band websocket messaging. The SDK now supports the ability to send messages to and receive messages from backend services through the existing websocket connection.
This feature was released with version 2.2.0.
Older, more generic, error codes have been replaced with more descriptive error codes and objects.
The library now has support for VDI environments, such as Citrix HDX.
This feature was released with version 2.5.0.
Fixed memory leaks, removed MediaDevice polling, addressed security vulnerabilities, and removed deprecated dependencies.
This feature was released with version 2.6.1.
The library source is hosted in a new GitHub repository. The recommended way to install the module is through npm.
2.x versions of the Voice JavaScript SDK are now published under @twilio/voice-sdk.
1.x versions of the Voice JavaScript SDK are still available as twilio-client.
In the interest of promoting best practices, 2.0 and newer releases will not be uploaded to the Twilio CDN. Existing versions (prior to 2.0) and any further 1.x release will continue to be served via the CDN. However, we still strongly recommend not to link directly to these files in production as it introduces the potential for interruption due to CDN outages.
For customers currently using the CDN, there are a couple of options for switching:
@twilio/voice-sdk
. From here, the built distribution files will be available under node_modules/@twilio/voice-sdk/dist
.-rc
), unzip it, and navigate to /dist
for the twilio.js
and twilio.min.js
files.If your application uses Content Security Policies (CSP), they need to be updated along with other network configurations such as firewall rules, etc. to allow connections to the new DNS names and IP addresses.
We've renamed the Connection
class to Call
. This shouldn't affect any public API; however, some internal method names have been updated. Therefore, any code accessing internal methods will break if not updated.
As part of adapting to modern design patterns, the singleton behavior of Device
has been removed.
If your code is similar to the following on 1.x:
const device = Twilio.Device;
Your code on 2.x should create a Device
like this:
const device = new Device(token, deviceOptions);
Create a new Device by invoking the constructor. The device.setup
method is no longer supported.
If your code is similar to the following on 1.x:
const device = Twilio.Device.setup(...);
Your code on 2.x should create a Device like this:
const device = new Device(token, deviceOptions);
Additionally, device.setup
will no longer work for updating the Device
instance after it has been created. Instead, use device.updateOptions(deviceOptions)
to update any of the Device
instance options.
The SDK now performs setup only when necessary, decreasing time to a ready application state and only making network connections when needed.
This means that the Device
constructor is synchronous and will not cause a signaling channel to be opened. The signaling websocket will be opened when either:
Device
instance to receive incoming calls.If your application needs to monitor the Device
instance registration status, the following events are emitted by the Device
instance:
In the scenario such that you are making an outbound call and have not previously registered for inbound calls, you can invoke Call.status
to observe the signaling connection status.
The AccessToken can be updated with device.updateToken(accessToken: AccessToken).
Prior to registering for inbound calls with device.register() or making an outbound call with device.connect(), you can ensure that the AccessToken is valid by listening to the tokenWillExpireEvent.
The following is an example of how to use this feature:
1/**2* This function would fetch 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});
Device status has been removed and refactored as Device state. Note that we no longer represent busy
as part of the Device
state. You can check if the Device is busy by using the device.isBusy getter method. The ready
status has been renamed to Device.State.Registered
. The offline
status has been renamed to Device.State.Unregistered
. An important note is that ready
and offline
have always indicated registration status rather than signaling connection status. This change aims to clear up confusion.
The functions to accept an incoming call and make an outgoing call now have their parameters standardized. Please see Call.AcceptOptions and Device.ConnectOptions. Note that Device.ConnectOptions
extends the Call.AcceptOptions
type. Also note that the option types take MediaStreamConstraints
as opposed to MediaTrackConstraints
. Please see this resource for more information.
Error reporting is now more descriptive. For backward compatibility, the existing error format is attached under the error.twilioError
member of the new error objects.
Some generic error codes have been replaced with more specific and precise error codes. See the following table for changed error codes.
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 |
In a prior version, we included ringing states on Call
, which were enabled behind the DeviceOptions
property enableRingingState
. We have removed this flag in 2.0, as it is now on by default.
For full functionality, this still requires setting answerOnBridge in your TwiML. However, even without answerOnBridge
, the Call
will go through the new ringing
state briefly before transitioning to open
. When answerOnBridge
is enabled, the ringing
state will begin when the recipient's phone begins ringing, and transition to open
when they have answered and media is established.
This event is no longer raised in response to a local call.ignore()
. Instead, it will only be raised when the remote end has canceled 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;
This functionality has been moved to device.connect and call.accept.
1-codecPreferences?: Connection.Codec[];2+codecPreferences?: Call.Codec[];
The functionality of this option remains the same, but the type has changed to reflect the Call
class rename.
-debug?: boolean;
This functionality is now covered by the logLevel
option.
-enableIceRestart?: boolean;
This functionality is now enabled by default.
-fakeLocalDTMF?: boolean;
This functionality is now enabled 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
used to provide in a standardized way.
-region?: string;
Connecting by region name is deprecated. Please use edge
.
-rtcConfiguration?: RTCConfiguration;
This functionality has been moved to device.connect and call.accept.
+maxCallSignalingTimeoutMs?: number;
This parameter enables the new Signaling Reconnection feature.
+RTCPeerConnection?: any;
This parameter enables VDI support.
-warnings?: boolean;
This functionality is now covered by the logLevel
option.
+tokenRefreshMs?: number;
This parameter adjusts the event timing of the tokenWillExpire
event.
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;
The device
object will no longer emit a cancel event for canceled incoming calls. Instead, attach a listener to the Call.Event.Cancel event.
-connectEvent(connection: Connection): void;
The device
object will no longer emit a connect
event when an outgoing call is established. Instead, use the return value from device.connect.
+destroyedEvent(): void;
New API. Raised when the Device has been destroyed.
-disconnectEvent(connection: Connection): void;
This functionality is now provided by Call.Event.Disconnect.
1-errorEvent(connection: Connection): void;2+errorEvent(error: TwilioError, call?: Call): void;
The listener signature for this event has now changed. It will only emit a call as the second parameter when the error is call related, otherwise signaling errors are surfaced as the first parameter to this event.
1-incomingEvent(connection: Connection): void;2+incomingEvent(call: Call): void;
The functionality of this event has not changed, only the names of the parameters as the Connection
class has been renamed to Call
.
1-offlineEvent(device: Device): void;2+unregisteredEvent(): void;
This event has been renamed to Device.Event.Unregistered.
1-readyEvent(device: Device): void;2+registeredEvent(): void;
This event has been renamed to Device.Event.Registered.
+registeringEvent(): void;
New API. Raised when the Device has started the registration process, in effect after Device.register
has been invoked.
+tokenWillExpireEvent(device: Device): void;
New API. Raised when the token passed to the Device is about to expire. The time interval of this event and when the token will actually expire is configurable, 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;
The application code should observe the registration status of the Device, either through the registration events or Device.state
.
-readonly sounds: Partial<Record<Device.SoundName, (value?: boolean) => void>> = {};
Use 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;
A Device
can no longer be constructed without a token.
-activeConnection(): Connection | null | undefined;
The application code should keep track of all calls made or received.
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;
Connecting by region is deprecated. See Device.edge.
-setup(token: string, options: Device.Options = {}): this;
The Device
is now lazily set up when making an outgoing call or registering for incoming calls.
1-status(): Device.Status;2+get state(): Device.State;
Renamed. See device.state.
+get home(): string | null;
New API.
+get identity(): string | null;
New API.
+get isBusy(): boolean;
New API.
1-registerPresence(): this;2+async register(): Promise<void>;
Registration is an asynchronous action and the API now surfaces that with a Promise.
1-unregisterPresence(): this;2+async unregister(): Promise<void>;
Unregistration is an asynchronous action and the API now surfaces that with a Promise.
+updateOptions(options: Device.Options = {}): void;
New API to update the options of a device after the device has been constructed.
This class has been renamed 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;
The type annotation of this property has been changed to reflect the class name change.
1-get direction(): Connection.CallDirection;2+get direction(): Call.CallDirection;
The type annotation of the return value has been changed to reflect the class name change.
-mediaStream: IPeerConnection;
Private class member, removed from public API. Instead, use the following APIs to get the MediaStream
objects associated with a call.
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;
Setting event handlers is now removed. Please use Call.on
or Call.addListener
.
1-accept(audioConstraints?: MediaTrackConstraints | boolean, rtcConfiguration?: RTCConfiguration): void;2+accept(options?: Call.AcceptOptions);
Call options have been consolidated 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>;
The functionality of this API remains intact. The method parameters have been renamed to reflect the Call
class name change.
1-status(): Connection.State;2+status(): Call.State;
The type of the return value has been renamed to reflect the Call
class name change.
-unmute(): void;
This deprecated API has been removed. Please use the following for the same effect.
1const call = device.connect();2...3call.mute(false); // unmutes the call