Skip to content

Instantly share code, notes, and snippets.

@lbrenman
Last active March 14, 2018 03:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lbrenman/2d0b28f8ec1ad9f021e5b4acc7779812 to your computer and use it in GitHub Desktop.
Save lbrenman/2d0b28f8ec1ad9f021e5b4acc7779812 to your computer and use it in GitHub Desktop.
API Builder - Receiving Two-Way SMS Messages with Twilio

API Builder - Receiving Two-Way SMS Messages with Twilio

In a prior blog post we introduced the API Builder Twilio Connector and how to use it to send SMS text messages from API Builder.

However, what if you want the user to be able to opt out of receiving text messages or ask a question of the user via SMS and have the user respond via SMS? This is known as Two-Way SMS and both Twilio and API Builder support two-way SMS.

This blog post will describe how to set this up.

The basic steps are outlined below:

  • Twilio supports two-way SMS by means of a web hook that will be called when the SMS recipient responds to the SMS

  • The web hook will be implemented as a Custom API in API Builder

  • After the API Builder Custom API is created, the URL for this API is populated in the Twilio Management Console Messaging Webhook section

API Builder Custom API

Let's build a simple API that can be used as a web hook.

From the Twilio online docs you can see what parameters will be sent in the webhook POST. Note that I had to experiment a little to figure out which of the parameters were sent and which were not and used this info to setup the POST parameters in my API Builder Custom API below, /api/twiliowebhook.js:

var Arrow = require('arrow');

var twiliowebhook = Arrow.API.extend({
	group: 'custom',
	path: '/api/twiliowebhook',
	method: 'POST',
	description: 'api to for Twilio to call when a user replies to a text',
	parameters: {
		MessageSid: {description:'A 34 character unique identifier for the message. May be used to later retrieve this message from the REST API.', optional: true},
		SmsSid: {description:'Same value as MessageSid. Deprecated and included for backward compatibility.', optional: true},
		AccountSid: {description:'The 34 character id of the Account this message is associated with.', optional: true},
		From: {description:'The phone number or Channel address that sent this message.', optional: true},
		To: {description:'The phone number or Channel address of the recipient.', optional: true},
		Body: {description:'The text body of the message. Up to 1600 characters long.', optional: true},
		NumMedia: {description:'The number of media items associated with your message', optional: true},
		FromCity: {description:'The city of the sender', optional: true},
		FromState: {description:'The state or province of the sender.', optional: true},
		FromZip: {description:'The postal code of the called sender.', optional: true},
		FromCountry: {description:'The country of the called sender.', optional: true},
		ToCity: {description:'The city of the recipient', optional: true},
		ToState: {description:'The state or province of the recipient.', optional: true},
		ToZip: {description:'The postal code of the called recipient.', optional: true},
		ToCountry: {description:'The country of the called recipient.', optional: true},
		SmsMessageSid: {description:'SmsMessageSid.', optional: true},
		SmsStatus: {description:'SmsStatus.', optional: true},
		NumSegments: {description:'NumSegments.', optional: true},
		ApiVersion: {description:'ApiVersion.', optional: true}
	},
	action: function (req, resp, next) {
		console.log('twiliowebhook: API called');

		console.log('twiliowebhook: Body: '+JSON.stringify(req.body));

        console.log('twiliowebhook: User sent: '+req.body.Body);

        next();
	}
});
module.exports = twiliowebhook;

The code above simply defines an API POST at /api/twiliowebhook that has up to 19 fields in the body of the POST. Then it prints the POST body to the console and also prints the text that the user entered when they responded to the SMS.

Note that the Custom API defined above assumes that the user will not send an MMS message (i.e. send a photo).

You can modify the API to implement your business logic (opt the user out of receiving SMS, etc...).

Twilio Console

Log into the Twilio Console and navigate the phone number that your application uses for sending SMS and navigate down to the Messaging section. Change the URL for the entry A Message Comes In and enter the API Builder URL as shown below

Test Two-Way SMS

Call your API to send an SMS to yourself.

Note that I created this project in Cloud9 so I was able to provide the URL to my development environment and it is publicly accessible. Alternately you can use something like ngrok to expose localhost or simply publish your API Builder Project

Respond to the SMS you receive, for example enter '2' and send.

In the screen shot above you can see the message I sent (2) in the console log.

Conclusion

In this blog post we showed how easy it is to use API Builder and Twilio together to implement two-way SMS. We leveraged the API Builder Twilio connector to send the SMS to the recipient and we used API Builder Custom API to create a web hook that is called by Twilio when the recipient responds.

/**
* Example configuration for connector/appc.twilio.
* Make the changes below as required for your environment.
*/
// This file is copied as template when you install this connector in arrow application
module.exports = {
connectors: {
'appc.twilio': {
sid: '<sid>',
auth_token: '<auth_token>',
twilio_number: '+19785793281',
generateModels: ['message'],
modelAutogen: true,
generateModelsFromSchema: true,
skipModelNamespace: false,
twilioWelcomeVoiceURL: 'https://demo.twilio.com/welcome/voice'
}
}
}
var Arrow = require('arrow');
var twiliowebhook = Arrow.API.extend({
group: 'custom',
path: '/api/twiliowebhook',
method: 'POST',
description: 'api to for Twilio to call when a user replies to a text',
parameters: {
MessageSid: {description:'A 34 character unique identifier for the message. May be used to later retrieve this message from the REST API.', optional: true},
SmsSid: {description:'Same value as MessageSid. Deprecated and included for backward compatibility.', optional: true},
AccountSid: {description:'The 34 character id of the Account this message is associated with.', optional: true},
From: {description:'The phone number or Channel address that sent this message.', optional: true},
To: {description:'The phone number or Channel address of the recipient.', optional: true},
Body: {description:'The text body of the message. Up to 1600 characters long.', optional: true},
NumMedia: {description:'The number of media items associated with your message', optional: true},
FromCity: {description:'The city of the sender', optional: true},
FromState: {description:'The state or province of the sender.', optional: true},
FromZip: {description:'The postal code of the called sender.', optional: true},
FromCountry: {description:'The country of the called sender.', optional: true},
ToCity: {description:'The city of the recipient', optional: true},
ToState: {description:'The state or province of the recipient.', optional: true},
ToZip: {description:'The postal code of the called recipient.', optional: true},
ToCountry: {description:'The country of the called recipient.', optional: true},
SmsMessageSid: {description:'SmsMessageSid.', optional: true},
SmsStatus: {description:'SmsStatus.', optional: true},
NumSegments: {description:'NumSegments.', optional: true},
ApiVersion: {description:'ApiVersion.', optional: true}
},
action: function (req, resp, next) {
console.log('twiliowebhook: API called');
console.log('twiliowebhook: Body: '+JSON.stringify(req.body));
console.log('twiliowebhook: User sent: '+req.body.Body);
next();
}
});
module.exports = twiliowebhook;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment