Text-to-Speech Voice Calls with PHP

Source: Vonage API Developer•

Text-to-Speech Voice Calls with PHP

Build a PHP application that handles inbound and outbound text-to-speech voice calls using the Vonage Voice API, Slim Framework, and dynamic NCCOs.

Introduction

Building voice-powered applications used to mean wrestling with hardware gateways and low-level telephony protocols. Today, the Vonage Voice API handles all that complexity with just a few lines of code.

In this tutorial, you’ll build a small PHP application that handles both inbound and outbound phone calls using the Vonage Voice API. You’ll start by returning a text-to-speech (TTS) message to anyone who calls your Vonage number, then extend the app to programmatically trigger outbound calls. Finally, you’ll make the spoken message dynamic by fetching a random joke from a public API.

Tl;dr: View the sample code in the Vonage Community GitHub repository.

Prerequisites

Before you start, make sure you have the following:

  • PHP 8.3 or higher installed. Run php -v to check your version.

PHP 8.3 or higher installed. Run php -v to check your version.

for dependency management

Node.js and npm to install the Vonage CLI

  • ngrok (or a similar tunnelling tool) to expose your local server to the internet

(or a similar tunnelling tool) to expose your local server to the internet

Set Up the Vonage CLI

The Vonage CLI lets you manage your account, create applications, and purchase numbers from the terminal. Install it globally with npm:

Once installed, authenticate the CLI with your API key and secret, which you’ll find in the Vonage API Dashboard:

Create a Vonage Application

A Vonage application is a container for the configuration and credentials your code needs to interact with Vonage APIs. Create a new working directory for your project, navigate into it, then run the following command:

You have now created a Vonage Application. Note the Application ID returned; you’ll need it shortly. The CLI also saves a private.key file in your current directory; keep it safe, as we’ll use it alongside the Application ID to authenticate with the Voice API in later steps.

Next, you need to purchase a voice-enabled virtual number to link to your application. Search for an available number in your country (replace US with your two-letter country code if needed). Numbers must be in E.164 format: include the country code and omit any leading zeros (for example, a UK number 07700900001 becomes 447700900001):

Select a number from the returned list, then purchase it by running:

Finally, link the number to your application:

You can check that the number has been correctly linked to your application by running:

Set Up Your Workspace

In your project directory, run composer init to start. Accept all defaults and skip defining your dependencies interactively; we’ll do this in the next step.

This tutorial uses the Slim Framework to handle incoming webhook requests from Vonage. Next, install Slim along with its PSR-7 implementation and the phpdotenv library for managing environment variables:

Ensure that the private.key file you received when creating your application is in this directory, at the same level as composer.json.

Create a .env file in the project root to store your credentials:

Add .env and private.key to your .gitignore file so credentials are never committed to version control:

Now start the local PHP development server:

Your application is now listening on port 8000.

Next, you need to expose your application to the internet so that Vonage can reach your webhooks. Let’s use ngrok for it:

Make note of your newly created ngrok URL; you’ll need to update your Vonage Application with it next.

Head over to your Vonage Dashboard and find your “vonage-calls” application under the Applications tab. Click on the Edit button, switch the Voice toggle on under Capabilities, then fill in your webhook URLs as shown below:

Save your changes, then you’re all set!

Create Your NCCO

Vonage Voice calls are controlled using JSON call control objects called NCCOs. An NCCO is a JSON array of actions that tells Vonage what to do when a call starts. Some of the available actions include:

  • connect - connect a call to another number

connect - connect a call to another number

  • record - record a call

record - record a call

  • conversation - create a conference call

conversation - create a conference call

  • talk - generate a text-to-speech message

talk - generate a text-to-speech message

See the NCCO reference for the full list.

Here’s the NCCO you’ll start with; a simple text-to-speech message:

Note on voice customisation: The talk action supports language and style parameters to control the voice used for text-to-speech. See the text-to-speech language reference for the full list of available voices.

Note on voice customisation: The talk action supports language and style parameters to control the voice used for text-to-speech. See the text-to-speech language reference for the full list of available voices.

Build the Answer Webhook

Create a file named public/index.php. The code below bootstraps the Slim app, loads your environment variables, registers an answer webhook handler, and returns the NCCO as a JSON response whenever Vonage makes a GET request to /webhooks/answer.

It also registers an event webhook at /webhooks/event that Vonage sends call status updates (such as ringing, answered, and completed) to throughout the call lifecycle. For now, the handler simply acknowledges receipt with a 204 No Content response; in a production app, you’d log or act on these events.

When Vonage makes a GET request to your Answer URL, the handler returns a JSON-encoded NCCO. As long as the response is valid JSON in the correct format, Vonage knows how to handle the call.

Time to test it out! Save the file, then call the virtual number you purchased to hear your text-to-speech message.

Make an Outbound Call

You’ve handled an inbound call, now let’s trigger an outbound one. When you make an outbound call, Vonage still looks at your Answer URL to find out how to handle it, so the webhook you just built will serve both directions.

To make an outbound call, we’ll need the Vonage PHP SDK:

Now add the following use statements at the top of public/index.php, after the existing ones:

Then add the route before $app->run():

To trigger an outbound call, visit the following URL in your browser, replacing DESTINATION_NUMBER with the number you want to call in E.164 format (for example, 14155550100 for a US number):

Add Dynamic NCCOs

You’ve accomplished what you set out to do, but it gets a little repetitive with the same message playing every time. Let’s make it dynamic by fetching a random programming joke from JokeAPI and reading it out on the call instead.

To make HTTP requests, install Guzzle:

Add the Guzzle use statement near the top of index.php:

Now update the /webhooks/answer handler to fetch a joke and use it as the spoken text:

is an actively maintained, free API. The type=twopart parameter returns jokes with setup and delivery fields, and safe-mode filters out explicit content. The handler concatenates them into a single string for the talk action to read aloud.

Now any time Vonage requests your Answer URL, whether for an inbound call or an outbound one you triggered, it will fetch a fresh programming joke and read it out. Test it by calling your Vonage number or by hitting the /makeCall endpoint.

What’s Next?

You’ve built a text-to-speech voice call system that handles both inbound and outbound calls and delivers dynamic content.

From here, you could:

  • Build a voice alert system - loop through a list of contacts, broadcast calls, and ask recipients to press a key to confirm receipt

Build a voice alert system - loop through a list of contacts, broadcast calls, and ask recipients to press a key to confirm receipt

  • Customise the message based on who’s calling, the time of day, or data from your own database

Customise the message based on who’s calling, the time of day, or data from your own database

  • Add call recording using the record NCCO action and the Voice API recording guide

Add call recording using the record NCCO action and the Voice API recording guide

  • Explore the full NCCO reference to add IVR menus, conference calls, and more

Explore the full NCCO reference to add IVR menus, conference calls, and more

What this article says