Text-to-Speech Voice Calls with PHP

Published October 20, 2017 by Michael Heap

For years, making and receiving phone calls in your code was tough to do (and usually involved writing some Java and plugging an old phone in to your laptop to serve as a gateway!). Fortunately, it’s not nearly as hard today thanks to services such as Nexmo.

Voice calls are a great communication method as they’re a lot more immediate than email or SMS—if you need to get a message to someone urgently, a phone call is the way to do it; a ringing phone is hard to ignore.

In this post, we’re going to build a small app that we can use to trigger an outbound phone call using our newly released PHP client.

The complete code for this post is available in our PHP building blocks repository on Github.


You’ll need PHP installed before working through this post. I’m running PHP 7.2, but the code here should work on PHP 5.6 and above. You’ll also need Composer available to install the Nexmo PHP client.

Next, you’ll need a Nexmo Account with some available credit (you get a few Euros free just for signing up). We’ll use this credit to make some outbound phone calls.

We’ll need a way to expose the app that we’re developing to the public so that Nexmo can communicate with it. We can do this using a tool such as ngrok. If you’re not familiar with the tool, there’s a fantastic ngrok introduction available on the Nexmo blog. For now, open a terminal and run ngrok http 8000. Make a note of your ngrok URL as you’ll need to replace https://example.com with it when configuring your Nexmo application.

Finally, if you don’t already have a Nexmo Voice application ready, you’ll need to create an application and purchase and link a number. The easiest way to do this is using the Nexmo CLI tool. Here’s the short version:

  • Install the Nexmo CLI tool by running npm install -g nexmo-cli
  • Create an application, replacing answer_url and event_url with your own endpoints by running nexmo app:create "Nexmo calls" https://example.com/answer/ https://example.com/event/ --keyfile private.key. Make a note of the application ID it returns
  • Purchase a number by running nexmo number:buy --country_code US --confirm. Make a note of the number purchased
  • Finally, link the number to your application by running nexmo link:app

Create your workspace

Let’s get our workspace set up so that we can start developing our application. We’re going to be using Lumen to receive call events from Nexmo and return instructions on how our calls should be handled. Let’s use composer to bootstrap a project.

This will create a folder called nexmo-calls that contains an empty Lumen project. Copy the private.key that was saved when creating an application into this folder. It should be at the same level as composer.json.

Next, we need to start the local PHP server so that we can make HTTP calls to our app. To do this, open a new terminal and run php -t public -S localhost:8000. Our application is now listening on port 8000 on our local machine, and is available via the internet thanks to the ngrok command we ran earlier.

At this point, we have a Lumen application bootstrapped, listening and exposed to the internet. This is all we need to do to start serving responses to Nexmo to instruct it how to handle our phone calls.

Creating your own NCCO

Nexmo phone calls are controlled using Nexmo Call Control Objects (or NCCOs). An NCCO defines a list of actions for the Nexmo system to follow when a call is handled. There are lots of different actions available, such as:

To start with, we’re going to generate a simple NCCO:

To do this, open up routes/web.php and add a new handler:

As Nexmo makes a GET request to our answer_url, we add a handler that matches these requests ($router->get('/answer')) and returns a JSON response (return response()->json()).

So long as we return JSON in the correct format, Nexmo knows how to handle the call. That’s really all there is to it! Save your changes then call the number you purchased to hear our text-to-speech message.

Making an outbound call

This is a good start, but we were aiming to make an outbound call, not just respond to incoming calls. Fortunately for us, we’ve already done most of the work. When we make an outbound call, Nexmo still makes a call to our answer_url to find out how to handle the call.

To trigger an outbound call, we need to make a POST request to the Nexmo API that contains to, from and answer_url along with some authentication information.

Whilst we could build that call by hand, the Nexmo PHP client makes it extremely easy. So let’s install it with Composer. Run the following in the same directory as your composer.json:

Once we have the Nexmo client installed, we can add a new endpoint that we’ll call to trigger a new outbound call. We’ll need our application ID and the private key we saved earlier to authenticate our API calls, and then we need to make a call to the Nexmo voice API. You’ll need to copy private.key into the same folder as your composer.json and replace APPLICATION_ID and YOUR_NEXMO_NUMBER with your own values. (Don’t forget to provide your own ngrok URL instead of example.com too!)

Once you’ve done that, make a GET request to /makeCall/ to trigger an outbound text to speech call via Nexmo.

Dynamic NCCOs

We’ve accomplished what we set out to do, but it’s a little boring. We broadcast out the same message every time we make a call. To make it dynamic we could read out the current time, but I have a better idea. Whenever we make an outbound call, we’ll make a request to the Chuck Norris Database and read out the response on our call.

To do this, we’ll use a lightweight HTTP library called Guzzle. To use Guzzle, we need to install it using Composer. Run the following in the same directory as your composer.json:

After we have Guzzle installed, we need to make a request to the Chuck Norris Database and use the response to populate our NCCO. We’re going to limit the search to nerdy jokes by default. Add the following to the top of your /answer handler:

This will return a random joke from the nerdy category. The next step is to update our NCCO to use the value from $apiResponse:

Now, any time Nexmo makes a request to our answer_url we’ll fetch a random joke from the Chuck Norris database and use that as our text to speech response. You can test that now by either making a phone call to your Nexmo number or by triggering an outbound call via the makeCall endpoint.

Congratulations! You just built a text to speech voice call system that can handle both inbound and outbound calls. Going forward you could customise the response based on who’s calling, the time of day or anything else you can think of.

What’s next?

So what’s next? You could extend your application into a voice-based critical alert system by looping through a list of contacts to broadcast calls out and have the recipients press a number to confirm receipt of your messages.

Leave a Reply

Your email address will not be published.

Get the latest posts from Vonage’s next-generation communications blog delivered to your inbox.

Select Your Subscription Edition

By signing up to our communications blog, you accept our privacy policy , which sets out how we use your data and the rights you have in respect of your data. You can opt out of receiving our updates by clicking the unsubscribe link in the email or by emailing us at [email protected].
By signing up to our communications blog, you accept our privacy policy , which sets out how we use your data and the rights you have in respect of your data. You can opt out of receiving our updates by clicking the unsubscribe link in the email or by emailing us at [email protected].