Receive Voice Call Events for a Call In Progress with Ruby on Rails
Published on May 20, 2021

This is the second article in a series of "Getting Started with Nexmo APIs and Ruby on Rails" tutorials. It continues the "Getting Started with Nexmo SMS and Ruby on Rails" series.

In our previous tutorial I showed you how to make a text-to-speech call using the Nexmo API and the Nexmo Ruby gem in a Rails application. What we didn't looked at though is how to know when a call has connected or completed. In this tutorial, we will look at how we can listen for call events from Nexmo to update the status of a call in our application.

View the source code on GitHub.

Prerequisites

To follow this tutorial, I assume you have:

  • a basic understanding of Ruby and Rails

  • Rails installed on your machine

  • NPM installed for the purpose of our CLI

  • followed our previous tutorial on Making a text-to-speech call with Ruby on Rails

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.

What Does "Connected" Mean?

When you make a successful Voice Call request to Nexmo, the API returns a status for your call. Often this will be the initial state of started. Next, Nexmo will route your call and start ringing the phone of the recipient. When that happens we can notify your Rails application of the change in status using a Call Event Webhook.

To receive this webhook in your application, you will need to set up a webhook endpoint, telling Nexmo where to forward these receipts.

Set the Webhook Endpoint with Nexmo

To receive a webhook we need two things. First, we need to set up our server so that Nexmo can make an HTTP call to it. If you are developing on a local machine, this might be hard, which is where tools like Ngrok come in. I won't go too much into detail, but with Ngrok you can make your local Rails server available to the outside world within seconds. If you'd like to read more about using ngrok, check out this article detailing how to use an ngrok tunnel.

# 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

With this in place, you can set up this URL as your event_url webhook address on your Nexmo Application. Lucky for us, we already did this when we created the Nexmo Application in the previous tutorial.

$ nexmo app:create "My Voice App" http://abc123.ngrok.io/inbound_calls http://abc123.ngrok.io/call_events --keyfile private.key --answer_method POST --event_method POST Application created: aaaaaaaa-bbbb-cccc-dddd-0123456789ab Private Key saved to: private.key

If you need to change the URLs somehow, you can do so easily using a pretty similar command.

$ nexmo app:update aaaaaaaa-bbbb-cccc-dddd-0123456789ab "My Voice App" http://abc123.ngrok.io/inbound_calls http://abc123.ngrok.io/call_events --answer_method POST --event_method POST Application updated

Handle a Call Event WebHook

The hard part is done at this point, really. When a call has been initiated Nexmo will notify your application of any changes in the call by sending a webhook. A typical payload will look something like this:

{
  "uuid": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
  "conversation_uuid": "CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
  "status": "ringing",
  "direction": "outbound"
}

We can extend the example from our previous tutorial and update the call record we stored then with the new status.

# app/controllers/call_events_controller.rb
class CallEventsController < ApplicationController
  # We disable CSRF for this webhook call
  skip_before_action :verify_authenticity_token

  def create
    if params[:uuid]
      Call.where(uuid: params[:uuid])
          .first_or_create
          .update(
            status: params[:status],
            conversation_uuid: params[:conversation_uuid]
          )
    end

    head :ok
  end
end

In this example, we find the call record with the uuid provided, and then update its status with the given status, in this case "ringing".

Start a Call and Receive a Call Event

Now we can use our "Make a call" form by navigating to http://abc123.ngrok.io/outbound_calls (your ngrok URL will be different). You can check out how we built this form in the first article of this series, "Make an Outbound Text-to-Speech Phone Call."

When the call event is sent, we’ll see a log of it in our Rails console.

Started POST "/call_events" for 192.0.2.0 at 2020-01-01 12:00:00 -0500 Parameters: { "conversation_uuid"=>"CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab", "status"=>"ringing", "direction"=>"outbound"} Call Load (0.3ms) SELECT "calls".* FROM "calls" WHERE "calls"."uuid" = ? ORDER BY "calls"."id" ASC LIMIT ? [["uuid", "aaaaaaaa-bbbb-cccc-dddd-0123456789ab"], ["LIMIT", 1]] Processing by CallEventsController#create as HTML (0.0ms) begin transaction Parameters: {"uuid"=>"aaaaaaaa-bbbb-cccc-dddd-0123456789ab", "conversation_uuid"=>"CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab", "status"=>"started", "direction"=>"outbound"} SQL (0.3ms) UPDATE "calls" SET "status" = ?, "conversation_uuid" = ?, "is_inbound" = ?, "updated_at" = ? WHERE "calls"."id" = ? [["status", "ringing"], ["conversation_uuid", "CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab"], ["is_inbound", "f"], ["updated_at", "2020-01-01 12:00:00"], ["id", 6]] Call Load (0.1ms) SELECT "calls".* FROM "calls" WHERE "calls"."uuid" = ? ORDER BY "calls"."id" ASC LIMIT ? [["uuid", "aaaaaaaa-bbbb-cccc-dddd-0123456789ab"], ["LIMIT", 1]] (0.7ms) commit transaction (0.0ms) begin transaction Completed 200 OK in 7ms (ActiveRecord: 1.3ms)

To Sum Things Up

That's it for this tutorial. We've set up our Rails application to receive webhooks, informed Nexmo where to find our server, and processed an incoming webhook with a Delivery Receipt.

You can view the code used in this tutorial on GitHub.

Next Steps

In the next tutorial, we will look at receiving inbound voice calls into our application.

Chris GuzmanVonage Alumni

Chris is a Developer Advocate at Nexmo where he helps developers use their global communications platform. When he’s not at conferences you can find him roaming the world.

Ready to start building?

Experience seamless connectivity, real-time messaging, and crystal-clear voice and video calls-all at your fingertips.