It’s easy to have an automated voice answer when people call your Nexmo virtual number, but there are times you’ll want to forward those calls on to a real person. With a minimal configuration and one webhook on a Koa.js server, you can pass inbound calls to any number you choose.
Set Up Ngrok and the Nexmo CLI
To begin, you’ll need to do some setup of Nexmo, your application, and ngrok (or another way to host your endpoints). If you’ve followed our other blog posts, you may have these things and be able to skip to the next section. If not, read on!
You can use ngrok to expose an endpoint on your local machine, rather than pushing your code to a publicly accessible server, for ease of development. Download it from ngrok.io and follow the setup instructions. In a new terminal window, start ngrok on port 3000:
1 2 |
ngrok http 3000 |
Keep that terminal window open so you can copy the ngrok URLs you’ve been assigned later in the tutorial.
Next you’ll need to install the Nexmo CLI from npm. Installing it globally will be useful so you have a consistent version across your projects and don’t have to keep track of the path to the utility:
1 2 |
npm install nexmo-cli -g |
Unless you’ll be using a different developer account for each project you create, you can set up the CLI by providing the credentials from your dashboard globally (which is the default):
1 2 |
nexmo setup <api_key> <api_secret>` |
Create Your App
Create a directory for your new application and perform any initialization you might want to do. This example uses Koa.js for a server, so the basics provided by npm init
should be enough. Because you’ll be storing some variables in a .env
file, it’s also a good time to remember to install dotenv:
1 2 |
npm install dotenv --save |
Let’s create the .env
file now, with a small template for the variables the application will need:
1 2 3 4 |
APP_ID= FROM_NUMBER= TO_NUMBER= |
Create a new application using the Nexmo CLI, supplying a name that will distinguish it in your dashboard and the ngrok endpoints you’ll code in the next section. This is where you need to swap in your own ngrok https URL:
1 2 |
nexmo app:create "Forward a call" https://04d37918.ngrok.io/answer https://04d37918.ngrok.io/event |
As long as this command is successful, you’ll receive an Application ID, which you can paste into your .env
file for safekeeping.
Koa Server
Now you’re ready to create your server. You’ll need to install Koa.js and two middleware packages, koa-body
and koa-router
:
1 2 |
npm install koa koa-body koa-router --save |
Your server will import dotenv
to give you access to the variables in .env
, as well as Koa and its middleware. It will create a new Koa application, wire up the middleware, then finally listen on port 3000 (the port we supplied to ngrok):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
require('dotenv').config(); const Koa = require('koa'); const router = require('koa-router')(); const koaBody = require('koa-body'); const app = new Koa(); app.use(koaBody()); router.get('/answer',() => {}); router.post('/event',() => {}); app.use(router.routes()).listen(3000); |
Your server has two routes, one which will answer inbound calls, and one which will log events. The second is simpler, so let’s flesh that out first. The handler will do two things: log the contents of the request to the console, and return an HTTP 204 status:
1 2 3 4 5 |
router.post('/event', async context => { console.log(context.request.body); context.status = 204; }); |
You also need to provide a handler for the /answer
endpoint. If you’ve worked with Nexmo’s API before, this may look very straightforward. We want to create a Nexmo Call Control Object (NCCO) and return that as a JSON object. There are several properties we need on this object:
- the action, which is “connect” (that is, we want to connect our caller to another endpoint)
- an array of
eventUrl
s, the only member of which will be our logging endpoint - the from number, which is not the inbound caller’s number but a Nexmo virtual number through which we will proxy
- an endpoint definition whose type is “phone” and whose number is the number we want to forward the call to
The code itself is minimal. Notice we’re using process.env
to get the variables in your .env
file, so you can keep phone numbers you may not want shared private. You don’t have to provide a URL for eventUrl
unless you want to use a different event handler for this NCCO than for the application as a whole:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
router.get('/answer', async context => { const ncco = [ { action: 'connect', eventUrl: [], from: process.env.FROM_NUMBER, endpoint: [ { type: 'phone', number: process.env.TO_NUMBER } ] } ]; context.body = ncco; }); |
Renting a Number
Your server is almost ready to go, but you’ll need to supply phone number values in .env
in order to test it. You can rent a number within your Nexmo dashboard, or use the command line:
1 2 |
nexmo number:search GB |
You’ll get a list of available numbers, all in E.164 format, which you’ll always use when interacting with the Nexmo API. If the country code at the beginning of the numbers listed doesn’t match your own, change “GB” to your country and run the command again. Once you find a number you like, you can rent it via the CLI:
1 2 |
nexmo number:buy 442079460005 |
After confirming the number is rented, you can add it to your .env
file along with your own number, or another number you’d like to forward calls to:
1 2 3 4 |
APP_ID=308494d1-06c6-4d47-9ba8-70488d946846 FROM_NUMBER=442079460005 TO_NUMBER=447700900003 |
You also want to associate the number you’ve rented with your application, which is done from the command line. You supply two arguments, the new number and your application ID:
1 2 |
nexmo link:app 442079460005 308494d1-06c6-4d47-9ba8-70488d946846 |
Test Your Application
You’re all set! Make sure ngrok is still running (if it’s not you’ll need to restart it and update the endpoint URLs in your app) and start your server with:
1 2 |
node index.js |
Now if someone calls your virtual number, it should ring your phone. In the console, you’ll see details about each step of the process. If you want to take your application further, you can use that information in the /events
endpoint to see if calls have been answered and do things like play a message or try forwarding to a backup number.