1. Vonage Learn
  2. Blog
  3. 2019
  4. 02
  5. 05
  6. Forward Call With Koa Js Dr
Forward a Call Via Voice Proxy With Koa.js

< Tutorial />

Forward a Call Via Voice Proxy With Koa.js

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:

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:

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):

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:

npm install dotenv --save

Let's create the .env file now, with a small template for the variables the application will need:


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:

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:

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):


const Koa = require('koa');
const router = require('koa-router')();
const koaBody = require('koa-body');
const app = new Koa();


router.get('/answer',() => {});
router.post('/event',() => {});


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:

router.post('/event', async context => {
  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 eventUrls, 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:

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:

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:

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:


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:

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:

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.

Comments currently disabled.