Not Receiving StasisStart Events in Node.js ARI App after Dialplan Configuration (FreePBX/Asterisk)

Hello everyone,

I’m setting up a custom IVR using FreePBX and Node.js ARI client.
I have created a context [ivr-incoming] inside extensions_custom.conf like this:

[ivr-incoming]
exten => s,1,NoOp(Incoming call to IVR)
 same => n,Answer()
 same => n,Stasis(ivrapp)
 same => n,Hangup()

In Node.js, I am connecting to ARI and listening to StasisStart like this
client.start(‘ivrapp’);
client.on(‘StasisStart’, (event, channel) => {
console.log(“StasisStart event:”, event);
console.log(“Channel:”, channel);
});
What happens:

  • Call rings on Zoiper.
  • Call is answered.
  • But StasisStart never fires.
  • Node.js console shows no events.

Checks I have done:

  • ARI user permissions are fine.
  • ari.conf configured correctly (enabled = yes, pretty = yes, allowed_origins = *).
  • Node.js app connects successfully to ARI (✅ ARI Connected Successfully!).
  • Application ivrapp is visible when listing client.Application().list().
  • Reloaded dialplan (dialplan reload).
  • No firewall issue.

My Question: ➔ Why am I not getting StasisStart events?
➔ What should I fix in the Dialplan or ARI settings?

You haven’t actually shown what happens when a call is done on the Asterisk console, or confirmed that the call is being routed to the ARI application.

Hi,
Thank you for your repsonse.

-= 2 extensions (5 priorities) in 1 context. =-
    -- Executing [s@from-pstn:1] Set("PJSIP/zeus-00000227", "__DIRECTION=INBOUND") in new stack
    -- Executing [s@from-pstn:2] Gosub("PJSIP/zeus-00000227", "sub-record-check,s,1(in,s,dontcare)") in new stack
    -- Executing [s@sub-record-check:1] GotoIf("PJSIP/zeus-00000227", "0?initialized") in new stack
    -- Executing [s@sub-record-check:2] Set("PJSIP/zeus-00000227", "__REC_STATUS=INITIALIZED") in new stack
    -- Executing [s@sub-record-check:3] Set("PJSIP/zeus-00000227", "NOW=1746046750") in new stack
    -- Executing [s@sub-record-check:4] Set("PJSIP/zeus-00000227", "__DAY=30") in new stack
    -- Executing [s@sub-record-check:5] Set("PJSIP/zeus-00000227", "__MONTH=04") in new stack
    -- Executing [s@sub-record-check:6] Set("PJSIP/zeus-00000227", "__YEAR=2025") in new stack
    -- Executing [s@sub-record-check:7] Set("PJSIP/zeus-00000227", "__TIMESTR=20250430-205910") in new stack
    -- Executing [s@sub-record-check:8] Set("PJSIP/zeus-00000227", "__FROMEXTEN=unknown") in new stack
    -- Executing [s@sub-record-check:9] Set("PJSIP/zeus-00000227", "__MON_FMT=wav") in new stack
    -- Executing [s@sub-record-check:10] NoOp("PJSIP/zeus-00000227", "Recordings initialized") in new stack
    -- Executing [s@sub-record-check:11] ExecIf("PJSIP/zeus-00000227", "0?Set(ARG3=dontcare)") in new stack
    -- Executing [s@sub-record-check:12] Set("PJSIP/zeus-00000227", "REC_POLICY_MODE_SAVE=") in new stack
    -- Executing [s@sub-record-check:13] ExecIf("PJSIP/zeus-00000227", "0?Set(REC_STATUS=NO)") in new stack
    -- Executing [s@sub-record-check:14] GotoIf("PJSIP/zeus-00000227", "2?checkaction") in new stack
    -- Goto (sub-record-check,s,17)
    -- Executing [s@sub-record-check:17] GotoIf("PJSIP/zeus-00000227", "1?sub-record-check,in,1") in new stack
    -- Goto (sub-record-check,in,1)
    -- Executing [in@sub-record-check:1] NoOp("PJSIP/zeus-00000227", "Inbound Recording Check to s") in new stack
    -- Executing [in@sub-record-check:2] Set("PJSIP/zeus-00000227", "FROMEXTEN=unknown") in new stack
    -- Executing [in@sub-record-check:3] ExecIf("PJSIP/zeus-00000227", "12?Set(FROMEXTEN=+16476546126)") in new stack
    -- Executing [in@sub-record-check:4] Gosub("PJSIP/zeus-00000227", "recordcheck,1(dontcare,in,s)") in new stack
    -- Executing [recordcheck@sub-record-check:1] NoOp("PJSIP/zeus-00000227", "Starting recording check against dontcare") in new stack
    -- Executing [recordcheck@sub-record-check:2] Goto("PJSIP/zeus-00000227", "dontcare") in new stack
    -- Goto (sub-record-check,recordcheck,3)
    -- Executing [recordcheck@sub-record-check:3] Return("PJSIP/zeus-00000227", "") in new stack
    -- Executing [in@sub-record-check:5] Return("PJSIP/zeus-00000227", "") in new stack
    -- Executing [s@from-pstn:3] Set("PJSIP/zeus-00000227", "CHANNEL(tonezone)=us") in new stack
    -- Executing [s@from-pstn:4] ExecIf("PJSIP/zeus-00000227", "1?Set(__FROM_DID=s)") in new stack
    -- Executing [s@from-pstn:5] Set("PJSIP/zeus-00000227", "returnhere=1") in new stack
    -- Executing [s@from-pstn:6] Gosub("PJSIP/zeus-00000227", "app-blacklist-check,s,1()") in new stack
    -- Executing [s@app-blacklist-check:1] GotoIf("PJSIP/zeus-00000227", "0?blacklisted") in new stack
    -- Executing [s@app-blacklist-check:2] Set("PJSIP/zeus-00000227", "CALLED_BLACKLIST=1") in new stack
    -- Executing [s@app-blacklist-check:3] Return("PJSIP/zeus-00000227", "") in new stack
    -- Executing [s@from-pstn:7] Set("PJSIP/zeus-00000227", "CDR(did)=s") in new stack
    -- Executing [s@from-pstn:8] GotoIf("PJSIP/zeus-00000227", "0?") in new stack
    -- Executing [s@from-pstn:9] ExecIf("PJSIP/zeus-00000227", "0 ?Set(CALLERID(name)=+16476546126)") in new stack
    -- Executing [s@from-pstn:10] Set("PJSIP/zeus-00000227", "__MOHCLASS=") in new stack
    -- Executing [s@from-pstn:11] Set("PJSIP/zeus-00000227", "__REVERSAL_REJECT=FALSE") in new stack
    -- Executing [s@from-pstn:12] GotoIf("PJSIP/zeus-00000227", "1?post-reverse-charge") in new stack
    -- Goto (from-pstn,s,14)
    -- Executing [s@from-pstn:14] NoOp("PJSIP/zeus-00000227", "") in new stack
    -- Executing [s@from-pstn:15] Set("PJSIP/zeus-00000227", "__CALLINGNAMEPRES_SV=allowed_not_screened") in new stack
    -- Executing [s@from-pstn:16] Set("PJSIP/zeus-00000227", "__CALLINGNUMPRES_SV=allowed_not_screened") in new stack
    -- Executing [s@from-pstn:17] Set("PJSIP/zeus-00000227", "CALLERID(name-pres)=allowed_not_screened") in new stack
    -- Executing [s@from-pstn:18] Set("PJSIP/zeus-00000227", "CALLERID(num-pres)=allowed_not_screened") in new stack
    -- Executing [s@from-pstn:19] NoOp("PJSIP/zeus-00000227", "CallerID Entry Point") in new stack
    -- Executing [s@from-pstn:20] Set("PJSIP/zeus-00000227", "__CRM_DIRECTION=INBOUND") in new stack
    -- Executing [s@from-pstn:21] Set("PJSIP/zeus-00000227", "__CRM_SOURCE=+16476546126") in new stack
    -- Executing [s@from-pstn:22] Set("PJSIP/zeus-00000227", "__CRM_LINKEDID=1746046750.552") in new stack
    -- Executing [s@from-pstn:23] AGI("PJSIP/zeus-00000227", "agi://127.0.0.1/sangomacrm.agi,true") in new stack
    -- <PJSIP/zeus-00000227>AGI Script agi://127.0.0.1/sangomacrm.agi completed, returning 0
    -- Executing [s@from-pstn:24] ExecIf("PJSIP/zeus-00000227", "1?Set(CHANNEL(hangup_handler_push)=crm-hangup,s,1)") in new stack
    -- Executing [s@from-pstn:25] Goto("PJSIP/zeus-00000227", "ivr-incoming,s,1") in new stack
    -- Goto (ivr-incoming,s,1)
    -- Executing [s@ivr-incoming:1] Gosub("PJSIP/zeus-00000227", "macro-hangupcall,s,1()") in new stack
    -- Executing [s@macro-hangupcall:1] Set("PJSIP/zeus-00000227", "__MCVMSTATUS=") in new stack
    -- Executing [s@macro-hangupcall:2] Gosub("PJSIP/zeus-00000227", "app-missedcall-hangup,s,1()") in new stack
    -- Executing [s@app-missedcall-hangup:1] NoOp("PJSIP/zeus-00000227", "Dialed: s") in new stack
    -- Executing [s@app-missedcall-hangup:2] NoOp("PJSIP/zeus-00000227", "Caller: ") in new stack
    -- Executing [s@app-missedcall-hangup:3] GotoIf("PJSIP/zeus-00000227", "0?exit") in new stack
    -- Executing [s@app-missedcall-hangup:4] Set("PJSIP/zeus-00000227", "EXTENNUM=s") in new stack
    -- Executing [s@app-missedcall-hangup:5] Set("PJSIP/zeus-00000227", "FEXTENNUM=s") in new stack
    -- Executing [s@app-missedcall-hangup:6] GotoIf("PJSIP/zeus-00000227", "0?exit") in new stack
    -- Executing [s@app-missedcall-hangup:7] AGI("PJSIP/zeus-00000227", "agi://127.0.0.1/missedcallnotify.php,s,,s,0,,PJSIP/zeus-00000227,,,,") in new stack
    -- <PJSIP/zeus-00000227>AGI Script agi://127.0.0.1/missedcallnotify.php completed, returning 0
    -- Executing [s@app-missedcall-hangup:8] Return("PJSIP/zeus-00000227", "") in new stack
    -- Executing [s@macro-hangupcall:3] UserEvent("PJSIP/zeus-00000227", "MES,RTPAUDIOQOSMESBRIDGED:,RTPAUDIOQOSMES:") in new stack
    -- Executing [s@macro-hangupcall:4] GotoIf("PJSIP/zeus-00000227", "1?theend") in new stack
    -- Goto (macro-hangupcall,s,6)
    -- Executing [s@macro-hangupcall:6] ExecIf("PJSIP/zeus-00000227", "0?Set(CDR(recordingfile)=)") in new stack
    -- Executing [s@macro-hangupcall:7] Hangup("PJSIP/zeus-00000227", "") in new stack
  == Spawn extension (macro-hangupcall, s, 7) exited non-zero on 'PJSIP/zeus-00000227'
    -- PJSIP/zeus-00000227 Internal Gosub(crm-hangup,s,1) start
    -- Executing [s@crm-hangup:1] NoOp("PJSIP/zeus-00000227", "Sending Hangup to CRM") in new stack
    -- Executing [s@crm-hangup:2] NoOp("PJSIP/zeus-00000227", "HANGUP CAUSE: 16") in new stack
    -- Executing [s@crm-hangup:3] ExecIf("PJSIP/zeus-00000227", "0?Set(__CRM_VOICEMAIL=)") in new stack
    -- Executing [s@crm-hangup:4] NoOp("PJSIP/zeus-00000227", "MASTER CHANNEL: 1746046750.552 = 1746046750.552") in new stack
    -- Executing [s@crm-hangup:5] GotoIf("PJSIP/zeus-00000227", "0?return") in new stack
    -- Executing [s@crm-hangup:6] Set("PJSIP/zeus-00000227", "__CRM_HANGUP=1") in new stack
    -- Executing [s@crm-hangup:7] AGI("PJSIP/zeus-00000227", "agi://127.0.0.1/sangomacrm.agi") in new stack
    -- <PJSIP/zeus-00000227>AGI Script agi://127.0.0.1/sangomacrm.agi completed, returning 0
    -- Executing [s@crm-hangup:8] Return("PJSIP/zeus-00000227", "") in new stack
  == Spawn extension (macro-hangupcall, s, 7) exited non-zero on 'PJSIP/zeus-00000227'
    -- PJSIP/zeus-00000227 Internal Gosub(crm-hangup,s,1) complete GOSUB_RETVAL=
    -- Executing [2410013433500318@from-sip-external:1] NoOp("PJSIP/anonymous-00000228", "Received incoming SIP connection from unknown peer to 2410013433500318") in new stack
    -- Executing [2410013433500318@from-sip-external:2] Set("PJSIP/anonymous-00000228", "DID=2410013433500318") in new stack
    -- Executing [2410013433500318@from-sip-external:3] Goto("PJSIP/anonymous-00000228", "s,1") in new stack
    -- Goto (from-sip-external,s,1)
    -- Executing [s@from-sip-external:1] GotoIf("PJSIP/anonymous-00000228", "1?setlanguage:checkanon") in new stack
    -- Goto (from-sip-external,s,2)
    -- Executing [s@from-sip-external:2] Set("PJSIP/anonymous-00000228", "CHANNEL(language)=en") in new stack
    -- Executing [s@from-sip-external:3] GotoIf("PJSIP/anonymous-00000228", "0?noanonymous") in new stack
    -- Executing [s@from-sip-external:4] Goto("PJSIP/anonymous-00000228", "from-trunk,2410013433500318,1") in new stack
    -- Goto (from-trunk,2410013433500318,1)
    -- Executing [2410013433500318@from-trunk:1] NoOp("PJSIP/anonymous-00000228", "Catch-All DID Match - Found 2410013433500318 - You probably want a DID for this.") in new stack
    -- Executing [2410013433500318@from-trunk:2] Set("PJSIP/anonymous-00000228", "__FROM_DID=2410013433500318") in new stack
    -- Executing [2410013433500318@from-trunk:3] Goto("PJSIP/anonymous-00000228", "ext-did,s,1") in new stack
    -- Goto (ext-did,s,1)
    -- Executing [s@ext-did:1] Set("PJSIP/anonymous-00000228", "__DIRECTION=INBOUND") in new stack
    -- Executing [s@ext-did:2] Gosub("PJSIP/anonymous-00000228", "sub-record-check,s,1(in,s,dontcare)") in new stack
    -- Executing [s@sub-record-check:1] GotoIf("PJSIP/anonymous-00000228", "0?initialized") in new stack
    -- Executing [s@sub-record-check:2] Set("PJSIP/anonymous-00000228", "__REC_STATUS=INITIALIZED") in new stack
    -- Executing [s@sub-record-check:3] Set("PJSIP/anonymous-00000228", "NOW=1746046775") in new stack
    -- Executing [s@sub-record-check:4] Set("PJSIP/anonymous-00000228", "__DAY=30") in new stack
    -- Executing [s@sub-record-check:5] Set("PJSIP/anonymous-00000228", "__MONTH=04") in new stack
    -- Executing [s@sub-record-check:6] Set("PJSIP/anonymous-00000228", "__YEAR=2025") in new stack
    -- Executing [s@sub-record-check:7] Set("PJSIP/anonymous-00000228", "__TIMESTR=20250430-205935") in new stack
    -- Executing [s@sub-record-check:8] Set("PJSIP/anonymous-00000228", "__FROMEXTEN=unknown") in new stack
    -- Executing [s@sub-record-check:9] Set("PJSIP/anonymous-00000228", "__MON_FMT=wav") in new stack
    -- Executing [s@sub-record-check:10] NoOp("PJSIP/anonymous-00000228", "Recordings initialized") in new stack
    -- Executing [s@sub-record-check:11] ExecIf("PJSIP/anonymous-00000228", "0?Set(ARG3=dontcare)") in new stack
    -- Executing [s@sub-record-check:12] Set("PJSIP/anonymous-00000228", "REC_POLICY_MODE_SAVE=") in new stack
    -- Executing [s@sub-record-check:13] ExecIf("PJSIP/anonymous-00000228", "0?Set(REC_STATUS=NO)") in new stack
    -- Executing [s@sub-record-check:14] GotoIf("PJSIP/anonymous-00000228", "2?checkaction") in new stack
    -- Goto (sub-record-check,s,17)
    -- Executing [s@sub-record-check:17] GotoIf("PJSIP/anonymous-00000228", "1?sub-record-check,in,1") in new stack
    -- Goto (sub-record-check,in,1)
    -- Executing [in@sub-record-check:1] NoOp("PJSIP/anonymous-00000228", "Inbound Recording Check to s") in new stack
    -- Executing [in@sub-record-check:2] Set("PJSIP/anonymous-00000228", "FROMEXTEN=unknown") in new stack
    -- Executing [in@sub-record-check:3] ExecIf("PJSIP/anonymous-00000228", "5?Set(FROMEXTEN=10001)") in new stack
    -- Executing [in@sub-record-check:4] Gosub("PJSIP/anonymous-00000228", "recordcheck,1(dontcare,in,s)") in new stack
    -- Executing [recordcheck@sub-record-check:1] NoOp("PJSIP/anonymous-00000228", "Starting recording check against dontcare") in new stack
    -- Executing [recordcheck@sub-record-check:2] Goto("PJSIP/anonymous-00000228", "dontcare") in new stack
    -- Goto (sub-record-check,recordcheck,3)
    -- Executing [recordcheck@sub-record-check:3] Return("PJSIP/anonymous-00000228", "") in new stack
    -- Executing [in@sub-record-check:5] Return("PJSIP/anonymous-00000228", "") in new stack
    -- Executing [s@ext-did:3] Set("PJSIP/anonymous-00000228", "CHANNEL(tonezone)=us") in new stack
    -- Executing [s@ext-did:4] ExecIf("PJSIP/anonymous-00000228", "0?Set(__FROM_DID=s)") in new stack
    -- Executing [s@ext-did:5] Set("PJSIP/anonymous-00000228", "returnhere=1") in new stack
    -- Executing [s@ext-did:6] Gosub("PJSIP/anonymous-00000228", "app-blacklist-check,s,1()") in new stack
    -- Executing [s@app-blacklist-check:1] GotoIf("PJSIP/anonymous-00000228", "0?blacklisted") in new stack
    -- Executing [s@app-blacklist-check:2] Set("PJSIP/anonymous-00000228", "CALLED_BLACKLIST=1") in new stack
    -- Executing [s@app-blacklist-check:3] Return("PJSIP/anonymous-00000228", "") in new stack
    -- Executing [s@ext-did:7] Set("PJSIP/anonymous-00000228", "CDR(did)=2410013433500318") in new stack
    -- Executing [s@ext-did:8] GotoIf("PJSIP/anonymous-00000228", "0?") in new stack
    -- Executing [s@ext-did:9] ExecIf("PJSIP/anonymous-00000228", "1 ?Set(CALLERID(name)=10001)") in new stack
    -- Executing [s@ext-did:10] Set("PJSIP/anonymous-00000228", "__MOHCLASS=") in new stack
    -- Executing [s@ext-did:11] Set("PJSIP/anonymous-00000228", "__REVERSAL_REJECT=FALSE") in new stack
    -- Executing [s@ext-did:12] GotoIf("PJSIP/anonymous-00000228", "1?post-reverse-charge") in new stack
    -- Goto (ext-did,s,14)
    -- Executing [s@ext-did:14] NoOp("PJSIP/anonymous-00000228", "") in new stack
    -- Executing [s@ext-did:15] Set("PJSIP/anonymous-00000228", "__CALLINGNAMEPRES_SV=allowed_not_screened") in new stack
    -- Executing [s@ext-did:16] Set("PJSIP/anonymous-00000228", "__CALLINGNUMPRES_SV=allowed_not_screened") in new stack
    -- Executing [s@ext-did:17] Set("PJSIP/anonymous-00000228", "CALLERID(name-pres)=allowed_not_screened") in new stack
    -- Executing [s@ext-did:18] Set("PJSIP/anonymous-00000228", "CALLERID(num-pres)=allowed_not_screened") in new stack
    -- Executing [s@ext-did:19] NoOp("PJSIP/anonymous-00000228", "CallerID Entry Point") in new stack
    -- Executing [s@ext-did:20] Set("PJSIP/anonymous-00000228", "__CRM_DIRECTION=INBOUND") in new stack
    -- Executing [s@ext-did:21] Set("PJSIP/anonymous-00000228", "__CRM_SOURCE=10001") in new stack
    -- Executing [s@ext-did:22] Set("PJSIP/anonymous-00000228", "__CRM_LINKEDID=1746046775.553") in new stack
    -- Executing [s@ext-did:23] AGI("PJSIP/anonymous-00000228", "agi://127.0.0.1/sangomacrm.agi,true") in new stack
    -- <PJSIP/anonymous-00000228>AGI Script agi://127.0.0.1/sangomacrm.agi completed, returning 0
    -- Executing [s@ext-did:24] ExecIf("PJSIP/anonymous-00000228", "1?Set(CHANNEL(hangup_handler_push)=crm-hangup,s,1)") in new stack
    -- Executing [s@ext-did:25] Goto("PJSIP/anonymous-00000228", "ivr-incoming,s,1") in new stack
    -- Goto (ivr-incoming,s,1)
    -- Executing [s@ivr-incoming:1] Gosub("PJSIP/anonymous-00000228", "macro-hangupcall,s,1()") in new stack
    -- Executing [s@macro-hangupcall:1] Set("PJSIP/anonymous-00000228", "__MCVMSTATUS=") in new stack
    -- Executing [s@macro-hangupcall:2] Gosub("PJSIP/anonymous-00000228", "app-missedcall-hangup,s,1()") in new stack
    -- Executing [s@app-missedcall-hangup:1] NoOp("PJSIP/anonymous-00000228", "Dialed: s") in new stack
    -- Executing [s@app-missedcall-hangup:2] NoOp("PJSIP/anonymous-00000228", "Caller: ") in new stack
    -- Executing [s@app-missedcall-hangup:3] GotoIf("PJSIP/anonymous-00000228", "0?exit") in new stack
    -- Executing [s@app-missedcall-hangup:4] Set("PJSIP/anonymous-00000228", "EXTENNUM=s") in new stack
    -- Executing [s@app-missedcall-hangup:5] Set("PJSIP/anonymous-00000228", "FEXTENNUM=s") in new stack
    -- Executing [s@app-missedcall-hangup:6] GotoIf("PJSIP/anonymous-00000228", "0?exit") in new stack
    -- Executing [s@app-missedcall-hangup:7] AGI("PJSIP/anonymous-00000228", "agi://127.0.0.1/missedcallnotify.php,s,,s,0,,PJSIP/anonymous-00000228,,,,") in new stack
    -- <PJSIP/anonymous-00000228>AGI Script agi://127.0.0.1/missedcallnotify.php completed, returning 0
    -- Executing [s@app-missedcall-hangup:8] Return("PJSIP/anonymous-00000228", "") in new stack
    -- Executing [s@macro-hangupcall:3] UserEvent("PJSIP/anonymous-00000228", "MES,RTPAUDIOQOSMESBRIDGED:,RTPAUDIOQOSMES:") in new stack
    -- Executing [s@macro-hangupcall:4] GotoIf("PJSIP/anonymous-00000228", "1?theend") in new stack
    -- Goto (macro-hangupcall,s,6)
    -- Executing [s@macro-hangupcall:6] ExecIf("PJSIP/anonymous-00000228", "0?Set(CDR(recordingfile)=)") in new stack
    -- Executing [s@macro-hangupcall:7] Hangup("PJSIP/anonymous-00000228", "") in new stack
  == Spawn extension (macro-hangupcall, s, 7) exited non-zero on 'PJSIP/anonymous-00000228'
    -- PJSIP/anonymous-00000228 Internal Gosub(crm-hangup,s,1) start
    -- Executing [s@crm-hangup:1] NoOp("PJSIP/anonymous-00000228", "Sending Hangup to CRM") in new stack
    -- Executing [s@crm-hangup:2] NoOp("PJSIP/anonymous-00000228", "HANGUP CAUSE: 16") in new stack
    -- Executing [s@crm-hangup:3] ExecIf("PJSIP/anonymous-00000228", "0?Set(__CRM_VOICEMAIL=)") in new stack
    -- Executing [s@crm-hangup:4] NoOp("PJSIP/anonymous-00000228", "MASTER CHANNEL: 1746046775.553 = 1746046775.553") in new stack
    -- Executing [s@crm-hangup:5] GotoIf("PJSIP/anonymous-00000228", "0?return") in new stack
    -- Executing [s@crm-hangup:6] Set("PJSIP/anonymous-00000228", "__CRM_HANGUP=1") in new stack
    -- Executing [s@crm-hangup:7] AGI("PJSIP/anonymous-00000228", "agi://127.0.0.1/sangomacrm.agi") in new stack
    -- <PJSIP/anonymous-00000228>AGI Script agi://127.0.0.1/sangomacrm.agi completed, returning 0
    -- Executing [s@crm-hangup:8] Return("PJSIP/anonymous-00000228", "") in new stack
  == Spawn extension (macro-hangupcall, s, 7) exited non-zero on 'PJSIP/anonymous-00000228'
    -- PJSIP/anonymous-00000228 Internal Gosub(crm-hangup,s,1) complete GOSUB_RETVAL=
voice*CLI>

this are the logs I get when I call the number.

There is a call from a “zeus” endpoint and an anonymous call. Neither go to your dialplan, so your ARI application is never invoked.

How have you configured things to go to your custom context? Or did you not do this?

Hi everyone,

I’m currently working on building a complete IVR (Interactive Voice Response) system with the following goals:

  • Receive incoming calls on a Twilio number
  • Route calls dynamically based on IVR flow stored in PostgreSQL
  • Allow agents to make outbound calls
  • Manage IVR flow and logic using Node.js (with ARI)

Here’s what I’ve done so far:

:white_check_mark: Purchased a Twilio phone number
:white_check_mark: Set up Asterisk + FreePBX server
:white_check_mark: Built a Node.js backend that uses Asterisk ARI to handle call logic
:white_check_mark: Created API endpoints to store and retrieve IVR flows (using PostgreSQL)


:red_question_mark: What I Need Help With:

  1. How do I connect the Twilio number with Asterisk/FreePBX for inbound calls?
  • Should I use SIP trunking?
  • Do I need to register a SIP domain with Twilio and route it to Asterisk?
  • How can I ensure incoming calls reach the Stasis() application?
  1. Once the call reaches Asterisk, how do I trigger my Node.js logic using ARI?
  • I’ve registered my ARI app (ivrapp) and listening on StasisStart, but it’s not receiving events yet.
  • What dialplan or context config is required to ensure the call enters Stasis(ivrapp)?
  1. How to allow outbound calls for agents via Asterisk (using Twilio or any other SIP trunk)?

For anyone reading this, it is also on the Asterisk forum:

I have set inbounds routes that’s enough right or could you please suggest me how can I do it ?

I have set this In /etc/asterisk/extensions_custom.conf.
[custom-ivrapp-incoming]
exten => s,1,NoOp(Incoming call to IVR)
same => n,Answer()
same => n,Stasis(ivrapp)
same => n,Hangup()
and just added context named as custom-ivrapp-incoming.
[actually I didn’t know how and what should I configure to complete this]

That’s a FreePBX configuration question which is outside of my knowledge base, someone else may be able to answer.

You need to create a Custom Destination that has your custom-ivrapp-incoming context as the target. You then need to update your inbound route or where ever you want to point to that new custom destination. That will send the call into your statis app.

Thank you so much for your reply.
Can you please suggest me what are the steps from starting I should follow ? because still I am not getting events in nodejs.