This is the first article in a series of "Getting Started with Vonage Voice APIs and Ruby on Rails" tutorials. It continues the "Getting Started with Vonage SMS and Ruby on Rails" series.
With the help of the Vonage Voice API you can make worldwide outbound and inbound calls in 23 languages with varieties of voices and accents. All you need is your virtual phone number, the Ruby Gem, and a few lines of code.
In this tutorial—and the ones to follow—I will take you through some real-life examples of how to integrate Vonage into your Rails application. I'll explain how to set up the basics, and then we will write some code together to properly integrate Vonage and start making and receiving phone calls. Let's get started!
View the source code on GitHub
Prerequisites
For this tutorial I assume you will have:
A basic understanding of Ruby and Rails
Rails installed on your machine
NPM installed for the purpose of our CLI
DT API Account
To complete this tutorial, you will need a DT API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the DT API Dashboard.
This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.
Get your API keys
In this tutorial, we will use this as our main way of preparing our application.
The Vonage CLI is a Node module and therefore does require NPM to have been installed.
$ npm install vonage-cli -g $ vonage config:set --apiKey=YOUR-API-KEY --apiSecret=YOUR-API-SECRET
With this in place, we can run the following commands to find and purchase a Voice-enabled number:
Alternatively, head over to the Numbers page on the Vonage Dashboard and purchase a number via the web interface.
Create a Vonage Application
In our previous series of SMS tutorials, we were able to configure a phone number directly with an endpoint. In this tutorial, we will be using the new, more powerful and more secure Vonage Applications API for configuring our callbacks.
Diagram: Using the Voice API to call your mobile phone
Our first step is to create an application by providing an application name and some callback URLs. Don't worry about these URLs yet as we'll be updating them later in a future tutorial.
$ vonage apps:create "My Voice App" --voice_answer_url=http://example.com/inbound_calls --voice_event_url=http://example.com/call_events --voice_answer_http=POST --voice_event_http=POST Application created: aaaaaaaa-bbbb-cccc-dddd-0123456789ab
This will create a Vonage Application with UUID aaaaaaaa-bbbb-cccc-dddd-0123456789ab
and a private key stored in a file called private.key
. Make sure you don't lose this key; Vonage does not keep a copy and it's used to sign your API calls.
Install the Vonage Ruby Gem
The easiest way to interact with the Vonage Voice API with Ruby is using the vonage
gem.
This gem conveniently provides an easy wrapper around the Vonage REST API. To initialize it, we will need to pass it the Application UUID and private key that we created earlier. Create a file named make-call.rb
with the following contents, replacing application_id
with your application ID:
require "vonage"
vonage = Vonage::Client.new(
application_id: 'aaaaaaaa-bbbb-cccc-dddd-0123456789ab',
private_key: File.read('private.key')
)
Make a voice call with Ruby
With our API client in place, making the first voice call is easy; we simply call the create_call
method on the initialized client and pass in a configuration specifying who to call to
, what number to call from
, and an answer_url
that will return a Vonage Call Control Object (NCCO) containing the actions to play back to the receiver. To get us up and running quickly, we'll provide a predefined NCCO URL that's hosted on Github.
Add the following code to make-call.rb
:
vonage.create_call({
to: [
{
type: 'phone',
number: '14155550101'
}
],
from: {
type: 'phone',
number: '14155550102'
},
answer_url: [
'https://nexmo-community.github.io/ncco-examples/first_call_talk.json'
]
})
This will play back a simple voice message to the recipient as specified by first_call_talk.json
. Run ruby make-call.rb
now, and wait for a call from Vonage that will read you a simple voice message.
There are a lot more parameters that we could pass into this method. Have a look at the reference documentation for full details.
Make an outbound call from Ruby on Rails
In a Rails application, we'd probably have a Model for Calls where we can store the to
, from
, and maybe the text
to play to the recipient before making the Vonage API call. For this example you could create a migration for a Call like so:
$ rails generate migration CreateCalls to:string from:string text:text uuid:string status:string
In my demo application, I've also whipped up a simple form for the Call model.
localhost:3000/outbound_calls
When the form is submitted, we store the Call record and then make the call. In a real application, you might use a background queue for this, though in this case, we will just pass the Call record to a new method.
# config/routes.rb
Rails.application.routes.draw do
resources :outbound_calls, only: [:index, :create, :show]
end
# app/controllers/outbound_calls_controller.rb
class OutboundCallsController < ApplicationController
def create
@call = Call.new(safe_params)
if @call.save
make @call
redirect_to :outbound_calls, notice: 'Call initiated'
else
flash[:alert] = 'Something went wrong'
render :index
end
end
private
def safe_params
params.require(:call).permit(:to, :from, :text)
end
end
Next, we can pass the call information to the Vonage API.
# app/controllers/outbound_calls_controller.rb
def make call
response = vonage.create_call({
to: [
{
type: 'phone',
number: call.to
}
],
from: {
type: 'phone',
number: call.from
},
answer_url: [
outbound_call_url(call)
]
})
call.update_attributes(
uuid: response['uuid'],
status: response['status']
) if response['status'] && response['uuid']
end
The response object will contain a uuid
if the call was initiated successfully. We can store the uuid
and the current call status
on the Call record. The uuid
can be used to track the status of the Call, specifically when a Call Update comes in via a webhook.
Provide an NCCO to play back text
When we called the create_call
method we used outbound_call_url(call)
in the answer_url
array. That answer_url
needs to be available to the public internet so that it is reachable by the Vonage APIs. You can do so by using ngrok. For more detailed instructions see Aaron's post explaining how to connect your local development server to the Vonage API using an ngrok tunnel.
After setting up ngrok like so:
# forwarding port 3000 to an externally accessible URL $ ngrok http 3000
Session Status online Account Cristiano Betta Version 2.2.4 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://abc123.ngrok.io -> localhost:3000 Forwarding https://abc123.ngrok.io -> localhost:3000
You will have an answer_url
that looks something like this:
http://abc123.ngrok.io/outbound_call/123
When the call is initiated, Vonage will make an HTTP request to that endpoint expecting an NCCO object with the actions to perform. In our case, we want to simply play back the text
we specified on the Call object.
# app/controllers/outbound_calls_controller.rb
def show
call = Call.find(params[:id])
render json: [
{
"action": "talk",
"voiceName": "Russell",
"text": call.text
}
]
end
Now go ahead, submit the form and within a few seconds you will receive a call playing back the message you just specified! There are many more actions you can specify in the NCCO. Have a play with them if you want.
To sum things up
That's it for this tutorial. We've successfully:
Created a Vonage account.
Installed the CLI.
Bought a number and created a Vonage Application.
Installed and initialized the Ruby gem.
Created a deep integration into our Rails application.
You can view the [code used in this tutorial](https://github.com/Nexmo/nexmo-rails-quickstart/blob/master/app/controllers/outbound_calls_controller.rb) on GitHub.
Next steps
In the next tutorials, we will look at receiving Call Events for calls we've created, and how to receive inbound calls as well.