This webhook server enables ElevenLabs voice agents to send DTMF tones (phone keypad presses) to navigate IVR systems when making outbound calls via Twilio.
- ✅ Send DTMF tones to active Twilio calls
- ✅ Track active call sessions
- ✅ Receive Twilio call status webhooks
- ✅ Health check endpoint
- ✅ Comprehensive logging
pip install -r requirements.txtCopy the example environment file:
cp .env.example .envEdit .env and add your Twilio credentials:
TWILIO_ACCOUNT_SID=your_actual_account_sid
TWILIO_AUTH_TOKEN=your_actual_auth_token
Get these from: https://console.twilio.com
python app.pyServer will start on http://localhost:8080
curl http://localhost:8080/healthSend DTMF tones to an active call.
Request:
{
"digits": "1",
"call_sid": "CAxxxxxxxxxxxxx"
}Response:
{
"success": true,
"message": "Sent DTMF: 1",
"call_sid": "CAxxxxxxxxxxxxx",
"digits": "1",
"timestamp": "2025-11-12T18:30:00"
}Twilio status callback endpoint. Configure in Twilio Console.
Health check endpoint.
List currently active calls.
- Install Railway CLI: https://docs.railway.app/develop/cli
- Run:
railway login
railway init
railway up- Create account at https://render.com
- Connect your GitHub repo
- Add environment variables in Render dashboard
- Deploy
- Install flyctl: https://fly.io/docs/hands-on/install-flyctl/
- Run:
fly launch
fly secrets set TWILIO_ACCOUNT_SID=xxx TWILIO_AUTH_TOKEN=xxx
fly deploy- Go to Twilio Console → Phone Numbers
- Select your ElevenLabs phone number
- Under "Voice Configuration":
- Status Callback URL:
https://your-webhook-url.com/webhook/call-status - Check: Initiated, Ringing, Answered, Completed
- Status Callback URL:
- Save
- In your ElevenLabs agent → Tools → send_dtmf
- Edit the webhook URL to:
https://your-webhook-url.com/send-dtmf - Save
Test DTMF sending:
curl -X POST http://localhost:8080/send-dtmf \
-H "Content-Type: application/json" \
-d '{"digits": "1", "call_sid": "CAxxxxx"}'Issue: "Twilio client not initialized"
- Solution: Check that TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN are set correctly
Issue: "No active call found"
- Solution: Ensure Twilio Status Callback is configured correctly
- Or pass call_sid explicitly in the request
Issue: DTMF not being sent
- Solution: Verify the call_sid is correct and the call is still active
All requests and errors are logged to console with timestamps.
Monitor logs:
tail -f app.log # if using file logging- Always use HTTPS in production
- Keep your Twilio credentials secure
- Consider adding authentication to webhook endpoints
- Use environment variables, never hardcode credentials
MIT