Capturing DTMF Input with Read()
Capturing DTMF Input with Read()
Read() plays a sound prompt and waits for the caller to enter DTMF digits, storing the result in a channel variable. This is the foundation of PIN entry, extension lookups, account number input, and any IVR that needs numeric data from the caller.
Basic Example
[ivr]
exten => s,1,Answer()
same => n,Wait(1)
same => n,Read(DIGITS,enter-ext-of-person,4)
same => n,Playback(you-entered)
same => n,SayNumber(${DIGITS})
same => n,Hangup()
PIN Verification
[pin-entry]
exten => s,1,Answer()
same => n,Read(PIN,agent-pass,6)
same => n,GotoIf($["${PIN}" = "123456"]?valid:invalid)
same => n(valid),Playback(auth-thankyou)
same => n,Goto(internal,s,1)
same => n(invalid),Playback(vm-incorrect)
same => n,Goto(s,1)
Extension Lookup
[dial-by-extension]
exten => s,1,Answer()
same => n,Read(EXT,enter-ext-of-person,4,,,5)
same => n,GotoIf($["${EXT}" = ""]?timeout)
same => n,Dial(PJSIP/${EXT},20)
same => n,Hangup()
same => n(timeout),Playback(vm-goodbye)
same => n,Hangup()
How it works
- Read(variable,filename,maxdigits,options,attempts,timeout): Plays the sound file and waits for DTMF input. Digits are collected until
maxdigitsis reached or the caller presses#. The result is stored invariable. - maxdigits: Limits how many digits are accepted. For a 4-digit extension, use
4. For open-ended input, omit this parameter and the caller terminates with#. - timeout: The last parameter is the timeout in seconds. If the caller doesn't press any key within this time,
Read()returns with an empty variable. Default is 10 seconds if not specified. - Sound files:
enter-ext-of-personandyou-enteredare built-in Asterisk sound files. They're searched in/var/lib/asterisk/sounds/<language>/. UsePlayback()beforeRead()if you need to play additional context. - Empty input: Always check for empty input with
GotoIf($["${DIGITS}" = ""]?label)to handle timeouts and callers who don't enter anything.
Tips
- For multi-digit input where you don't know the length, omit
maxdigitsand let the caller press#to finish:Read(DIGITS,enter-your-account-number). - Chain
Read()withSayDigits()orSayNumber()to read back the input for confirmation. - For a retry loop, use a counter:
Set(TRIES=0)then increment on invalid input andGotoIf($[${TRIES} < 3]?retry). Read()only captures digits 0-9,*, and#. The#key terminates input by default. To accept#as input, use thenoption.- Combine with
CHANNEL(language)to play localized prompts:Set(CHANNEL(language)=es)switches to Spanish prompts. - For IVR menus where each digit routes to a different destination, use
Background()+WaitExten()instead ofRead(): they're designed for single-key menus.
User Notes
No notes yet. Be the first to contribute a tip or example.
Contribute a note
Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.