How to Add SMS to Your Node.js Apps with Express

The Nexmo SMS API allows you to send and receive a high volume of SMS anywhere in the world. Once you get your virtual phone number, you can use the API to manage outbound messages ("sending") and inbound messages ("receiving"). In this article, you will learn how to send and receive SMS messages with Node.js and Express.

GitHub icon View the source code on GitHub

Prerequisites

Before starting this tutorial, make sure you have:

  • a basic understanding of JavaScript and Node.js
  • Node.js installed on your machine. It can be any operating system (OS X, Linux, Windows, etc.). Whatever it is, you just need to be comfortable working work with the operating system's command line interface.
  • Selected a text editor like Sublime or Atom to create and save some source code

 

Getting Your API Keys

To get started with the SMS API, sign up for a Nexmo account to get your virtual number, as well as your API credentials. Once you have signed up, go to the Nexmo Dashboard to get your number (in the Numbers section) and your API key and secret (in the Settings section).

Nexmo dashboard

Using the Nexmo REST API Client for Node.js

First, use npm to install nexmo, the REST API client for Node.js in your working directory:

$ npm install nexmo --save

Use your text editor to create a .js file — let's call it index.js — and in the file, initialize a Nexmo instance with your credentials:

const Nexmo = require('nexmo');
const nexmo = new Nexmo({
 apiKey: YOUR_API_KEY,
 apiSecret: YOUR_API_SECRET
});

There are also optional parameters such as applicationId, privateKey, and an options object. You can find out more on the node-nexmo library repo on GitHub.

 

Send SMS Messages with Node.js

To send a message, use the nexmo.sms.sendSms function and pass the virtual number you are sending the message from, a recipient number, and the message to be sent. You can also pass optional parameters and a callback.

To try the API, let's hard-code your mobile phone number (which should start with a country code, e.g. "15105551234") and a message:

nexmo.message.sendSms(
 YOUR_VIRTUAL_NUMBER, '15105551234', 'yo',
   (err, responseData) => {
     if (err) {
       console.log(err);

     } else {

       console.dir(responseData);

     }

   }
);

Run the following command and see if you get the SMS to your mobile phone.

$ node index.js
SMS sent via Nexmo on Android

If it worked, you now know how to send an SMS message with the Nexmo Node.js Library.

You can stop right here, or proceed to learn how to take the queries dynamically from POST requests with Express.js!

Building a Simple SMS App with Express.js

Let's write a very simple app using Express to send an SMS. Install Express and body-parser as a dependency:

$ npm install express body-parser --save
In the index.js, add the following code to start a server and listen on port 5000 for connections:
const bodyParser = require(body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const server = app.listen(5000);

Now, wrap a call to nexmo.message.sendSms() with the Express post route method (note that this call to the nexmo.message.sendSMS method is slightly different from the one above). Let's set the type to 'unicode' so you can send some emojis too! Also, print out the success response at the callback.

app.post('/send', (req, res) => {
 // Send SMS
 nexmo.message.sendSms(
   YOUR_VIRTUAL_NUMBER , req.body.toNumber, req.body.message, {type: 'unicode'},
   (err, responseData) => {if (responseData) {console.log(responseData);}}
 );
 res.send('SMS Message Sent');

});

Now, try sending an SMS to any mobile phone number (including Google Voice numbers) using your app.

Instructions for creating HTML with a form UI where a user can enter a phone number and message are beyond the scope of this tutorial, so let's pretend we are sending data from a web interface by using Postman to make requests to your app. Postman is a good tool to have when you develop apps with REST APIs!

1. Launch Postman, Select POST, and then enter http://localhost:3000/send.

2. For Headers, set Content-Type: application/json

Send a post request to your app using Postman

3. For Body, select "raw" for the payload type and type a valid JSON with "toNumber" and its value (use your mobile phone number to receive an SMS message), as well as "message" and its value.

Send a post request to your app using Postman

4. Press the blue Send button

Once you made a successful POST to your app, you will get a text message to your phone from the virtual number.

SMS on Android

Also, you will see the response printed on your terminal.

Response from Nexmo SMS API

You can view the code sample used in this tutorial on GitHub.

Receiving SMS Messages with Node.js and Express

In the previous section, you set up your Nexmo account and learned how to send SMS messages with Node.js. In this section, you will learn about receiving an inbound SMS by implementing a webhook endpoint in Node.js using Express.

GitHub icon View the source code on GitHub

Writing Webhook Endpoints with Express

Let's start off by writing the Webhook endpoint. You will need body-parser to handle POST requests with Express. So, if you haven't installed it already for the last exercise, you'll need to install it now.

$ npm install express body-parser --save

Use your text editor to create a .js file (let's call it webHookApp.js) in whatever directory suits you, instantiate express, and listen the server to port 3000. the last exercise, you'll need to install it now.

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const server = app.listen(3000, () => {
 console.log('Express server listening on port %d in %s mode', server.address().port, app.settings.env);
});

Next, in the same directory as webHookApp.js, create a HTTP POST route to handle the requests:

app.post('/inbound', (req, res) => {
 handleParams(req.body, res);
});

Then in the same file as before, define the handleParams function:

function handleParams(params, res) {
 if (!params.to || !params.msisdn) {
   console.log('This is not a valid inbound SMS message!');
 } else {
   console.log('Success');
   let incomingData = {
     messageId: params.messageId,
     from: params.msisdn,
     text: params.text,
     type: params.type,
     timestamp: params['message-timestamp']
   };
   res.send(incomingData);
 }
 res.status(200).end();
}

 

Defining a Webhook Endpoint and Handling it With Express

In order to receive an SMS from Nexmo you need to associate the Webhook endpoint (URL) we just wrote with a virtual number that you have rented from Nexmo. Inbound messages to that number are then sent to your Webhook endpoint.

A diagram showing how a SMS is received from a user

While you are developing the Webhook endpoint, it is a pain to keep deploying your work while it is in progress. To make your life easier, let's use ngrok to expose your Webhook endpoint on your local machine as a public URL.

Using ngrok

First, download ngrok from https://ngrok.com. Once installed (note: the instructions are slightly different for OS X and Linux than they are for Windows), run ngrok on your terminal for port 3000, because that's the port we used in our Express Webhook endpoint:

$ ./ngrok http 3000
Running ngrok

Your local server (localhost:3000) now has a ngrok URL. In the case above, it is https://71f03962.ngrok.io, but yours will be different. Additionally, every time you re-run ngrok, this ngrok URL will change. So, if during testing, you exit from ngrok (while in the terminal interface, just press CTRL-C to stop ngrok) and then restart it, you will need to make a note of the new ngrok URL because you'll need to enter it into your Nexmo dashboard.

Setting the Webhook Endpoint with Nexmo

Sign in to your Nexmo account, and go to Settings. Scroll all way down to API Settings and fill out the Callback URL for Inbound Message by entering a ngrok URL with a route to the HTTPS URL that ngrok reported to you with the path "/inbound" appended to the end. For example, if your ngrok URL is https://71f03962.ngrok.io, the URL that you would enter into the inbound URL on your Nexmo settings page would be https://71f03962.ngrok.io/inbound.

Next, set the HTTP Method to POST and then save.

Setting your Webhook endpoint

Now all your incoming messages will go to the Webhook (callback) URL we wrote with Node.js and Express.

Note: We've set the Webhook endpoint for SMS at an account level. But you can also set up unique Webhook endpoints for each virtual number.

Upon saving these settings in the Nexmo dashboard, Nexmo will automatically attempt several POST operations (because you picked POST as the HTTP method) to the ngrok URL that you supplied). The messages themselves are not SMS messages, but if everything is setup properly, you will see the POST requests to the "inbound" route in the ngrok console along with their HTTP 200 OK statuses (as shown below):

OK, from the directory where you are saving your .js files, let's run the Node code:

$ node webHookApp.js

Then, let's try sending some messages from your phone to your virtual number.

Screenshot of a user sending a SMS message from an Androidphone

When you are tunneling your local app with ngrok, you can also inspect the request at http://127.0.0.1:4040/ on your browser.

ngrok inspector

Voilà! Now you can see that your SMS message has been sent, and Nexmo has received the message and passed it onto your Express application via a Webhook.

If you take a look at the code sample in GitHub, you will notice the extra example — a persistent data storage (like the HTML5 Local Storage, but for Node) and the incoming data is stored with each key (message ID) and values. That way, you can set up a /inbound/:id route parameter as named URL segment. For instance, when you access http://localhost:3000/inbound/080000001947F7B2, it returns:

{"messageId":"080000001947F7B2","from":"14159873202","text":"Yo!","type":"text","timestamp":"2016-10-26 17:47:26"}

In reality, you should set up a real DB, rather than the data storage.

How Do You Know When Your SMS Message is Delivered?

In the previous sections, you have learned how to send SMS messages and consume a webhook for incoming SMS messages with Node.js. In this section, you will learn how to find out if the SMS messages sent from your virtual number have been delivered.

GitHub icon View the source code on GitHub

When you send a message to a mobile phone number using the Nexmo API from your virtual number, the HTTP response from the API can tell you that the message has been successfully sent from your app. However, it doesn't tell you if the message is actually delivered to the recipient or not. To find out the status you need to register a Webhook callback that is made when the status of the delivery changes.

If you have designated a Webhook endpoint to handle delivery receipts (done through the Nexmo dashboard), Nexmo forwards this delivery receipt to it when the recipient's mobile phone carrier returns a Delivery Receipt (DLR) to Nexmo.

How Delivery Receipt (DLR) works - Nexmo

Handling a Nexmo Delivery Receipt  Webhook with Express

Let's go ahead and write the Express endpoint to handle a Nexmo delivery receipt Webhook. To make this work, all we need to do is add some new Webhook handling code to the webHookApp.js code we developed in the previous exercise.

Similar to the previous section, you will need to have ngrok installed and running. However, whereas the previous exercise involved an incoming route called "/inbound" to handle inbound SMS messages, this exercise is going to add a new incoming route called "/receipt" to handle delivery receipts.

Using your text editor, add the following code to webHookApp.js:

// For webhooks configured to use POST
app.post('/receipt', (req, res) => {
 handleReceiptParams(req.body, res);
});

// For webhooks configured to use GET
app.get('/receipt', (req, res) => {
 handleReceiptParams(req.query, res);
});
Then add the following code to define the handleReceiptParams function as follows:
function handleReceiptParams(params, res) {
 if (params.status !== 'delivered') {
   console.log('Fail: ' + params.status);
 } else { // Success!
   console.log(params);
 }
 res.status(200).end();
}

Now if you look at your code, you will notice how, using Express, we are essentially just setting up routes and handlers to different paths like "/inbound" and "/receipt". For example, using Express' app.post method, we've defined a route for any HTTP POST requests that arrive at the "/inbound" URL, and handle those requests with the handleParams() function. Correspondingly, we've used Express' app.post and app.get methods to define routes for HTTP POST and GET requests that arrive at the "/receipt" URL. Those requests are handled by the handleReceiptParams() function.

Also, note at the end of this code, when you receive the DLR, it responds with a status code of 200. With Nexmo, you must send a 200 OK response. If you don't, Nexmo will resend the delivery receipt for the next 72 hours.

Once you've saved the webHookApp.js file, you'll need to restart it. If your webHookApp.js node app is running from before, go to the terminal window where it's running and shut terminate the app (press CTRL-C). Then, restart it to get it running with the new code.

$ node webHookApp.js

Setting the Endpoint with Nexmo

Now that we have the Webhook endpoint, let's set it up in your Nexmo dashboard

If you terminated ngrok from the previous exercise, follow those same instructions to get it started again. Only this time, in addition to populating the "Callback URL for Inbound Message" field in your Nexmo settings (in the Nexmo dashboard) with the ngrok URL appended by "/inbound", you will also need to populate the "Callback URL for Delivery  Receipt" field with the ngrok URL appended by "/receipt".

If ngrok is still running from before, then copy the Callback URL from the inbound message field, paste it into the "Callback URL for Delivery Receipt" field, and replace the "/inbound" part of the path with "/receipt". Then save.

Nexmo Setting for ngrok Webhook endpoints

Now, every time you send a message from your virtual number, the delivery receipt Webhook call will be made to that URL.

One other thing to note is how this code listens on port 5000. The reason for this is that to have two Node-based Nexmo apps running simultaneously — one that can send outgoing SMS messages (the first exercise) and one that receive both inbound SMS messages and inbound delivery receipts (the second and third exercise) — each node app (index.js and webHookApp.js) have to be listening on different ports. Otherwise, the two apps would conflict with each other.

So, why do both apps need to run at that same time? Well, you need the first app (that sends SMS messages) to test the delivery receipt capability (from the third exercise). Alternatively, there's no reason you cannot combine the two applications into a single app that listens on a single port that has defined routes for "/send" (from the first exercise), "/inbound", and "/receipt." You just have to keep in mind that the single base of source code must import the Nexmo functionality and include your Nexmo credentials.

So, now, with both webHookApp.js and index.js running at the same time, if you go back to Postman and send a message (exactly as you did before), you should not only have success in sending the message, you should also see the delivery receipt show up in the both the terminal window where webHookApp.js is running as well as in browser-based console where you're watching ngrok:

 

Postman delivery

 

Postman delivery - POST receipt

So, if your message has been successfully sent to your mobile phone, the delivery receipt should include status, message ID, network code, timestamp, etc.

{
 "msisdn": "14155551234",
 "to": "12015556666",
 "network-code": "310090",
 "messageId": "02000000FEA5EE9B",
 "price": "0.00570000",
 "status": "delivered",
 "scts": "1208121359",
 "err-code": "0",
 "message-timestamp": "2016-10-19 22:40:30"
 }

You can find out more about delivery info on the API Reference page.

Note: Some US carriers do not support this feature. Also, if you are sending SMS to a Google Voice number, you will not get any receipt. We do not provide reach to other virtual number providers for fraud prevention purposes. If you have any particular business case where you would like to be able to reach virtual numbers, please contact our Support team!

Alex Lakatos Alex Lakatos is a newly minted JavaScript Developer Advocate for Nexmo. In his spare time he volunteers at Mozilla as a Tech Speaker and a Reps Council member. JavaScript developer building on the open web, he has been pushing its boundaries every day.

Comments