Make Outbound calls to a phone using Twilio and Rails

Vipul

By Vipul

on September 29, 2014

In this blog post we will see how to make outbound phone calls from the browser to a phone using Twilio . We will make use of the Twilio-JS library and Twilio-Ruby gem.

The Rails App we will be creating, is based on the Twilio Client Quick-start tutorial. That Twilio tutorial makes use of Sinatra. We will see how we can achieve this in a Rails application.

Step 1 - Setup Twilio Credentials and TwiML App

We need to setup twilio credentials. We can find account ID and auth token from our account information.

When the call is made using browser then the phone that is receiving the call has to see a number from which the call is coming. So now we need to setup a Twilio verified number. This number will be used to place the outgoing calls from. How to setup a verified number can be found here.

When our app make a call from the browser using twilio-js client, Twilio first creates a new call connection from our Browser to Twilio. It then sends a request back to our server to get information about what to do next. We can respond by asking twilio to call a number, say something to the person after a call is connected, record a call etc.

Sending of this instructions is controlled by setting up a TwiML application. This application provides information about the end point on our server, where twilio should send the request to fetch instructions. TwiML is a set of instructions, that we can use to tell Twilio what to do in different cases like when an outbound phone call is made or when an inbound SMS message is received.

Given below is an example that will say a short message How are you today? in a call.

1
2<?xml version="1.0" encoding="UTF-8"?>
3<Response>
4    <Say voice="woman">How are you today?</Say>
5</Response>
6

The TwiML app can be created here. Once the app is configured then we will get appsid.

We need to configure following information in our Rails Application:

1twilio:
2  verified_number: <%= ENV['TWILIO_VERIFIED_NUMBER']%>
3  account_sid: <%= ENV['TWILIO_ACCOUNT_SID'] %>
4  auth_token: <%= ENV['TWILIO_AUTH_TOKEN'] %>
5  call_app_sid: <%= ENV['TWILIO_CALL_APP_SID'] %>

Step 2 - Generate capability token to be used by twilio-js

After we have the config setup, we will proceed to create the capability token. This token will be generated using the ruby gem, and passed to the javascript SDK. The token helps the twilio-js client determine, what permissions the application has like making calls, accepting calls, sending SMS, etc.

We define a TwilioTokenGeneratorService for this purpose.

1
2class TwilioTokenGeneratorService
3
4  def process
5    capability = twilio_capability()
6    capability.generate
7  end
8
9  private
10
11  def twilio_capability
12    capability ||= Twilio::Util::Capability.new Settings.twilio.account_sid, Settings.twilio.auth_token
13    capability.allow_client_outgoing Settings.twilio.call_app_sid
14    capability
15  end
16
17end
18

As you can see, we first define a new Twilio::Util::Capability instance and pass credentials to it. We then call allow_client_outgoing method and pass the client Sid to it. This is the identifier for the TwiML application we have previously created on Twilio. Calling allow_client_outgoing gives permission to the client to make outbound calls from Twilio. Finally we call the generate method to create a token from the capability object.

Step 3 - Define view elements and pass token to it

The generated token will now be passed to the Twilio JS client for connecting with Twilio. In our App we define CallsController, and index action in this controller. This action takes care of setting the capability token. Our index view consists of two buttons- to place and hangup a call, a number input field, call logs, and data field to pass capability token to the javascript bindings. We import the Twilio-JS library in the view. The css styling being used is from the Twilio example.

1
2<div id="twilioToken" data-token="<%= @twilio_token %>"></div>
3
4<button id="caller" class="call">Call</button>
5<button id="hangup" class="hangup">Hangup</button>
6
7<input type="text" id="phoneNumber" placeholder="Enter a phone number to call"/>
8
9<div id="log">Loading pigeons...</div>
10
11<script type="text/javascript" src="//static.twilio.com/libs/twiliojs/1.2/twilio.min.js"></script>
12

Step 4 - Define coffeescript bindings to handle TwilioDevice connection to Twilio

Next we setup coffeescript bindings to handle initialization of TwilioDevice and making use of entered number to place calls Twilio. We are taking care of various events like connect, disconnect, ready, etc. on TwilioDevice instance. More information about TwilioDevice usage can be found here.

1
2class TwilioDevice
3  constructor: ->
4    @initTwilioDeviceBindings()
5    @initFormBindings()
6
7  initTwilioDeviceBindings: ->
8    twilio_token = $('#twilioToken').data('token')
9    twilio_device = Twilio.Device
10
11    # Create the Client with a Capability Token
12    twilio_device.setup(twilio_token, {debug: true});
13
14    #/* Let us know when the client is ready. */
15    twilio_device.ready ->
16      $("#log").text("Ready")
17
18    #/* Report any errors on the screen */
19    twilio_device.error (error) ->
20      $("#log").text("Error: " + error.message)
21
22    #/* Log a message when a call connects. */
23    twilio_device.connect (conn) ->
24      $("#log").text("Successfully established call")
25
26    #/* Log a message when a call disconnects. */
27    twilio_device.disconnect (conn) ->
28      $("#log").text("Call ended")
29
30  initFormBindings: ->
31    $('#caller').bind "click", (event) ->
32      params = {"phone_number": $('#phoneNumber').val()}
33      Twilio.Device.connect(params)
34
35    $('#hangup').bind "click", (event) ->
36      Twilio.Device.disconnectAll()
37
38$ ->
39  new TwilioDevice()
40

If we now load this page, we should be able to see our app saying its ready to take calls.

Step 5 - Define TwiML Response Generator Service

The final step before we place calls from our App is to handle callbacks from Twilio and return TwiML response. For this we are going to define TwilioCallTwiMLGeneratorService which takes care of generating this response. More information about how we need to define the response and individual fields can be found from Twilio's docs.

What we need to define is a response as below:

1
2<?xml version="1.0" encoding="UTF-8"?>
3<Response>
4  <Dial callerId="+15005550000">
5    <Number>+15005550001</Number>
6  </Dial>
7</Response>
8

We are making use of two elements here - Dial, which makes Twilio place a call using defined callerId value, as the number from which the call is made, which is displayed on the callee's phone. Note that this is the same verified number that we had specified before. Then we specify Number which is the number, to which we want to place the call to. This number is passed first by the javascript client to Twilio, and then back to our application by Twilio, which we use to generate the response as above.

We define our TwilioCallTwiMLGeneratorService to take in a phone number as parameter. It creates an instance of Twilio::TwiML::Response and tapping on this instance we provide Dial element with a :callerId value, and the Number to place the call to. We validate the number before passing it back, and return an error if the number is invalid.

1
2class TwilioCallTwiMLGeneratorService
3  attr_reader :phone_number
4  VALID_PHONE_NUMBER_REGEX = /^[\d\+\-\(\) ]+$/ # Matches valid phone numbers acceptable to Twilio
5
6  def initialize phone_number
7    @phone_number = phone_number
8  end
9
10  def process
11    Twilio::TwiML::Response.new do |r|
12      if VALID_PHONE_NUMBER_REGEX.match(phone_number)
13        r.Dial :callerId => Settings.twilio.verified_number do |d| # callerId is number from which call is made.
14          d.Number(CGI::escapeHTML phone_number) # The number to call
15        end
16      else
17        r.Error("Invalid number!")
18      end
19    end.text.strip
20  end
21
22end
23

Step 6 - Send TwiML response on Twilio callback

We are now set to define twilio's callback handler. This will be handled by the create_call action in CallsController. Twilio will be sending this endpoint a POST request along with some information specified here. We make use of phone_number being passed to us by Twilio and pass it along to the TwilioCallTwiMLGeneratorService, which return us with valid TwiML response. Since TwiML is a flavor of XML, we make using render xml to return the response.

1
2def create_call
3  response_to_twilio_callback = TwilioCallTwiMLGeneratorService.new(call_params[:phone_number]).process
4  render xml: response_to_twilio_callback
5end
6
7def call_params
8  params.permit(:phone_number)
9end
10

As create_call endpoint will be used by Twilio API, we need to skip authenticity token check for this action.

1class CallsController < ApplicationController
2  skip_before_action :verify_authenticity_token, only: [:create_call]
3end

Finally we need to specify the callback url in our TwiML App on Twilio. For testing this locally, we can make use of a service like https://ngrok.com/, to expose this endpoint.

Our service is now ready to place calls. The complete Rails application code that we have created can be found here.

Happy calling everyone!

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.