Skip to main content

Answering Machine Detection - Node.js

Answering Machine Detection (AMD) is a useful tool for high-volume phone systems. It is used to screen outbound calls to determine whether a human or machine (such as an IVR or voicemail system) has answered the call. If a human answers, the call can be connected to a human agent. If a machine is detected, your system may want to end the call or leave a voicemail message. This example implements AMD using the Compatibility SDK with Node.js. To follow along, see the full code in the GitHub repo.

Setup Your Environment

First, let's define our environmental variables. Copy the contents of env.example and save them in a new file called .env.

PROJECT_ID=
API_TOKEN=
SIGNALWIRE_SPACE_URL=

SERVER_URL=

SW_NUMBER=
CUSTOMER_NUMBER=
AGENT_NUMBER=

The first three are standard SignalWire credentials. If you need help finding them, check out our guide to Navigating Your SignalWire Space. The SERVER_URL is an endpoint for receiving your AMD detection result and returning it to your application. Of the three numbers needed for this demo, only the SW_NUMBER is required to be a number from your SignalWire Space.

Run Your Express Server

This example runs an Express server. After your environmental variables are set, you can install dependencies with npm install then start the Express server with npm run start. If you prefer to use Docker, build the image with docker build -t nodeamd . and run it with docker run --p 3000:3000 --env-file .env nodeamd.

Testing with Ngrok

This demo creates a call with the AMD feature enabled, then returns the detection result to a specified URL. We recommend using Ngrok to provide an HTTPS URL to direct that result back to this demo server. In your Ngrok CLI, run ngrok http 3000, where 3000 is the port we set in our Express server. It will return a secure URL you can copy into the environmental variables discussed above.

Code Walkthrough

In the repo's index.js file, you will see a REST API call and four routes: an entry route, a route to dial an agent, a voicemail route, and a hangup route.

The first step is to create a call with AMD enabled using the Compatibility API's create a call endpoint. Note that we use DetectMessageEnd for our detection value and we lengthened the default Machine Detection Timeout to account for longer voicemail messages. The URL we specify in this API call is an Ngrok tunnel that will redirect that return information to our server. If you have a separate dialer, specify the URL of your hosted server.

This example automatically dials a test number, but in production, you might choose to extract this action to dial numbers in sequence with an auto dialer like the one discussed in this article or customize your code to dial numbers in parallel from a list or CSV file.

When the AMD determination is returned, it will hit the default route which performs a different action depending on whether a human or machine answers the call. If a human answers, we play a message and connect the customer to a live agent if they press a key. Using this gather verb, you can create an intricate IVR system with multiple route options as in this IVR example. For this simple example, the call is sent to the dialAgent route which dials a agent's phone number. If the agent does not answer, the call is sent to the voicemail route for a voicemail recording, then to the hangup route to log the voicemail recording and end the call.

All of these routes use the same syntax to use Compatibility XML with the Compatibility SDK. We generate XML to run and send it with the following lines.

const response = new RestClient.LaML.VoiceResponse();
// logic with XML verbs
res.set("Content-Type", "text/xml");
res.send(response.toString());

Following the same pattern, you can use Compatibility XML to extend this example to suit your needs.

Wrap Up

This example is a simple implementation of answering machine detection. With this starting point and the tips explained above, you can not only leverage this useful feature, but extend this application to an IVR if you need one. For an example of a full IVR with AMD and voicemail using the Node.js Compatibility SDK, see Voicemails to Email IVR.