IVR with PIN + API query


Would also like to see something on like making changes to the PBX with API like create, or delete extensions for example.

(Dark Wolf Slv) #5

@GeekBoy - Yes, there is a database of 50+ PINs so a static 6 digit option is not an alternative.

@lgaetz - your conference is in my calendar. any pointers before then so I can start testing?

(Communication Technologies) #6

Get your API call working on the Linux command line, then bring it into dial plan using shell.

Here is an example that sets the curl result to ${result}, which you can then use in later dialplan:
exten => s,n,Set(result=${SHELL(curl https://website.com/message/send -d contacts=ptn:/${ALT_NUMBER} -d session=${APIKEY} --data-urlencode body="${msgBody}")})

An alternate “All FreePBX” approach, would be to put the numbers in your phonebook then you can lookup from there. We do this putting additional call routing variables in the caller id name field.
exten => s,n,Gotoif($[${DB_EXISTS(cidname/${CALLERID(dnid)})}]?match:nomatch)

Benefit to this approach is everything is local (assuming your DB is not) and ensures correct routing, even if the API is not reachable. The phonebook is easily modified from the GUI or by some more complex automated process.

(Dark Wolf Slv) #7

Thank you comtech!
The shell part is easy (PIN=237182 && curl “website/id=$PIN”) how do I make the IVR to allow the customer to input more than one key?

Also, how do you evaluate result?
if result = X

Also, I get confused with the “exten => s,n,Set” is this a fancy way to express how the IVR is configured on the GUI or it must be set on a particular file?

(Communication Technologies) #8

Set is setting the result(response) of my curl command to the dialplan variable ${result}. I can use ${result} in evaluations and/or routing.

I believe the “IVR” would need to be programmed in dialplan (vs. the GUI) to accomplish what you are outlining. You would need to build your own context and point the route there.

In dialplan you would use the read command to accept a predefined number of digits, and assign that to a variable name of your choosing for use in following steps.

exten => s,n,Read(CBA,custom/cba,10,n,3,10)

My example stores the 10-digit input from the caller in the ${CBA} variable. In this example you would then use a gotoif to determine where to send the call.

(Dark Wolf Slv) #9

I see, so if I’m reading all the documentation right I need to manually update the extensions.conf (/etc/asterisk/) with a script similar to this:

#answer the call and request a PIN
exten => 1,1,Answer(500)
	same => n,Playback(RequestPIN)
#read 6 digits 
exten => 2,1,Read(CBA,custom/cba,6,n,1,10)
	same => n,WaitExten(5)
#send digits to API using CBA
exten => 3,1,Set(result=${SHELL(curl website/id=${CBA})})
	same => n,Goto(5,$result)
#result = 0 good PIN, forward to 800-555-1234
exten => 5,0,Dial(PJSIP/8005551234@trunk)
	same => n,Hangup
#result = 1 bad PIN, play message and hangup.
exten => 5,1,Playback(WrongPIN)
	same => n,Hangup

Thank you so much for all the help.

(Communication Technologies) #10

I am not sure your dialplan would work (No way for me to know for sure) as you have it above.

That being said, you would put the working [off-hours-pin] context in /etc/asterisk/extensions_custom.conf

extensions.conf = Made by FreePBX, not permanently editable.
extensions_custom.conf = Lets you add contexts that will not be overridden. Not editable via the GUI.
extensions_override.conf = Lets you override contexts that might already exist in the GUI or FreePBX system dialplan. Not editable via the GUI.

You also have the option to define the context as a custom destination. Making your custom code accessible in the GUI.

If you need help with dialplan, this helped me greatly when I began:

Below is a good way to debug your call flow, when you get to that.

(Dark Wolf Slv) #11

:frowning: nothing that I try seems to work and every little change cause another problem to solve.

Current state:

  • In VirtualBox I have FreePBX up to date, with two extensions. Calls between extensions work.
  • I cannot dial an IVR created on the GUI with just one option because I do not have an active trunk (you would imagine that internal dialing should work) for testing on the Outbound route I set the “Optional Destination on Congestion” to the IVR.
  • I updated the /etc/asterisk/extensions_custom.conf with a simple Playback on extension 500 and it keeps saying “your call cannot be completed as dialed” [Reference]. The article in question does not mention the need of adding an outbound route so I do not have one, but if I create one, the missing trunk is a problem once again.

exten => 500,1,Answer(500)
exten => 500,n,Playback(RequestPIN)
exten => 500,n,WaitExten(5)

  • No matter what do I dial, none of the log life increase in size so I do not think anything is getting logged, this stated happening after the system upgrade [Reference]
  • I already watched all these videos and besides not setting a valid trunk, I do not think I’m missing any steps.

Every single test I try results in an unexpected behavior/error, I cannot imagine trying to accomplish the IVR I wanted with the 6 digits and API call :frowning:

(Lorne Gaetz) #12

Create a Misc Application with a feature code to access the IVR internally.

Possibly this bug: Bug in Asterisk Logfiles Module ver 15.0.4

(Dark Wolf Slv) #13

Thank you @lgaetz
I was definitely hitting that bug.

The Misc App worked for the “GUI IVR” and I think it works for the Custome Extension if I do a Misc App + Custom Destination but I do not heard anything so I’ll continue testing.


(Communication Technologies) #14

You are closer than you were before. If you keep at it you will succeed.

(Dark Wolf Slv) #15

I think I finally got it!! Thank you so much both for all the help!!! The dial-plan below is working for me (expect the dial part since I do not have a trunk, but at this point that should be the easy part.
If the API returns 1, the PIN is valid and we can forward the call, otherwise the call is terminated.

What do you think?

;answer the call and set variables
exten => 500,1,Answer(500)
exten => 500,n,Set(IF_CORRECT=0)
exten => 500,n,Set(RESULT=0)

;request a 6 digit PIN
exten => 500,n,Read(PIN,custom/RequestPIN,6,n,1,10)
exten => 500,n,Playback(you-entered)
exten => 500,n,SayDigits(${PIN})
exten => 500,n,Read(IF_CORRECT,custom/IfThisIsCorrect,1,n,1,3)
exten => 500,n,GotoIf($[ ${IF_CORRECT} = 1 ]?600,1:700,1)

;send PIN to API using cURL
exten => 600,1,Set(RESULT=${SHELL(curl -s website_here)})
exten => 600,n,GotoIf($[ ${RESULT} = 1 ]?:700,1)
exten => 600,n,Dial(SIP/8005551234@
exten => 600,n,Goto(700,1)

;hangup the call
exten => 700,1,Hangup()

Again, thank you so much for all the patience.

(Itzik) #16

I’d rather use something like

exten => 600,n,Dial(local/8885551234@from-internal)


And 600 and 700 are unnecessary use of possibly other wise useful endpoint identifiers, I suggest you use OK and NOTOK instead

exten => 500,n,GotoIf($[ ${IF_CORRECT} = 1 ]?OK,1:NOTOK,1)
exten => OK,1,Set(RESULT=${SHELL(curl -s website_here)})
exten => same,GotoIf ($[ ${RESULT} = 1 ]?:NOTOK,1)
exten => NOTOK,1,Hangup()

(Lorne Gaetz) #18

I’m sure this works, but there is probably some value in using the native dialplan function for ‘curl’:

 exten => 600,1,Set(RESULT=${CURL(https://website_here)})

Again, not wrong, but convention suggests that when writing dialplan with an arbitrary extension, you use the s character, i.e.:

exten => s,1,Answer(500)
exten => s,n,Set(IF_CORRECT=0)
exten => s,n,Set(RESULT=0)

(Dark Wolf Slv) #19

Thank you all for all the suggestions, I did the necessary adjustments for my use case and we can consider this solved.

Thanks again.

(Lorne Gaetz) #20

Share your final result :slight_smile:

(Dark Wolf Slv) #21

;answer the call and set variables
exten => s,1,Answer(500)
exten => s,n,Set(IF_CORRECT=0)
exten => s,n,Set(RESULT=0)

;request a 6 digit PIN
exten => s,n,Read(PIN,custom/RequestPIN,6,n,1,10)
exten => s,n,Playback(you-entered)
exten => s,n,SayDigits(${PIN})
exten => s,n,Read(IF_CORRECT,custom/IfThisIsCorrect,1,n,1,3)
exten => s,n,GotoIf($[ ${IF_CORRECT} = 1 ]?CORRECT,1:HANGUP,1)

;send PIN to API using cURL
exten => CORRECT,1,Set(RESULT=${CURL(https://website/${PIN})})
exten => CORRECT,n,GotoIf($[ ${RESULT} = 1 ]?:HANGUP,1)
exten => CORRECT,n,Dial(SIP/8005551234@
exten => CORRECT,n,Goto(HANGUP,1)

;hangup the call
exten => HANGUP,1,Hangup()

(Jared Busch) #22

If you want to try and keep a bit of this in the GUI for others, you can use a Misc Destination and Misc Application. It is certainly more cumbersome, but it keeps people out of config files if you need to change the number that is being dialled.

First, make a Misc Destination.

Then make a Misc Application that points to it.

Then have your context dial the Misc Application number

exten => CORRECT,n,(from-internal,4357,1)

(system) closed #23

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.