Skip to end of metadata
Go to start of metadata


This page is a companion to the Astricon 2020 presentation by Lorne Gaetz. In places in the video, there are references to dialplan which are shared below.

Preprocess Inbound Calls

To apply user defined custom dialplan to an inbound call before it reaches your FreePBX Inbound routes, create a context similar to this:

[from-trunk-preprocess]                                                                             ; context name is arbitrary
; Characters that follow a ; are ignored, use for commenting
exten => _.,1,Noop(Entering user defined context from-trunk-preprocess in extensions_custom.conf)   ; log some breadcrumbs to assist debugging later
exten => _.,n,Verbose(0,Caller ID: ${CALLERID(name)})                                               ; doesn't do much, just logs the Caller ID name 

;  add whatever other lines you need

exten => _.,n,Goto(from-trunk,${EXTEN},1)                                                           ; context must end with at goto the from-trunk context

; end of from-trunk-preprocess

With the context created in /etc/asterisk/extensions_custom.conf, you now edit your FreePBX trunk(s) in the GUI and change the context to the name you used above, in this case 'from-trunk-preprocess`. Submit and apply config, and all inbound calls on those trunks will first use the preprocess context before going to the Inbound Routes.

Custom Destinations

If you want to direct a call thru the system to a specific destination with custom dialplan, you do it by creating a Custom Destination. In this example, we are using two APIs, the to get the text of a joke, and the Voip Innovations apidaze API to send the content of that joke out via SMS. Example dialplan for /etc/asterisk/extensions_custom.conf:

exten => s,1,Noop(Entering user defined context randomjoke-sms-apidaze in extensions_custom.conf)

exten => s,n,Set(apidaze_key=xxxxxxxxx)               ; get from APIDAZE Dev App
exten => s,n,Set(apidaze_secret=xxxxxxxxxxxxxxx)      ; get from APIDAZE Dev App

exten => s,n,Set(from_DID=xxxxxxxxx)                  ; DID associated with APIDAZE App
exten => s,n,Set(destination=${CALLERID(number)})

; set headers and curl for corny joke
exten => s,n,set(CURLOPT(httpheader)=Accept:text/plain)
exten => s,n,set(CURLOPT(httpheader)=User-Agent:Asterisk-FreePBX-joke2SMS)
exten => s,n,set(joke=${URIENCODE(${CURL(})})         ; make API call and encode it. Content returned with a <CR> is a problem
exten => s,n,set(joke=${URIDECODE(${STRREPLACE(joke,%0A,%20)})})                 ; filter out <CR> by replacing with a space character

; send the joke to the caller's CallerID number via SMS using Voip Innovations api-daze API
exten => s,n,set(result=${CURL(${apidaze_key}/sms/send?api_secret=${apidaze_secret},from=${from_DID}&to=${destination}&body=${joke})})

exten => s,n,Return                                   ; end the custom destination context with a return application

With the above in place, create a Custom Destination with a GoSub string of:


And enable the Return option. Choose the destination for the call and submit. 

Custom Feature Code Prefix

To create a dial prefix, use code similar to the following. If you want to dial an extension with a specific delay, you can do it with this code in /etc/asterisk/extensions_custom.conf

exten => _**XXX*XXXX,1,Noop(Entering user defined context from-internal-custom in extensions_custom.conf)
exten => _**XXX*XXXX,n,Noop(ext: ${EXTEN:-4} delay: ${EXTEN:2:3})
exten => _**XXX*XXXX,n,Wait(${EXTEN:2:3})
exten => _**XXX*XXXX,n,goto(from-internal,${EXTEN:-4},1)

Once the dialplan has been reloaded (apply config), dialing "**015*1004" will allow the system to dial extension 1004 with a 15 second delay before dialing.

Dialplan Hook for Outbound Calls

If you want to perform an action on all outbound calls, you can use a dialplan hook macro similar to this:

exten => s,1,Noop(Entering user defined context macro-dialout-trunk-predial-hook in extensions_custom.conf)
exten => s,n,GosubIf($["${EMERGENCYROUTE}"="YES"]?ifttt2twitter,s,1)
exten => s,n,MacroExit

; create an webhook to accept one data field and get the webhook name and key
exten => s,1,Noop(Entering user defined context ifttt2twitter in extensions_custom.conf)
exten => s,n,Set(ifttt_app=xxxxxxxxx)               ; get from webhook name
exten => s,n,Set(ifttt_key=xxxxxxxxxxxxxxx)         ; get from webhook key
exten => s,n,Set(result=${CURL(${ifttt_app}/with/key/${ifttt_key}?value1=${AMPUSER})})
exten => s,n,Return


Related articles