An IVR (Interactive Voice Response) system is the technology behind 'Press 1 for sales, press 2 for support.' Building one used to require expensive hardware. Today, you can build a fully featured IVR with Python and a voice API in an afternoon.
What we will build
- A greeting menu with 3 department options
- Routing based on caller input
- Graceful handling of invalid input
- Call recording for quality assurance
Setup
pip install wirexaapi flask
1. Originate the call
call = client.calls.create(
to="+15551234567",
from_="+15559876543",
url="https://your-backend.com/ivr",
record=True,
)2. Main menu
@app.route('/ivr', methods=['POST'])
def ivr_main():
xml = '''<Response>
<Gather numDigits="1" timeout="8" action="/ivr/route">
<Say language="en-US" voice="polly.Joanna">
Thank you for calling. Press 1 for Sales.
Press 2 for Support. Press 3 for Billing.
</Say>
</Gather>
<Redirect>/ivr</Redirect>
</Response>'''
return Response(xml, mimetype='text/xml')3. Route by digit
@app.route('/ivr/route', methods=['POST'])
def ivr_route():
digit = request.form.get('Digits', '')
routes = {
'1': ('Sales', '/ivr/sales'),
'2': ('Support', '/ivr/support'),
'3': ('Billing', '/ivr/billing'),
}
if digit in routes:
name, path = routes[digit]
xml = f'<Response><Say>Connecting to {name}.</Say><Redirect>{path}</Redirect></Response>'
else:
xml = '<Response><Say>Invalid option.</Say><Redirect>/ivr</Redirect></Response>'
return Response(xml, mimetype='text/xml')Tips for production IVRs
- Keep menus to 4 options or fewer — callers forget longer lists
- Always offer a way to repeat and to reach a human agent
- Use short, clear Say text — avoid complex sentences
- Enable call recording from day one for QA and compliance
- Log
Digitsfrom every Gather to analyze drop-off points
Next steps
This IVR runs entirely from Python + Flask with no special hardware. You can extend it with database lookups, CRM integrations, or real-time agent transfers.
Read the full API reference or contact us to set up your account.