
Connect Calls Using the Vonage Voice API
Introduction
In this tutorial, we will set up a call between two phone numbers and connect another phone number to the current call using the Vonage Voice API with the help of the NCCOs.
We will specify an NCCO element in the destination object to control the call by specifying a URL. We will use the ‘connect’ and 'talk’ NCCO actions.
You can find the complete GitHub repo code here.
Vonage API Account
To complete this tutorial, you will need a Vonage 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 Vonage API Dashboard.
Prerequisites
Before starting to build the project, ensure you have:
Node.js version 20+ and npm installed on your machine.
Ngrok for creating a secure tunnel to your localhost.
A text editor and basic JavaScript knowledge.
Set up the Vonage Application
Create a Vonage Voice Application
Create a New Application: Go to 'Your Applications' in the dashboard and toggle the Voice capability.
A video explanation of how to create a Vonage application.
Purchase and Link a Virtual Phone Number
Acquire a virtual number for your application.
To buy a virtual phone number, go to your API dashboard and follow the steps shown below.
Purchase a phone number
Go to your API dashboard
Navigate to BUILD & MANAGE > Numbers > Buy Numbers.
Choose the attributes needed and then click Search
Click the Buy button next to the number you want and validate your purchase
To confirm you have purchased the virtual number, go to the left-hand navigation menu, under BUILD & MANAGE, click Numbers, then Your Numbers
Link a virtual number to your application.
Voice API Capability
Start an ngrok Tunelling Instance
Ngrok is a tool that allows you to expose your application to the internet; you'll need this to read in event webhooks from the Vonage Voice API. If you haven’t used ngrok before, you can start here. I’ve added the steps to run an instance below the image.
Run the following command to start an ngrok tunneling instance.
ngrok http 3000
ngrok (Ctrl+C to quit)
👋 Goodbye tunnels, hello Agent Endpoints: https://ngrok.com/r/aep
Session Status online
Account plan name
Version 3.22.0
Region Europe (eu)
Latency 31ms
Web Interface http://127.0.0.1:4040
Forwarding https://xyz.ngrok.app -> http://localhost:8000
Connections ttl opn rt1 rt5 p50 p90
14 0 0.03 0.03 6.10 7.79
Configure the Webhooks
Back in the Vonage API Dashboard, under your Apps, toggle the Voice option under capabilities and set your server's public URL from ngrok as the endpoint for inbound messages and events. It should look like: https://xyz.ngrok.com/answer
for inbound and https://xyz.ngrok.com/webhooks/status
for status. If you’d like to learn more about webhooks, it’s on our Vonage documentation.
Install the Dependencies
It’s time to open our text editor, create a new project, and install the required dependencies. We will use the Vonage Voice SDK for Node.js, Vonage JWT SDK for Node.js, Express, and Dotenv.
Install all of them in one go, and run the following command to automatically add these packages to yourpackage.jsonfile and your project'snode_modules
directory.
npm install @vonage/voice @vonage/jwt express dotenv
Implement the Server Side Code
In your src/server.js file, start the project by importing the required modules. You'll set up Express to handle incoming HTTP requests.
// src/server.js
// Import dependencies
require("dotenv").config();
const express = require("express");
const { NCCOBuilder, Talk, Connect } = require("@vonage/voice");
const { verifySignature } = require("@vonage/jwt");
// Create Express app
const app = express();
// Parse request body
app.use(express.json());
app.use(express.urlencoded({ extended: false })););
Environment Variables
Let’s create a .env file that holds all the environment variables we will use for this web application. I’ve listed and explained them below. You can learn more about using environment variables in Node.js.
# .env
VONAGE_API_SIGNATURE_SECRET= this is the secret used to sign the request that corresponds to the signature secret associated with the API key included in the JWT claims. You can identify your signature secret on the Dashboard settings.
SECOND_PHONE_NUMBER= The phone number that will receive the control of the call
VONAGE_VIRTUAL_NUMBER= Your Vonage virtual number linked to the Vonage Application
> NOTE: When entering a phone number, don't use a leading + or 00; start with the country code, such as16600700000.
Create the JWT Verification Function
Create a JWT function to verify whether the incoming call actually came from Vonage. Learn more about verifying the request.
// src/server.js
const verifyJWT = (req) => {
// Verify if the incoming call came from Vonage
const jwtToken = req.headers.authorization.split(" ")[1];
if(!verifySignature(jwtToken, process.env.VONAGE_API_SIGNATURE_SECRET)) {
console.error("Unauthorized request");
throw new Error('Not a voice API request');
}
console.log('JWT verified');
}
Create the Endpoint to Handle Inbound Calls
We will create an/answer
endpoint, the one we’ve added the URL to on the Vonage Dashboard. Once a call is made to the Vonage virtual phone we’ve purchased and linked to the application, we verify the JWT and add a Talk action: “Hello, this is a test call. The call will be forwarded shortly.”
// src/server.js
// Endpoint to handle inbound calls
app.all("/answer", (req, res) => {
console.log("Received inbound call...");
verifyJWT(req);
// Build the NCCO for handling the call
const builder = new NCCOBuilder();
// Add the Talk action to greet the caller
builder.addAction(
new Talk("Hello, this is a test call. The call will be forwarded shortly.")
);
Connect the Current Call to Another Number
Following that, we add an NCCO action that connects another phone number to the call, so a call is made to another phone number that is then connected to this existing call.
// src/server.js
// Add the Connect action to forward the call to another number
builder.addAction(
new Connect(
{
type: "phone",
number: process.env.SECOND_PHONE_NUMBER,
},
process.env.VONAGE_VIRTUAL_NUMBER
)
);
let ncco = builder.build(); // Build the NCCO
// Respond with the NCCO to control the call
res.json(ncco);
});
Handle Vonage Call Events
Similarly to /answer
we’ve seen before, we’ve also added a /webhooks/event
URL under the voice capabilities on the Vonage Dashboard; we can log information about the events to check, for instance, if the call has been rejected, the call status, its UUID, etc.
// src/server.js
app.all("/webhooks/event", (req, res) => {
console.log("Received Event:", req.body);
const { status } = req.body;
if (status === "rejected") {
console.error("Call rejected. Check error code and message.");
}
// Ensure response is in JSON format
res.status(200).json({ success: true }); // This should be a valid JSON response
});
Add a Port Listener
Finally, we add the bit of the code for the server to listen on a specified port; for this example, I made it port 3000.
// Listen on port 3000
app.listen(3000, () => {
console.log("App listening on port 3000");
});
Run and Test your Code
It’s time to test things out. Start by running the server file from your terminal or command prompt.
node src/server.js
Make sure your .env file contains all the environment variables set up, ngrok is running, and the correct URLs are set up on the Vonage Dashboard.
Call the virtual phone number you purchased and linked to the application. The first phone number setup receives the call, which is then connected to the second phone number, and you should receive a call there.
Conclusion
Learn more about the Call Control Objects in this One-Dev-Minute video and the Vonage Voice API NCCO documentation.
Got any questions or comments? Join our thriving Developer Community on Slack, follow us on X (formerly Twitter), or subscribe to our Developer Newsletter. Stay connected, share your progress, and keep up with the latest developer news, tips, and events!
Further Reading
Handle an Inbound Phone Call with Python
Build an Escape Plan With the Vonage Voice API and Get a Ghost Call