Gather User Input with Keypad
Learn to gather user input through a phone's keypad with Twilio Programmable Voice by using the TwiML <Gather> verb to capture DTMF tones during a live call. You can use this guide to send voice notifications, create self-service automation, build inbound contact centers, and create outbound contact centers.
See Related reference documentation to learn more about the TwiML elements used in this guide.
- Create a Twilio account.
- In the Twilio Console, create a compliance profile, then buy a voice-enabled phone number.
- In the legacy Console, buy a voice-enabled phone number. Only Messaging-enabled phone numbers need a compliance profile.
Select your programming language and complete the prerequisites:
- Install Python 3.3 or later.
- Install Flask and the Twilio Python Helper Library. Using pip, run the following command:
pip install flask twilio
- Install and set up ngrok.
Extract your credentials from your Twilio account then save these credentials as environment variables.
-
Go to the Twilio Console. The Let's get building page appears.
-
Click API keys and Auth tokens. The API keys & auth tokens page appears with the Auth Tokens tab selected.
-
Scroll to your Account SID.
-
Click the copy button next to your Account SID.
-
Run the following command, replacing
YOUR_ACCOUNT_SIDwith your Account SID.macOS TerminalWindows command linePowerShellexport TWILIO_ACCOUNT_SID=YOUR_ACCOUNT_SIDThis command creates an environment variable on your development system for your account SID.
-
To display the Auth Token, click the eye button in the Primary auth token box.
-
Highlight and copy the Auth Token.
-
Run the following command, replacing
YOUR_AUTH_TOKENwith your Authentication Token.macOS TerminalWindows command linePowerShellexport TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKENThis command creates an environment variable on your development system for your auth token.
To learn more about features, see Interactive Voice Response.
To collect input from the user during a phone call, use the <Gather> TwiML verb. IVR systems rely on user input from the keypad.
Using the TwiML <Say> and <Play> verbs, you program the IVR voice prompts. When the IVR answers a call, it asks end users to make decisions using their phone keypad.
To forward the call to one department, the IVR tells the end user to press 1. For a different department, the IVR tells the end user to press 2.
This guide prompts the end user for a number that connects them to a certain department within the IVR system.
Python only requires the Twilio Python helper library as noted in the prerequisites.
1from flask import Flask2from twilio.twiml.voice_response import VoiceResponse, Gather34app = Flask(__name__)567@app.route("/voice", methods=['GET', 'POST'])8def voice():9"""Respond to incoming phone calls with a menu of options"""10# Start our TwiML response11resp = VoiceResponse()1213# Start our <Gather> verb14gather = Gather(num_digits=1)15gather.say('For sales, press 1. For support, press 2.')16resp.append(gather)1718# If the user doesn't select an option, redirect them into a loop19resp.redirect('/voice')2021return str(resp)2223if __name__ == "__main__":24app.run(debug=True)
Twilio waits for end user input. How long Twilio waits depends on the timeout you set. If the end user doesn't enter any input within this period, Twilio processes the call using other instructions in the TwiML document. When Twilio reaches the end of the TwiML document, it ends the call.
Without any end user input, Twilio repeats the prompt. To repeat the prompt, this code uses the <Redirect> verb.
The previous code doesn't include any logic that processes end user input.
Twilio repeats the prompt endlessly regardless of end user actions.
By default, if the user does enter input in the <Gather>, Twilio sends another HTTP request to the current webhook URL with a POST parameter containing the Digits entered by the user.
In the sample above, we weren't handling this input at all. Let's update that logic to also process user input if it is present.
1from flask import Flask, request2from twilio.twiml.voice_response import VoiceResponse, Gather34app = Flask(__name__)567@app.route("/voice", methods=['GET', 'POST'])8def voice():9"""Respond to incoming phone calls with a menu of options"""10# Start our TwiML response11resp = VoiceResponse()1213# If Twilio's request to our app included already gathered digits,14# process them15if 'Digits' in request.values:16# Get which digit the caller chose17choice = request.values['Digits']1819# <Say> a different message depending on the caller's choice20if choice == '1':21resp.say('You selected sales. Good for you!')22return str(resp)23elif choice == '2':24resp.say('You need support. We will help!')25return str(resp)26else:27# If the caller didn't choose 1 or 2, apologize and ask them again28resp.say("Sorry, I don't understand that choice.")2930# Start our <Gather> verb31gather = Gather(num_digits=1)32gather.say('For sales, press 1. For support, press 2.')33resp.append(gather)3435# If the user doesn't select an option, redirect them into a loop36resp.redirect('/voice')3738return str(resp)3940if __name__ == "__main__":41app.run(debug=True)
You may want to have an entirely different endpoint in your app handle the processing of user input. This is possible using the "action" attribute of the <Gather> verb. Let's update our example to add a second endpoint that will be responsible for handling user input.
1from flask import Flask, request2from twilio.twiml.voice_response import VoiceResponse, Gather34app = Flask(__name__)567@app.route("/voice", methods=['GET', 'POST'])8def voice():9"""Respond to incoming phone calls with a menu of options"""10# Start our TwiML response11resp = VoiceResponse()1213# Start our <Gather> verb14gather = Gather(num_digits=1, action='/gather')15gather.say('For sales, press 1. For support, press 2.')16resp.append(gather)1718# If the user doesn't select an option, redirect them into a loop19resp.redirect('/voice')2021return str(resp)222324@app.route('/gather', methods=['GET', 'POST'])25def gather():26"""Processes results from the <Gather> prompt in /voice"""27# Start our TwiML response28resp = VoiceResponse()2930# If Twilio's request to our app included already gathered digits,31# process them32if 'Digits' in request.values:33# Get which digit the caller chose34choice = request.values['Digits']3536# <Say> a different message depending on the caller's choice37if choice == '1':38resp.say('You selected sales. Good for you!')39return str(resp)40elif choice == '2':41resp.say('You need support. We will help!')42return str(resp)43else:44# If the caller didn't choose 1 or 2, apologize and ask them again45resp.say("Sorry, I don't understand that choice.")4647# If the user didn't choose 1 or 2 (or anything), send them back to /voice48resp.redirect('/voice')4950return str(resp)5152if __name__ == "__main__":53app.run(debug=True)
The action attribute accepts a relative URL. This URL points to another route that your server can handle. To handle our call logic with separate code paths, use actions and redirects.
This guide covers a feature for the following use cases:
You can use this guide to send voice notifications that require a quick user response. For example, you can programmatically alert users about fraudulent activity on an account and prompt them to confirm or deny the transaction immediately using their phone's keypad.
To learn more advanced features that you can use with voice notifications, see Voice notifications.
You can use this guide to build phone systems that resolve customer requests without human intervention. For example, callers can securely authenticate their identity, check their bank account balance, or update an appointment status entirely by using keypad menus.
To learn more advanced features that you can use with self-service automation, see Voice self-service automation.
You can use this guide to route incoming customer calls to the right agent or department efficiently. By deploying an interactive keypad menu, you can direct customers based on their explicit selections, minimizing wait times and transfers.
To learn more advanced features that you can use with inbound contact centers, see Voice inbound contact center.
You can use this guide to enhance proactive customer outreach with immediate routing controls. For example, when an outbound dialer connects with a customer, it can offer keypad options to speak with a live agent, schedule a callback, or opt out of future communications.
To learn more advanced features that you can use with outbound contact centers, see Voice outbound contact center.
After following this guide, you can successfully collect DTMF tones from a user's telephone keypad during a phone call using Twilio Programmable Voice. You can test your system by calling your Twilio phone number, pressing the keypad buttons when prompted, and verifying that your application branches its logic based on the collected digits.
Explore the following guides to build on what you've learned in this guide:
- Build an Interactive Voice Response (IVR) phone tree: Step through full sample applications to construct advanced multi-level menus.
- Respond to incoming phone calls: Learn how to handle inbound webhooks and generate initial TwiML responses for your callers.
- Make outbound phone calls: Learn how to programmatically initiate outbound calls and generate TwiML responses for those calls.