Migrating Your Node.js Application from Twilio SDK 2.x to 3.x

Deprecation notice: New functionality will only be added to the new library (Node Helper Library 3.x). The old library (2.x) will be officially supported until 8/31/2017. After that day, Twilio will stop providing bug fixes and Support might ask you to upgrade before debugging issues.

The Twilio Node Helper Library has undergone a number of changes from version 2.x to 3.x - we'll break down the major changes here to make migrating to the new version as painless as possible. If you're integrating Twilio in your Node app for the first time, you can skip straight to the install page.

Importing the Library

In twilio-node 2.x, you would have to make a new instance of each client you used:

var Twilio = require('twilio');
var accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
var authToken = 'your_auth_token';

var ipmClient = new Twilio.IpMessagingClient(accountSid, authToken);
var lookupsClient = new Twilio.LookupsClient(accountSid, authToken);

In twilio-node 3.x, there is now only one object to import and initialize:

var accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
var authToken = 'your_auth_token';

var Twilio = require('twilio');
var twilio = new Twilio(accountSid, authToken);

Accessing Resources

// Old
client.messages('SM123').get(function(err, message) {
  console.log(message.sid); //=> SM123
});

// New
client.api.v2010.account.messages('SM123').fetch(function(err, message) {
  console.log(message.sid); //=> SM123
});
// (or)
client.messages('SM123').fetch(function(err, message) {
  console.log(message.sid); //=> SM123
});

The new library makes Twilio API subdomains (Lookups, Trunking, Monitor, etc) first-class citizens. You can now also pin your interactions to the Twilio API to specific versions of that API (the .v2010. ensures we always talk to the 2010-04-01 version of the API). This allows you to migrate portions of your code to future versions independently without having to do a full upgrade when you update the library.

You'll also notice that get has been updated to fetch. We've updated the library to use fetch, create, update, and remove to be more explicit about what action you are taking.

Promises

You may also use promises to interact with twilio-node:

var promise = twilio.messages('SM123').fetch();
promise.then(function(message) {
  console.log(message.sid);
});

Listing Resources

There are now 2 ways to get a list of resources: list and each.

  • list fetches the entire collection of resources and resolves to an array that contains the resources' instances.
var promise = twilio.messages.list();
promise.then(function(messages) {
  console.log(messages); //=> [MessageInstance, MessageInstance, MessageInstance, ...]
});
  • each will page through the list of resources and call the callback function that you passed in with each instance and a done function. To stop iteration at any point, call the done function.
twilio.messages.each(function(message) {
  console.log(message.sid); //=> 'SM123'
});

var i = 0;
twilio.messages.each(function(message, done) {
  console.log(message.sid);

  i++;

  // break after 10 messages
  if (i >= 10) {
    done();
  }
});

Paging

One of the biggest advantages of twilio-node 3.x is that it automatically handles paging for you! In both list and each, you can specify the maximum number of instances to grab (limit), and the page size (pageSize). The library will take care of everything else.

twilio.messages.each({limit: 10}, function(message) {
  console.log(message.sid);
});

var promise = twilio.messages.list();
promise.then(function(messages) {
  console.log(messages.length); //=> 125
});

promise = twilio.messages.list({
  limit: 100
});
promise.then(function(messages) {
  console.log(messages.length); //=> 100
});

Configurable HTTP Client

You can now plug your own HTTP client into the Twilio client! Just pass a client that conforms to the RequestClient interface and pass it in when you initialize Twilio.

var accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
var authToken = 'your_auth_token';

var client = new CustomClient();
var twilio = new Twilio(accountSid, authToken, client);

TwiML

Now, you have a specific constructor for each TwiML type: Voice and Message.

// Old
var TwimlResponse = require('twilio').TwimlResponse;
var twiml = new TwimlResponse();

// New
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var messagingResponse = new MessagingResponse();

var VoiceResponse = require('twilio').twiml.VoiceResponse;
var voiceResponse = new VoiceResponse();

For a basic VoiceResponse, only the order of the parameters changed:

Loading Code Samples...
Language
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.say('Hola Mundo!', { voice: 'woman', language: 'es' });

console.log(twiml.toString());
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
response.say(
  {
    voice: 'woman',
    language: 'es',
  },
  'Hola Mundo!'
);

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say voice="woman" language="es">Hola Mundo!</Say>
</Response>
Using a specific language as an attribute in a Say verb

Nested verbs don't need to be defined inside a callback anymore, as you can see below.

Loading Code Samples...
Language
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.gather({
  input: 'speech',
  action: '/completed'
}, function() {
  this.say('Welcome to Twilio, please tell us why you\'re calling')
});

console.log(twiml.toString());
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    input: 'speech',
    action: '/completed'
});
gather.say('Welcome to Twilio, please tell us why you\'re calling');

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather action="/completed" input="speech">
        <Say>Welcome to Twilio, please tell us why you're calling</Say>
    </Gather>
</Response>
Speech Gather

The same applies for a basic MessagingResponse.

Loading Code Samples...
Language
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.message('', function() {
  this.body('Store Location: 123 Easy St.');
});

console.log(twiml.toString());
const MessagingResponse = require('twilio').twiml.MessagingResponse;

const response = new MessagingResponse();
const message = response.message();
message.body('Store Location: 123 Easy St.');

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        <Body>Store Location: 123 Easy St.</Body>
    </Message>
</Response>
Simple sending of SMS

And an example of a MessagingResponse with nested verbs:

Loading Code Samples...
Language
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.message('', function() {
  this.body('Hello Jenny');
  this.media('https://demo.twilio.com/owl.png');
});

console.log(twiml.toString());
const MessagingResponse = require('twilio').twiml.MessagingResponse;

const response = new MessagingResponse();
const message = response.message();
message.body('Hello Jenny');
message.media('https://demo.twilio.com/owl.png');

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        <Body>Hello Jenny</Body>
        <Media>https://demo.twilio.com/owl.png</Media>
    </Message>
</Response>
Sending of an Message with Media (MMS)

Capability Token

In the new version, there are specific constructors for each new capability.

var accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
var authToken = 'your_auth_token';

// Old
var capability = new twilio.Capability(accountSid, authToken);
capability.allowClientIncoming('Identity');
capability.allowClientOutgoing(TWILIO_TWIML_APP_SID);
var token = capability.generate();

// New
var ClientCapability = require('twilio').jwt.ClientCapability;
var capability = new ClientCapability({
  accountSid: accountSid,
  authToken: authToken
});
capability.addScope(new ClientCapability.IncomingClientScope('Identity'));
capability.addScope(new ClientCapability.OutgoingClientScope({
  applicationSid: config.twimlAppSid,
  clientName: identity
}));
var token = capability.toJwt();

Debugging API Requests

To assist with debugging, the library allows you to access the underlying request and response objects. This capability is built into the default HTTP client that ships with the library.

For example, you can retrieve the status code of the last response like so:

// Twilio Credentials
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';

// require the Twilio module and create a REST client
const client = require('twilio')(accountSid, authToken);

client.messages
  .create({
    to: '+14158675309',
    from: '+14258675310',
    body: 'Ahoy!',
  })
  .then(() => console.log(client.httpClient.lastResponse.statusCode));

Where to Find Help

All of the Quickstarts, Tutorials, and API Reference documentation will have example code in both the older 2.x library and the new 3.x library. There are hundreds of samples just waiting for you to copy, paste and modify.

The Twilio Node helper library is open source software. Please visit us on GitHub to view the source, open issues, or submit pull requests.


Finally, we are always ready to help. Just contact us directly for support.

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.say('Hola Mundo!', { voice: 'woman', language: 'es' });

console.log(twiml.toString());
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
response.say(
  {
    voice: 'woman',
    language: 'es',
  },
  'Hola Mundo!'
);

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say voice="woman" language="es">Hola Mundo!</Say>
</Response>
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.gather({
  input: 'speech',
  action: '/completed'
}, function() {
  this.say('Welcome to Twilio, please tell us why you\'re calling')
});

console.log(twiml.toString());
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    input: 'speech',
    action: '/completed'
});
gather.say('Welcome to Twilio, please tell us why you\'re calling');

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather action="/completed" input="speech">
        <Say>Welcome to Twilio, please tell us why you're calling</Say>
    </Gather>
</Response>
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.message('', function() {
  this.body('Store Location: 123 Easy St.');
});

console.log(twiml.toString());
const MessagingResponse = require('twilio').twiml.MessagingResponse;

const response = new MessagingResponse();
const message = response.message();
message.body('Store Location: 123 Easy St.');

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        <Body>Store Location: 123 Easy St.</Body>
    </Message>
</Response>
SDK Version:
  • 2.x
  • 3.x
Format:
  • TwiML
const twilio = require('twilio');

const twiml = new twilio.TwimlResponse();
twiml.message('', function() {
  this.body('Hello Jenny');
  this.media('https://demo.twilio.com/owl.png');
});

console.log(twiml.toString());
const MessagingResponse = require('twilio').twiml.MessagingResponse;

const response = new MessagingResponse();
const message = response.message();
message.body('Hello Jenny');
message.media('https://demo.twilio.com/owl.png');

console.log(response.toString());
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        <Body>Hello Jenny</Body>
        <Media>https://demo.twilio.com/owl.png</Media>
    </Message>
</Response>