Ten percent of my work time is dedicated to professional development through two āHackdaysā a month. For my most recent Hackdays I wanted to combine old-school phone technology with āmodernā web technoligies. I came across a service called Plivo which lets you work with the phone network through a web API.
What is Plivo?
Plivo is a web service that gives us a web API to interact with the phone network. You rent a number with Plivo and pay a charge for each minute of calling or SMS message sent.
What can Plivo do?
There seems to be a lot of things you can do with Plivo, but the main ones are:
- Sending and receiving SMS messages.
- Receiving inbound calls and making outbound calls.
- On a call you can:
- Convert text to speech.
- Play audio by providing a URL to an MP3 file.
- Accept digits from callers (e.g.: āpress 1 for salesā in phone menus).
Making something with Plivo!
My initial plan was to implement a game of Hangman over SMS, especially considering Iād written a game of Hangman back on my devtrain. However, I quickly discovered that Plivo didnāt support receiving SMS messages in New Zealand, only sending them. Next I thought Iād just make a phone call based Hangman game, but sadly Plivo doesnāt support speech recognition making it difficult to receive character inputs.
Instead, I ended up implementing a simple number guessing game. This was a great place to start because the logic for such a game is very simple which allowed me to focus on the phone integration side. The game chooses a random number between 1 and 100 and asks the caller to guess the number by entering it on their dialpad. The game gives feedback on whether the guess is correct or higher/lower than the actual number. If the guess is wrong the caller can keep guessing until they get it correct.
How do I work with Plivo for calling?
Something I was unsure about initially was how youād actually handle a call. Iād assumed that after a call was picked up that youād need to deal with the audio stream yourself, but in fact, Plivo handles the entire audio stream for you!
When a call comes in, Plivo hits your API which provides a set of instructions in XML. Depending on the actions you ask for, you may need to define a callback URL for Plivo to hit later with more data (e.g.: a URL for it to hit for instructions after receiving digits from the caller).
It takes a little while to think about phone calls in terms of API requests, but this approach means that you can scale your phone system just like you scale your normal web APIās.
Implementation time!
I used Node and Plivoās Node SDK to build the hotlineās API. Plivoās SDK handles all the XML instruction formatting for you, making implementation very simple. A good reference for this was Plivoās Phone IVR guide which introduces all the Plivo functionality I used for the project.
The game is pretty simple, it consists of only two endpoints for Plivo to hit; one for when the call is initially made to welcome the caller (and prompt them to enter a guess) and the other as a callback for the callerās guess.
Welcome Route
When a call comes in, Plivo hits the /
route with a GET
request and the route returns the following XML to instruct Plivo:
<Response>
<Speak>Welcome to the number guessing hotline.</Speak>
<GetDigits action="[server URL]/guess?number=[chosen random number]" method="POST" timeout="10" numDigits="2" retries="3">
<Speak>What is your guess?</Speak>
<Play>[server URL]/elevator_music.mp3</Play>
</GetDigits>
<Speak>Huh? I didn't understand. Could you try again?</Speak>
</Response>
This simply tells Plivo to speak a welcome message then allow the caller to enter some digits with a defined callback URL. Plivo will ask the caller what their guess is and play some music while the caller enters their digits.
If the GetDigits
action fails (e.g.: the caller takes too long) then the wrong input message is spoken.
Guess checking route
When the caller has entered some digits, Plivo will hit the guess URL with a POST
request. Plivo puts the entered digits in a āDigitsā field in the request (if youāre testing this out for yourself in a tool like Postman use the x-www-form-urlencoded
format of POST
body).
In addition to this, you may have noticed in the XML above, the games chosen random number is a query string parameter in the callback URL. This is because Iām super lazy and I didnāt want to have to persist the chosen random number for a call in a database. Getting Plivo to pass this parameter around for us means we can easily scale up the number of app servers as required for the millions of simultaneous calls required by our booming number guessing hotline startup!
You can checkout the code for the guess route, but it yet again returns some XML for Plivo:
<Response>
<Speak>You guessed too [low/high]!</Speak>
<GetDigits action="[server URL]/guess?number=[chosen random number]" method="POST" timeout="10" numDigits="2" retries="3">
<Speak>What is your guess?</Speak>
<Play>[server URL]/elevator_music.mp3</Play>
</GetDigits>
<Speak>Huh? I didn't understand. Could you try again?</Speak>
</Response>
Once again this makes use of GetDigits
to prompt the caller for a further guess, making use of the same callback URL with the random number.
Or if the caller gets the number correct then it simply returns a simple <Speak>
response. After this is spoken Plivo has no more instructions so will just hangup on the caller.
You can checkout all the code on GitHub at jordancrawfordnz/number-guessing-hotline
Setting the hotline up on Plivo
When a call comes in, Plivo needs to hit a public API endpoint that we provide. This means we need to host our API somewhere on the internet.
If you arenāt comfortable with SSHāing into a server to setup your app, Heroku is a good option that takes care of all the server management stuff for you. If you want to save a bit of money and donāt mind running the app server yourself then something like Hetzner, Digital Ocean or Vultr will work great. All these options use hourly (or in the case of Heroku, secondly!) billing so it wonāt cost you much to mess around with Plivo. This might also be a good candidate for Serverless given the simplicity of our application code.
Next, buy a number through Plivo then create an application with your server URL as the answer URL and assign your number to your application.
You should now be able to call up your number and enjoy the phone hotline built with less than 100 lines of JavaScript!
Edit, 11 March 2018 The Plivo team also published this over on their company blog!
Edit, 5th May 2024 Some links have been fixed to point at newer versions of the Plivo docs.