How to integrate interactive voice response into Django with Twilio

We have all heard those automated voice recorders at one point or other perhaps when making a call to the bank or a support hotline. What tends to happen when you make the call to such an institution is you are greeted with an automated voice recorder which would sound something like “Welcome to CompanyA for English press 1 for untuk Bahasa Indonesia tekan angka dua”. Such automated voice systems are referred to as IVR’s. Interactive Voice systems. Systems that take certain actions based on the keypad input from your phone. IVR’s streamline support operations or could be used for the purpose of collecting data. In this tutorial, we are going to see how we can do that in Django fairly quickly.


  • Have python installed version 2.7 to 3.5
  • Create a free Twilio trial account ( no credit card required). Sign up here.

To give you an idea of what Twilio is. If you have used PAAS services like Heroku, Openshift then Twilio would be the equivalent version tailored for telephony communications. Twilio service your code to interact with voice, video, SMS messaging. Imagine being able to take part in a survey or cast your vote while based in the remote parts of the world without access to the internet through conventional SMS and have all that data cataloged.  Such use cases are perfect for Twilio like services.

Getting Started

Twilio uses a simple concept that allows mobile communication to occur between your web application and your mobile device through the use of TwiloXML (TwiML)which are routed through a REST API service. Your application receives instructions from Twilio in the form of TwiML to perform an action. How this is achieved is via predefined verbs that you can execute within your web application as outlined below.

List of Twilio verbs

Say – Read text to the caller
Play – Play an audio file for the caller
Dial – Add another party to the call
Record – Record the caller’s voice
Gather – Collect digits the caller types on their keypad
Sms – Send an SMS message during a phone call
Hangup – Hang up the call
Queue – Add the caller to a queue of callers.
Redirect – Redirect call flow to a different TwiML document.
Pause – Wait before executing more instructions
Reject – Decline an incoming call without being billed.
Message – Send an MMS or SMS message reply

We do not need to explicitly write TwiML since Twilio provides helper libraries in a variety of languages not limited to Python which abstracts the creation of TwiML. Now in order to achieve this intercommunication in Django, let go ahead and create a simple Django project and prep up our virtual environment.

The above version of Django is not a strict requirement you may choose to use the latest stable release if you wish to do so. We will take advantage of Twilio-python library, so we do not need to fiddle with the XML DOM manually.

Create the Django view

With our view, when a caller makes a call to a Twilio number. Twilio will lookup the associated URL attached to the phone number and make a request to that URL, this URL will route to our above view. Which will return instructions with which next instruction to perform e.g make a call, play a message, prompt the caller to input digit(s) on their keypad. The Gather verb is responsible for collecting user input and Twilio will forward the request to an action URL.

Within the let’s create the user response handler function that will handle users response based on initial_automated_call questions function.

Configure Django’s URL configuration to link the view to a URLs

Before moving forward let’s summarize code. Twilio response library correctly formats the requests and responses so you don’t have to into XML format that conforms to what Twilio requirements. Within the function, we are creating a new response, adding the Gather and Say verbs, and then returning it all back. In the gather call, we are setting num_digits to 1. This explicitly tells Twilio accept 1 digit nothing more. We have used the response.redirect(‘/gather/’) command to repeat the question in the event no response is given by the caller. In our Django URL configurations, we have added a mapping to both endpoints which will be accessible when you boot up your server at localhost8000/gather or /respond.

The last thing you want to do is navigate to your Django and ensure you comment out CRSF and link jacking middleware as we do not need those for our example. IF you do not do this Twilio won’t be restricted access to your Django URL routes. Do take note in a production environment you would need to ensure you handle security for your exposed Twilio endpoints perhaps whitelisting so that only Twilio is authorized to access.

This will run you server on port 8000, but take note if you’re running this on your local you need to download a handy tool called ngrok that allows you to generate a temporary domain that maps to your localhost. In essence, we are creating webhook that Twilio will be able to call based on actions you have written. Ngrok will elevate the need to deploy our app for quick testing as it assigns a tempory domain name which tunnels to our localhost. Take note ngrok is a single executable no installation is required. Just unzip and your good to go.

In a Terminal window, navigate to the directory where you unzipped ngrok. To make it easier to use you may also want to add it to your Windows or Linux paths so that you do not explicitly have to navigate to the ngrok directory. In order to start ngrok issue the below command.

Linux/Mac:  ./ngrok 8000

Windows: ngrok 8000

Once ngrok is fired up, you should see HTTP & HTTPS temporary domains that link back to your local Django development server. Next step is to configure your Twilio number to point to your temporary domain.

Configure Twilio to work with our local machine

Within your Twilio account dashboard, navigate to list of incoming numbers and choose one to work with. Enter your ngrok URL, including the “/gather” route, as shown in the image below. Also, make sure to change the HTTP request type to a “GET” rather than a “POST”. Save your changes. This process finalizes the Link between your Django URL routes and your Twilio number.

twilio number configuration

Let’s test everything out and see what actually happens. Call the number located within your Twilio account, do take note local call charges will apply though negligible. Since your running on a trial account, the first initial message will just give you a heads up that this is a trial account press any button to execute your code. Follow the call instructions and watch your runserver console terminal.

We’ve demonstrated the basics of receiving user input via Twilio and routing input to our Django app to take further action and issue a responds back to the caller via SMS. We have barely begun diving deeper hopefully you should see the potential. With Twilio’s list of verbs and actions available it’s pretty easy to start creating a fully fledged IVR app or sub-component for your web applications.

The source code for this article can be found on github, do feel free to download and try it out.