Build a Full-Featured IVR App with the SignalWire Realtime SDK

Quickly build a voice app complete with call options, call forwarding, text to speech, and prompts with speech recognition.

Moheeb Zara | Developer Advocate

Aug 17, 2022

The founders of FreeSwitch, an open-source project that is used by telecommunications companies worldwide, created SignalWire to make developing communications app easier and more ubiquitous. 

Following that mantra, the SignalWire Realtime SDK enables you to create powerful communications automation on the fly. We used it to create an example voice automation that reads out multiple options to hear information (hours/location), forward the call to a representative, reprompt, and use speech to text to create bookings. These features encompass what most interactive voice response systems do. Use this example as a launching point for your next big application!

Running the Example

The example is under 100 lines of javascript code, production ready, and can be easily customized. To run the example you can follow the instructions in the GitHub Repository or use this Replit Template that can be run in the browser.

Understanding the Code

The Realtime SDK connects as a RELAY Consumer Voice Client and registers a Context. Context is used in SignalWire to determine where to route calls and messages.

We then create an event handler for received calls. When a call is made to the SignalWire Inbound Phone Number configured to the context for this consumer, they will be passed to this function. Properties of the call are also available, such as call.from and call.to.

Next we want to play a welcome sound, take a pause, and then read out the call options while we prompt the caller. One of the options is to hear all the options again and re-prompt. To reduce redundancy, we can use a feature of the Realtime SDK that allows the creation of playlists.

As shown below we’ve combined playing an audio mp3, text to speech, and silence into a playlist object. That playlist along with the call object gets passed to a custom function, promptCallOptions.

The promptCallOptions function is created so that we can recursively call this function when the caller asks to re-prompt.

The first thing it does is use the call.prompt function to prompt the caller to enter an option into the dial pad. We pass it the playlist object so it knows to play when prompting. By specifying the digits key we’re telling it to accept dial pad digits instead of speech.

We set the max number of digits to input as 1 and the timeout as 2 seconds after pressing. By not indicating a terminator, simply pressing a digit will indicate a selection is confirmed. You can increase the number of digits and specify a terminator if you wanted to ask for something like “Enter your pin followed by the pound key”.

See our developer docs on how Call Prompt works.

We use prompt.waitForResult to block the script until an option is selected. Once selected the script moves on to a switch case. The digits are returned as strings. So we check for the numbers in quotations.

The first option is to simply read out the hours and location and then hangup. Since we don’t need a whole playlist we can just use call.playTTS and use playback.waitForEnded to ensure its read out completely before calling call.hangup.

Option 2 is to make an appointment. Here we first create an event handler for when the prompt has ended so that we can read out the result. Then we initiate a prompt using speech recognition by including the speech key. We set the endSilenceTimout to 3 seconds.

This means as soon as the caller finishes saying their name, number, and reason for calling we accept that as completed input and the event handler will then read out the text in the console.

Once read to the console, call.hangup ends the call. Here you could modify the code to send the recognized text out as an SMS to a provider or call a third party API for making appointments in a calendar.

Option 3 is to restate the options, so we simply call the promptCallOptions function again.

Option 0 using call.connectPhone to forward the call to a Verified Number. This can be used to allow callers to “speak with a representative”.

Wow that was easy! What next?

We’ve now demonstrated and explained how you can quickly and easily write and deploy an IVR application using the SignalWire RELAY Realtime API. The sample performs all the operations you would expect from a standard IVR application. It can receive calls, play sounds, prompt a user to select from a list of options, read out requested information, recognize speech, and forward calls.

What you do next is entirely up to you. Integrate it with a third party API to further automate or dive into what you can do with the Realtime API beyond Voice. It can also be used for Video, Messaging, and Chat.

We hope you take what you’ve learned from this example and build something exciting! Be sure to share it with us and consider submitting to our code bounty program!

Here at SignalWire, we love our community of developers! Find us on the SignalWire Twitter and be sure to join our SignalWire Community Slack. We’re always happy to help answer questions and we look forward to engaging with you!