DTMF Control
DTMF (Dual-Tone Multi-Frequency) tones allow you to interact with calls using keypad input. This enables features like IVR menus, navigating automated systems, and capturing user input.
What is DTMF?
DTMF is the standard telephone signaling method that produces the tones when you press numbers (0-9) or symbols (* and #) on a phone keypad. Each key produces a unique combination of two frequencies.
┌─────┬─────┬─────┬─────┐
│ 1 │ 2 │ 3 │ A │
├─────┼─────┼─────┼─────┤
│ 4 │ 5 │ 6 │ B │
├─────┼─────┼─────┼─────┤
│ 7 │ 8 │ 9 │ C │
├─────┼─────┼─────┼─────┤
│ * │ 0 │ # │ D │
└─────┴─────┴─────┴─────┘
Receiving DTMF Input
Use the gather DTMF action to collect user input:
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/gather-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Press 1 for billing, 2 for support, or 3 for sales.",
"max_digits": 1,
"timeout": 10
}'
Response:
{
"call_id": "call_xyz789",
"digits_collected": "2",
"input_type": "dtmf",
"collected_at": "2024-01-15T10:31:00Z"
}
Gather Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
prompt | string | - | Message to play before collecting input |
max_digits | integer | 1 | Maximum digits to collect |
timeout | integer | 10 | Seconds to wait for input |
finish_key | string | # | Key that finishes input collection |
language | string | en-US | Language for TTS prompt |
voice | string | female | Voice gender for TTS |
interrupt_on_dtmf | boolean | true | Allow user to interrupt prompt by pressing digit |
Using Pre-Recorded Prompts
Instead of TTS, play a recorded audio file:
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/gather-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://example.com/menu-prompt.mp3",
"max_digits": 2,
"timeout": 10,
"finish_key": "#"
}'
Collecting Multiple Digits
Collect longer sequences of input:
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/gather-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Please enter your account number followed by the pound key.",
"max_digits": 15,
"timeout": 30,
"finish_key": "#"
}'
Response:
{
"call_id": "call_xyz789",
"digits_collected": "123456789012345",
"finish_key_pressed": "#",
"collected_at": "2024-01-15T10:31:00Z"
}
Handling DTMF Timeouts
If no input is received within the timeout period:
{
"call_id": "call_xyz789",
"digits_collected": null,
"timeout": true,
"timed_out_at": "2024-01-15T10:31:15Z"
}
Handle timeouts and retry:
async function collectWithRetry(callId, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await gatherDTMF(callId, {
prompt: `Please enter your selection. This is attempt ${i + 1}.`,
max_digits: 1,
timeout: 10
});
if (response.digits_collected) {
return response.digits_collected;
}
} catch (error) {
console.error('Error gathering DTMF:', error);
}
}
// All retries failed
return null;
}
Sending DTMF Tones
Send DTMF tones to the call destination (useful for automating interactions with other systems):
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/send-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"digits": "1234",
"duration": 100,
"pause_between": 100
}'
Send DTMF Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
digits | string | - | DTMF digits to send |
duration | integer | 100 | Milliseconds per digit |
pause_between | integer | 100 | Milliseconds between digits |
Example: Navigating an Automated System
# Call an automated system and navigate to extension 5
curl -X POST https://api.audian.com:8443/v2/calls \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+14155552671",
"to": "+14155552672",
"call_control": {
"on_answered": [
{
"action": "play_audio",
"message": "Navigating to extension 5"
},
{
"action": "send_dtmf",
"digits": "5",
"duration": 100
}
]
}
}'
DTMF Routing
Route calls based on DTMF input during call setup:
curl -X POST https://api.audian.com:8443/v2/calls \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+14155552671",
"to": "+14155552672",
"call_control": {
"on_answered": [
{
"action": "play_audio",
"message": "Press 1 for sales, 2 for support, 3 for billing."
},
{
"action": "gather_dtmf",
"max_digits": 1,
"timeout": 10,
"routes": [
{
"digit": "1",
"action": "transfer",
"destination": "+14155552673"
},
{
"digit": "2",
"action": "transfer",
"destination": "+14155552674"
},
{
"digit": "3",
"action": "transfer",
"destination": "+14155552675"
},
{
"digit": "*",
"action": "repeat_menu"
}
]
}
]
}
}'
DTMF Events
Monitor DTMF input through webhooks:
ivr.input_received
{
"event": "ivr.input_received",
"data": {
"call_id": "call_xyz789",
"menu_id": "menu_main",
"input": "2",
"input_type": "dtmf",
"received_at": "2024-01-15T10:31:00Z"
}
}
ivr.timeout
{
"event": "ivr.timeout",
"data": {
"call_id": "call_xyz789",
"menu_id": "menu_main",
"timeout_duration": 30,
"timed_out_at": "2024-01-15T10:31:30Z"
}
}
DTMF Validation
Validate DTMF input for common use cases:
function validateDTMF(input, rules) {
// Validate format (digits, length, etc.)
if (!input || input.match(/[^0-9#*]/)) {
return {
valid: false,
error: 'Input contains invalid characters'
};
}
if (rules.minLength && input.length < rules.minLength) {
return {
valid: false,
error: `Minimum length is ${rules.minLength}`
};
}
if (rules.maxLength && input.length > rules.maxLength) {
return {
valid: false,
error: `Maximum length is ${rules.maxLength}`
};
}
if (rules.allowedDigits) {
const isValid = input.split('').every(digit =>
rules.allowedDigits.includes(digit)
);
if (!isValid) {
return {
valid: false,
error: `Only these digits are allowed: ${rules.allowedDigits.join(', ')}`
};
}
}
return { valid: true };
}
// Usage
const result = validateDTMF('123', {
minLength: 1,
maxLength: 5,
allowedDigits: ['1', '2', '3', '4', '5']
});
Common DTMF Patterns
Account Lookup
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/gather-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Please enter your 6-digit account number.",
"max_digits": 6,
"timeout": 20,
"finish_key": "#"
}'
PIN Verification
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/gather-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Please enter your 4-digit PIN.",
"max_digits": 4,
"timeout": 15,
"suppress_log": true
}'
Menu Selection
curl -X POST https://api.audian.com:8443/v2/calls/call_xyz789/gather-dtmf \
-H "X-Auth-Token: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Press 1 to repeat this menu, 2 for the main menu, or 0 to speak with an agent.",
"max_digits": 1,
"timeout": 10,
"interrupt_on_dtmf": true
}'
Error Handling
No Input Detected
{
"error": "no_input",
"message": "No DTMF input detected",
"code": 408
}
Invalid Digits
{
"error": "invalid_input",
"message": "Invalid DTMF input detected",
"code": 400
}
Call Disconnected
{
"error": "call_ended",
"message": "Call ended while waiting for DTMF input",
"code": 503
}
Code Examples
Node.js - Menu with Retry
const axios = require('axios');
async function handleMenuWithRetry(callId, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
console.log(`Attempt ${attempt}`);
const response = await axios.post(
`https://api.audian.com:8443/v2/calls/${callId}/gather-dtmf`,
{
prompt: 'Press 1 for sales, 2 for support, or 3 for billing.',
max_digits: 1,
timeout: 10
},
{
headers: {
'Authorization': `Bearer ${process.env.AUDIAN_API_KEY}`
}
}
);
if (response.data.digits_collected) {
return response.data.digits_collected;
}
if (attempt < maxAttempts) {
// Offer to retry
await axios.post(
`https://api.audian.com:8443/v2/calls/${callId}/play-audio`,
{
message: 'Sorry, I did not hear a valid selection. Please try again.',
participant: 'callee'
},
{
headers: {
'Authorization': `Bearer ${process.env.AUDIAN_API_KEY}`
}
}
);
}
} catch (error) {
console.error(`Attempt ${attempt} failed:`, error.response?.data);
}
}
return null;
}
Python - Account Lookup
import requests
import os
def lookup_account(call_id):
url = f'https://api.audian.com:8443/v2/calls/{call_id}/gather-dtmf'
headers = {
'Authorization': f"Bearer {os.getenv('AUDIAN_API_KEY')}",
'Content-Type': 'application/json'
}
payload = {
'prompt': 'Please enter your 6-digit account number.',
'max_digits': 6,
'timeout': 20,
'finish_key': '#'
}
try:
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data.get('digits_collected'):
account_number = data['digits_collected']
print(f'Account: {account_number}')
return account_number
else:
print('Timeout - no input received')
return None
except requests.exceptions.RequestException as e:
print(f'Error: {e}')
return None
Best Practices
- Clear prompts: Make menu options clear and concise
- Allow interruption: Let users interrupt prompts with DTMF
- Set proper timeouts: 10-30 seconds depending on use case
- Provide feedback: Confirm selections back to the user
- Handle retries: Offer 2-3 attempts before connecting to agent
- Validate input: Check input format and length
- Suppress logging: Don't log sensitive input (PINs, account numbers)