Asterisk IVR: Advance IVR Asterisk (Latest Versions)
Updated guide for modern Asterisk (PJSIP era): advance ivr asterisk with real configs, common mistakes, and troubleshooting steps.
A basic IVR works for small teams, but real businesses quickly need more: multiple levels, smart routing, office-hour handling, queue awareness, customer-specific flows, and clean failover.
This is where advanced IVR design in Asterisk matters. Advanced IVR is not about adding more menu options — it is about building decision-based call journeys.
This guide shows how to build advanced IVRs in modern Asterisk (PJSIP-based) using dialplan best practices: reusable contexts, subroutines, variables, database checks, and production-safe looping rules.
What Makes an IVR “Advanced”?
Advanced IVR typically includes:
- Multi-level menus (main menu → department menu)
- Office hours routing (open vs closed)
- Queue-aware routing (if queue too busy, offer callback)
- VIP caller routing (database-driven priority)
- Language selection (Hindi/English) prompts
- Skill-based routing (sales vs support tiers)
- Reusable building blocks (subroutines)
Recommended Folder/Prompt Strategy
For maintainability, keep prompts organized:
/var/lib/asterisk/sounds/custom/ivr/
main-menu.wav
sales-menu.wav
support-menu.wav
closed.wav
invalid.wav
no-input.wav
Use consistent naming and avoid changing filenames often.
Advanced IVR Architecture (Clean Dialplan Structure)
A good structure separates:
- Inbound entry (from-trunk) → only routes into IVR
- Decision logic → office hours, VIP checks, language
- Menu contexts → main menu and submenus
- Destinations → queues, ring groups, voicemail
This makes the IVR readable and scalable.
Step 1 — Main Entry: Decide Open vs Closed
Use a simple time decision first.
[from-trunk]
exten => s,1,Answer()
same => n,Gosub(ivr-common,s,1)
same => n,Hangup()
[ivr-common]
exten => s,1,NoOp(IVR common entry)
same => n,Set(TIMEOUT(digit)=3)
same => n,Set(TIMEOUT(response)=5)
; Example open hours check (Mon-Sat 10:00-19:00)
same => n,GotoIfTime(10:00-19:00,mon-sat,*,*?open:closed)
same => n(open),Gosub(ivr-main,s,1)
same => n,Return()
same => n(closed),Playback(custom/ivr/closed)
same => n,Voicemail(1000@default,u)
same => n,Return()
Step 2 — Main Menu with Controlled Loops
Advanced IVR must avoid infinite loops. Use a counter variable.
[ivr-main]
exten => s,1,NoOp(Main IVR)
same => n,Set(IVR_TRIES=$[${IF($["${IVR_TRIES}"=""]?0:${IVR_TRIES})}+1])
same => n,GotoIf($[${IVR_TRIES} > 3]?fail,1)
same => n,Background(custom/ivr/main-menu)
same => n,WaitExten(6)
; Sales submenu
exten => 1,1,Gosub(ivr-sales,s,1)
same => n,Goto(ivr-main,s,1)
; Support submenu
exten => 2,1,Gosub(ivr-support,s,1)
same => n,Goto(ivr-main,s,1)
; Operator / fallback
exten => 0,1,Goto(destinations,operator,1)
; Invalid
exten => i,1,Playback(custom/ivr/invalid)
same => n,Goto(ivr-main,s,1)
; No input
exten => t,1,Playback(custom/ivr/no-input)
same => n,Goto(ivr-main,s,1)
exten => fail,1,Playback(custom/ivr/all-agents-busy)
same => n,Goto(destinations,operator,1)
Step 3 — Submenus (Sales / Support)
Sales submenu example:
[ivr-sales]
exten => s,1,NoOp(Sales submenu)
same => n,Background(custom/ivr/sales-menu)
same => n,WaitExten(6)
; New sales → queue
exten => 1,1,Goto(destinations,sales_queue,1)
; Existing customer → ring group
exten => 2,1,Goto(destinations,sales_ringgroup,1)
; Back to main menu
exten => 9,1,Return()
exten => i,1,Playback(custom/ivr/invalid)
same => n,Goto(ivr-sales,s,1)
exten => t,1,Return()
Support submenu example:
[ivr-support]
exten => s,1,NoOp(Support submenu)
same => n,Background(custom/ivr/support-menu)
same => n,WaitExten(6)
; Technical support
exten => 1,1,Goto(destinations,support_queue,1)
; Complaints
exten => 2,1,Goto(destinations,complaints_queue,1)
; Back
exten => 9,1,Return()
exten => i,1,Playback(custom/ivr/invalid)
same => n,Goto(ivr-support,s,1)
exten => t,1,Return()
Step 4 — Destinations Context (Single Place for Routing)
Keep all final call actions in one context.
[destinations]
exten => sales_queue,1,Playback(custom/ivr/connecting-sales)
same => n,Queue(sales,tT)
same => n,Voicemail(2000@default,u)
same => n,Hangup()
exten => support_queue,1,Playback(custom/ivr/connecting-support)
same => n,Queue(support,tT)
same => n,Voicemail(1000@default,u)
same => n,Hangup()
exten => complaints_queue,1,Queue(complaints,tT)
same => n,Voicemail(3000@default,u)
same => n,Hangup()
exten => sales_ringgroup,1,Dial(PJSIP/1005&PJSIP/1006,20)
same => n,Hangup()
exten => operator,1,Dial(PJSIP/1000,20)
same => n,Voicemail(1000@default,u)
same => n,Hangup()
This makes future maintenance much easier.
Advanced Enhancement: Queue Busy Awareness (Offer Callback)
When queues get overloaded, callers should not wait forever. You can detect current waiting callers from CLI and integrate logic.
Practical approach:
- If queue has too many waiting callers → route to voicemail or callback flow
- Otherwise → enter queue normally
Many businesses implement callback using CRM or external systems. Asterisk dialplan can trigger those workflows via AGI/ARI/HTTP.
Advanced Enhancement: VIP Routing with AstDB
Example VIP flag:
Set(DB(vip/${CALLERID(num)})=yes)
In IVR entry:
same => n,GotoIf($["${DB(vip/${CALLERID(num)})}"="yes"]?vip,1)
exten => vip,1,Playback(custom/ivr/vip-welcome)
same => n,Queue(priority-support,tT)
same => n,Hangup()
This provides premium support routing with minimal complexity.
Common Advanced IVR Problems and Fixes
DTMF Works Internally But Not Externally
- Trunk DTMF mode mismatch (RFC4733 vs INFO vs inband)
- Codec mismatch causing inband DTMF loss
Menus Become Unmaintainable
- Too much logic in one context
- Fix: split into common / menu / destinations contexts
Callers Get Stuck in Loops
- No loop counter
- Fix: IVR_TRIES pattern and fail route
Best Practices for Advanced IVRs
- Design menus based on business outcomes, not features
- Keep prompts short and human-recorded
- Limit loops and provide operator fallback
- Separate dialplan into reusable contexts
- Test with real external calls and real SIP trunk conditions
Advanced IVR is a customer experience system — build it like a product, not a script.
Key Takeaway
Advanced IVR in Asterisk is about clean architecture: reusable logic (Gosub), clear menus, controlled looping, office-hour decisions, and smart destinations.
With the right structure, you can scale your IVR from 2 options to a full enterprise call journey without chaos.
Want to see API-driven CRM + Telecom workflows in action? Try the WhatsApp bot or explore the demos.