Call Monitoring with Node.js, Express and Twilio Call Progress Events

September 14, 2015
Written by
Sam Agnew
Twilion

Call-Progress-Events-Blog-Post

Call progress events are a really useful tool if you ever need to track the state of phone calls an app you built makes with the Twilio Voice API. Let’s say you are building a dashboard to manage the huge influx of calls that your heavy metal themed, over the phone radio app makes to listeners. By providing a status callback to your web app you can track the state of a voice call from when it is initiated to when it is completed by receiving requests in real-time whenever a call’s state changes.

In this post we will be going through the basics of how to set up a web app in Node.js using the Express framework to receive HTTP requests from Twilio whenever the status of a phone call changes.

Getting started

In order for everything to run correctly, you are going to need to have have Node.js and npm installed. At the time of writing this blog post, I have the brand new Node v4.0 and npm v2.14.2 installed. Node 4.0 allows us to use some newer ES6 features directly without having to transpile your code with something like Babel. You will also need to create a Twilio account and purchase a phone number with Voice capabilities:

buy-a-twilio-number.gif

Now let’s initialize an app. Navigate to the directory you want to start this project in and run:

npm init

This will generate a package.json file that will contain all of the information about our project. You can totally breeze through the prompts if you are not interested in customizing this information. With that taken care of we can get to installing the dependencies that we’ll need for our Node app.

Let’s grab the Twilio (3.x) Node module:

npm install twilio --save

When we send out phone calls we will need to provide a URL for Twilio to send HTTP requests to when progress events occur. We will build a server side application with the Express web framework for Node to do this:

npm install express --save

In order to parse the requests that we receive from Twilio we will need to install the BodyParser middleware for Express:

npm install body-parser --save

Receiving call progress events with Express

Now we are ready to jump into some code. In order to receive updates from Twilio on the status of our phone calls we need to set up an Express server for handling these requests.

When the state of one of our phone calls is updated, we will receive a request similar to this one with these POST parameters:

{
  ApiVersion: '2010-04-01',
  Called: 'YOUR_PHONE_NUMBER',
  Caller: 'YOUR_TWILIO_NUMBER',
  SequenceNumber: '2',
  CallStatus: 'in-progress',
  From: 'YOUR_TWILIO_NUMBER',
  CallSid: 'IDENTIFIER_FOR_THIS_PHONE_CALL',
  To: 'YOUR_PHONE_NUMBER',
  Direction: 'outbound-api',
  Timestamp: 'Fri, 11 Sep 2015 16:18:42  0000',
  AccountSid: 'YOUR_ACCOUNT_SID',
  CallbackSource: 'call-progress-events'
}

Let’s get started with a barebones Express app to handle this request and log the results to the console. Fire up your favorite text editor, open a file called index.js and try the following code:

"use strict";

const express = require('express');
const bodyParser = require('body-parser');
const app = express();

// Run server to listen on port 3000.
const server = app.listen(3000, () => {
  console.log('listening on *:3000');
});

app.use(bodyParser.urlencoded({ extended: false } ));

// Set Express routes.
app.post('/events', (req, res) => {
  let to = req.body.to;
  let fromNumber = req.body.from;
  let callStatus = req.body.CallStatus;
  let callSid = req.body.callSid;

console.log(to, fromNumber, callStatus, callSid);
  res.send('Event received');
});

Before we can test to see if we can log the state of a phone call we first need to have a phone call to log. So let’s add another route to our server that will generate some TwiML to tell our phone call how to proceed. Let’s just have it say “Call progress events are rad” in a robot voice. Open up your index.js file again and add another route, this time using the Twilio Node library:


"use strict";

const express = require('express');
const bodyParser = require('body-parser');
const twilio = require('twilio');
const app = express();

// Run server to listen on port 3000.
const server = app.listen(3000, () => {
  console.log('listening on *:3000');
});

app.use(bodyParser.urlencoded({ extended: false } ));

// Set Express routes.
app.post('/events', (req, res) => {
  let to = req.body.to;
  let fromNumber = req.body.from;
  let callStatus = req.body.CallStatus;
  let callSid = req.body.callSid;

console.log(to, fromNumber, callStatus, callSid);
  res.send('Event received');
});

app.post('/voice', (req, res) => {
  // Generate a TwiML response
  let twiml = new twilio.twiml.VoiceResponse();
  // Talk in a robot voice over the phone.
  twiml.say('Call progress events are rad');
  // Set the response type as XML.
  res.header('Content-Type', 'text/xml');
  // Send the TwiML as the response.
  res.send(twiml.toString());
});

In order for Twilio to reach our application to alert us when a call’s state changes we need to expose our server to the Internet. We can do this using ngrok. My buddy Kevin wrote a great tutorial on how to get started with ngrok. Once you have that set up, let’s have ngrok listen to port 3000:

ngrok http 3000

You should see a screen that looks like this with a generated link that we can visit to access our Express app:

seouod9NcjVT7kO5DVp0glEE5Lkm46-fuhBM0YmHn1fdaR-6sn8rZTJT3klLJajaMSBO8O8yoKREyiYX_i7OEbxRvR6x8iSXn9xXk8oantsPrn3ATFYlu9EV51bCCuth6PTjYYQF

We’re almost ready to see call progress events in action, but first we need to set a status callback URL in the settings for your Twilio number. Head to your account dashboard and locate the settings for the phone number you want to use.

Using your new ngrok URL to access your Express server, make sure you set your voice request url to point to your “/voice” route and your status callback to send requests to your “/events” route. Now Twilio will make an HTTP request to “/voice” whenever you receive a phone call, and will send a request to “/events” whenever a voice call is completed.

Now run your server:

node index.js

And now we can make a phone call to our new Twilio number and see our console print the data we receive when the call is completed:

EndCall.gif

Making outgoing calls

That was awesome but this feature has existed for a while. What’s cool about the new call progress events is that we can now specify which events we want to listen for whenever we make a voice call with the REST API. Instead of just knowing when a call is completed, we can tell when it is ringing or when someone answers the phone.

Let’s demonstrate this by throwing a quick Node script together to make outgoing calls using the Twilio REST API that will use our Express app to monitor their status. Open up a new file called makeCall.js and try this code out:

"use strict";

const twilio = require('twilio');
const client = new twilio();
client.calls.create({
  url: '*ngrok url to your /voice route*',
  to: '*your phone number*',
  from: '*your Twilio number*',
  statusCallback: '*ngrok url to your /events route*',
  statusCallbackMethod: 'POST',
  statusCallbackEvent: ['initiated', 'ringing', 'answered', 'completed'],
}, (err, call) => {
  if(err) { console.log(err); return err; }
  process.stdout.write(call.sid);
});

This is all the code we need to make phone calls, but we still need to authenticate with Twilio. Head over to your Twilio account dashboard and grab your Account SID and Auth Token. Store them in environment variables like so:

export TWILIO_ACCOUNT_SID='your_account_sid_here'
export TWILIO_AUTH_TOKEN='your_auth_token_here'

No need to add these to your code, because upon initialization of the REST client object, the Twilio Node module checks to see if these environment variables exist. Don’t forget to replace the values in that code before you run it. Replace the url arguments with the same ones you used on your Twilio dashboard. Head to your terminal again and run:

node index.js

Now with your index.js server running again, try opening another terminal window and running our code to send a phone call to yourself:

node makeCall.js

Watch as your server receives the status of the call as it changes:

CallProgressEvents.gif

Moving forward

You’re now equipped to begin tracking the status of calls that you make with the Twilio REST API. Once you receive the request containing the call status, you can do whatever you want with that information. With some modifications, the code that we wrote in this post could act as a back end to a dashboard that monitors voice calls in real time. Some next steps could be:

I’d love to see what you build with this. Feel free to reach out if you have any questions or if you want to show off how you used call progress events in your Twilio app.