At the excellent SF Developer Advocates Meetup this week, I met Johnny Diggz, Chief Evangelist for Tropo, a cloud API for Voice and SMS. Chatting about how you could integrate Tropo and Force.com, Diggz mentioned that Tropo supports speech recognition – it can post a transcription of a voice message to a URL. No prizes for guessing the first thought that came into my head: “I bet I can build an integration here – look up a contact based on the caller ID and create a Task with the message transcription.” (Completed Tasks appear in a Contact’s Activity History, just like when you ‘Log a Call’ in the browser.)

Here is a run through of how I got this working, and some ideas for taking it further.

First, I signed up for Tropo and created an application, assigning it a phone number. I used the Tropo transcribing sample as the basis for a hosted JavaScript file that executes on their infrastructure when my number receives a call. Here it is:

When the call connects, my app says “Please leave a message!”, beeps, and the caller has two minutes of message time. When the call completes, the incoming caller ID and a transcription of the call is JSON encoded and sent (via HTTP POST) to the given URL. I used the indispensable RequestBin to test this out: I called my app’s number, left a message, and this is what my bin received (edited to remove my phone number!):

So far so good. Now I used Simon Fell‘s JSON2Apex to create an Apex class to model that JSON – copy, paste, and voilà:

The next step was creating an endpoint on Force.com to receive message transcriptions. First, I defined an Apex class as a REST endpoint. I’ll walk through it step by step here; you can also grab the complete Apex class.

Let’s start with the class definition:

That gives me an endpoint at /services/apexrest/messageToTask on a Force.com Site. Now, since the incoming JSON object has a single property, ‘result’, I need only paste the corresponding class as an inner class in MessageToTask:

Next I need to define a method that will handle the HTTP POST. Here is the signature, with the relevant annotation:

Conveniently, the incoming message is parsed by the platform, and I’m given a Result object, ready to use. Tropo gives me the incoming caller ID as unadorned digits, so I need to format it before I can query for a matching Contact:

As you can see, this will work for US numbers only – I left international formatting for another day! 😉 The next step is to locate a contact from this phone number:

I’m just matching on the main and mobile phone numbers for Contacts here, but you could match on additional fields, match against Leads, custom objects whatever you like. For simplicity, If I don’t find a match, I simply write a debug message and exit, but you could create a new Lead with the phone number, or whatever makes sense in your environment.

With a Contact ID in hand, it’s a snap to populate a Task record with the relevant data and insert it in the database:

And that’s it – all done, in less than 40 lines of Apex.The last step was to create a Force.com Site, and make the MessageToTask endpoint publicly visible, as described in detail here. That gave me a publicly accessible endpoint with a URL of the form https://somesite.force.com/services/apexrest/messageToTask, which I copied into my snippet of JavaScript as the transcriptionOutURI. A couple of quick calls confirmed that all was working as expected!

Here are a couple of messages logged against a Contact:

And here is the detail of one of those:

Now that the Task is saved against the Contact, you’d likely want some Workflow or a Trigger to notify the Contact’s owner that a new message has arrived and, presumably, demands some attention. I’ll leave that as an exercise for the reader 🙂

Note that this is a very basic solution – as it stands, you would need to think about how to authenticate the incoming message. Given that the messages are exchanged over a secure transport, and thus are secure against eavesdropping, a simple shared secret might suffice. You could append a separator and the shared secret to the callerID in the transcriptionID, then parse it out in the Apex class and validate it. There are also other integration approaches that would produce a more secure implementation – watch this space!

What have you integrated with Force.com recently? Let us know in the comments!

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS