Handle Keypad Input (DTMF) with PHP

Published August 10, 2018 by Martyn Davies

In this tutorial, we’re going to go through everything you need to know to set up a PHP application that can receive inbound calls and capture user input entered via the keypad.

By following this tutorial you will end up with a simple application that can be extended to include more complex, interactive elements and give you a head start building interactive menus for your callers.

The code for this tutorial can be found on GitHub.


TL;DR – You’ll need the following things:

Here’s the long version:

If you want to follow along then you’ll need a Nexmo account to get started, so sign up now if you don’t have one already.

Receiving a phone call with Nexmo is charged at €0.0045/min and you will have to rent a number for people to call. We’ll cover doing that later.

The example code uses the Slim framework for handling requests. We’ve chosen this because of its simplicity and readability but, if you’re familiar with PHP and would like to handle this in a different way, you are welcome to use something different. You’ll need to install Slim using Composer so make sure you have that set up as well.

The code you will create is expected to work with any version of PHP 5.6 or above.

Our recommended way of working with Nexmo, from an administration point of view, is to use our command line tool, Nexmo-CLI.

In order to make the code on our local machine accessible to the outside world, we’re going to use ngrok, so ensure you have that installed as well.

Receiving the inbound call

When Nexmo receives a call on a number you have rented, an HTTP request is made to a URL (a ‘webhook’, that you specify) that contains all of the information needed to receive and respond to the call. This is commonly called the answer URL.

We’ll also be collecting DTMF input from our callers. DTMF stands for Dual Tone Multifrequency and, in the case of this tutorial, occurs when a user presses a number on their keypad.

Whenever a DTMF input is collected from the user, this is sent to a different URL in your app which we’ll also have to specify.

Next, we will begin by writing the code needed to handle these requests.

To install Slim using Composer run the following command inside the project folder in your terminal:

Next up, in your main folder, create a new file called index.php and add the following code to it:

With this code we’re setting up a new URL in our app, webhooks/answer, that will respond to any incoming calls to your phone number with the directions provided in the $ncco array.

The $ncco will perform these steps once the call is answered:

  1. Read out the text ‘Please enter a digit’
  2. Capture the digit entered by the caller
  3. Pass input that was captured over to the route that handles the input, /webhooks/dtmf

Handle the user input

Let’s add the code to handle incoming DTMF in index.php:

After the code we entered above, and before $app->run(); add the following:

This route’s function will perform the following steps:

  1. Receive the input from /webhooks/answer
  2. Parse the request body into a variable, $params
  3. Create a new $ncco array that speaks back to the caller and tells them which number they pressed.

For reference, your final index.php file should look exactly like this one.

Now, you’re set up and ready to run the code, you can do that by entering the following command in your terminal:

This will start a server and route any traffic to http://localhost:3000 through to your index.php file.

Expose your app with ngrok

In order to allow Nexmo to make requests to your app, you need to expose the code running on your local machine to the world.

ngrok is our tool of choice for this, and we’ve provided a great introduction to the tool that you can read to get up to speed if you haven’t used it before.

Once you have ngrok installed, run ngrok http 3000 to expose your application to the internet. You’ll need to make a note of the ngrok URL generated as we’ll need to provide it to Nexmo in the next step (it’ll look something like http://45hfh5.ngrok.io).

Buy a number and create an app

With the code completed, and our app available to the world, we now need to get ourselves a phone number and link this code, that will be running locally, to it.

Let’s start by purchasing a number via the Nexmo CLI:

You can use a different country code if you want to. Make a note of the number you purchase, as we’ll need it for the next step.

We now need to create a Nexmo application, which is a container for all the settings required for your application. In this case, we need to tell Nexmo which URL to make a request to when an incoming call is received (the answer_url), and where to send any event information about the call (the event_url, you can find out more about events in the Call Flow documentation).

Use the Nexmo CLI to create your application making sure you substitute <your_ngrok_url> with your own generated URL that ngrok gave you earlier:

The response you’ll get back will contain a huge private key output and, above that, an application ID. You can ignore the private key as it isn’t necessary for handling inbound calls.

Make a note of the application ID (which looks like this: e7a25242-77a1-42cd-a32e-09febcb375f4) and then link it to your new number:

That’s everything needed to associate the code above with your Nexmo app and number. You can test it out by dialling the number you purchased and following the steps that are magically spoken to you on the other end of the line!


In just thirty lines of PHP, you now have an app that can receive an incoming call and collect DTMF input from the caller. How could you expand this from here?

If you want to learn more about what is possible with inbound voice calls, and how you can make them more complex by adding features such as recording audio, you can learn more about how to operate your NCCOs in the NCCO reference.

As always, if you have any questions about this post feel free to email devrel@nexmo.com or join the Nexmo community Slack channel, where we’re waiting and ready to help.

Leave a Reply

Your email address will not be published.

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

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 privacy@nexmo.com.