Typically when developing a Twilio application, there is an ugly and confusing separation between making REST requests to Twilio's API servers, and setting up the response handlers that reply back to Twilio with TwiML instructions. For example, when you POST to the /Calls resource in order to initiate an outgoing call, you specify a StatusCallback URL. When the call is answered, Twilio requests that StatusCallback URL. Your application then must respond back with valid TwiML, and Twilio executes your instructions.
In truth, this all is very straightforward no matter what library, language, or platform you're using to build your Twilio app. You make some REST requests, ensure there's some sensible and valid TwiML at the URLs you specify, and you're good to go.
Here's an example of what I mean, borrowed from the Python Twilio helper library:
# Instantiate a Twilio REST account object
account = twilio.Account(SID, AUTH_TOKEN);
# Call my parents req_data = {
'From': MY_CALLER_ID,
'To': '867-445-1795',
'Url': 'http://hostname/path/to/my/love/filled/parental/greeting.xml'
}
print account.request('/2010-04-01/Accounts/%s/Calls' % \
ACCOUNT_SID, 'POST', req_data)
Before your request is POSTed to Twilio, this code assumes you've set up a webserver on your machine, and you've gone and put your TwiML (either statically or dynamically generated) in the path you've specified. The file probably looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>
Hey mom and dad! It's your baby boy! I love you!
</Say>
</Response>
Granted, nothing above is really difficult (who can't configure nginx or apache and write some XML, after all?), but it still is pretty annoying to have separate controllers for your Twilio REST requests and your TwiML responses. Additionally, if your app includes lots of complex logic (suppose, for instance, you have various different responses you want to deliver based on an incoming caller's geographic location), it becomes a cumbersome and error-prone process to maintain all your different REST controllers and TwiML response generators.
Enter: Node-Twilio.
Node-Twilio is a Twilio helper library for Node.js. Now, Node-Twilio's not your average Twilio helper library; It doesn't simply provide you with a few simple method calls for making REST requests and a few functions to ensure you generate valid TwiML (but it does include both of those). Node-Twilio takes care of provisioning all the URLs you deliver to Twilio to deliver TwiML, and it exposes all of Twilio's functionality as EventEmitter objects.
Perhaps an example is in order. Again, let's call my parents (they're great, and I want to make sure they really know it), but this time, let's do it with Node-Twilio.
// First, we have to require TwilioClient and the TwiML helper
var TwilioClient = require('twilio/client'),
Twiml = require('twilio/twiml');
// Now, let's instantiate our client with our credentials and hostname
var client = new TwilioClient(ACCOUNT_SID, AUTH_TOKEN, HOSTNAME);
// Ok, great! Now, let's get a new PhoneNumber object
// Note: We can pass in either a Twilio phone number
// associated with our account, or the SID of same.
var phone = client.getPhoneNumber('+16067777777');
// Alright, we're ready to make a call
phone.makeCall('+18674451795', null, function(call) {
// Call is an OutgoingCall object
// It is an EventEmitter
call.on('answered', function(callParams, response) {
// callParams is simply a map of the POST vars
// Twilio sends with its request.
// response is a Twiml.Response object
response.append(new Twiml.Say('Hey mom and dad! It's your baby boy! I love you!'));
response.send();
});
call.on('ended', function(params) {
console.log('Call ended');
process.exit(0);
});
});
Past all that into a file called app.js, substitute in your credentials, and you're ready to call my parents.
Now, what about incoming calls (and SMS, too)? Well, they're just as simple to handle. The PhoneNumber object returned by the TwilioClient is also an EventEmitter. It emits 'incomingCall' and 'incomingSms' events. So, if you wanted to respond to SMS messages, you'd do something like this:
phone.on('incomingSms', function(smsParams, response) {
// No matter what the incoming message is, respond back with a
// quote from your favourite recent novel (Adam Levin's The Instructions)
response.append(new Twiml.Sms('We are on the side of damage!'));
response.send();
});
Simple, isn't it? Node-Twilio makes developing Twilio apps simpler and more rapid than any other platform or application. In addition to providing a clear EventEmitter interface to Twilio's REST API, Node-Twilio includes wrapper methods for every one of the resources defined in the API, so if you want to get into the nitty-gritty, you're easily able to.
Interested in trying it out? Check out Node-Twilio on github, take a look at the documentation (which is still slightly in-progress), and give it a whirl!