In this article we will discuss how small to mid size company may have implement its dial plan.

The dial plan will provide basic capabilities of IVR, inbound and outbound calling, voicemail, DISA and other standard PBX functionality used in small to mid size companies.

If you are interested in company IVR only, check this article: Asterisk voip how to make company IVR

For this purpose you will need the following two software products – Asterisk open source PBX and Apstel Visual Dialplan.

Asterisk PBX is free, open source PBX, while Visual Dialplan is commercial software but its trial version can be freely downloaded and comes with all major functionality that we need to create this dial plan.

1. Download and install Asterisk PBX

Asterisk PBX is available in two major distributions – as a standalone Asterisk PBX without GUI, and Asterisk PBX with a GUI.
We recommend you to use Asterisk PBX with a GUI since it is significantly easier to set it all up through the GUI comparing to manual edit of configuration files at Linux OS.

You can find several Asterisk GUIs on the market (Elastix, PIAF, AsteriskNOW etc.) but we do recommend Elastix GUI.

After you download the Elastix PBX ISO package, run it on some virtual machine and follow on screen instructions.
The ISO will install all you need – Linux OS, MySQL database, Asterisk PBX, Elastix GUI etc.

2. Download and install Visual Dialplan

Visual Dialplan is intuitive and easy to use tool for dial plan development. There is no need to know Linux or to have some Asterisk experience to use it and create complex dial plans. It also comes with several ready to use dial plan examples.

Download Visual Dialplan here: Visual Dialplan download


Asterisk voip how to – create office dial plan

Now that we have both software components up and running, Elastix GUI and Visual Dialplan, we can proceed and create office dial plan.

The dial plan is broken into contexts, separated parts of the dial plan where each part has its own functionality.

We will create the following contexts:


This context is intended for placing the SIP outbound calls and for checking voicemail.
Outbound calls are all calls initiated from the SIP endpoint (voip phone) to other SIP endpoints or outside world.

Asterisk voip how to - SIP outbound context

The first entry component matches all the extensions (each voip phone has its own extension number) in the following format 1XX (e.g. 100, 101, 102 … 199).

Calls that land on these extensions will be forwarded to the dial-ext context, which is used to dial the SIP endpoint.

Second entry point component matches the extension *1 and invokes the voicemail main application (administrative voicemail application). The caller is sent to the administrative interface for the voice mailbox based on the caller ID number. For example, the employee on extension 101 will be sent to the administrative voicemail application for the voice mailbox 101.

The third entry point component matches all other extensions and dials that number over the DAHDI channel from group 1 (DAHDI/g1/${EXTEN}).


This context is used for dialing the local extensions.

Asterisk PBX - Dialing local extensions

After the call is logged for debugging purposes (Log component), appropriate Sip extension is dialed.
In case of the busy, unavailable or no answer response, the call is sent to the voice mailbox for the dialed extension.


This context accepts all incoming calls coming through the DAHDI lines.
Basically it is simple company IVR call flow.

Visual Dialplan - incoming calls

All inbound calls (landing the S extension) are first answered and presented with a welcome message, after which the main menu is played and caller input is expected.

The caller can choose from one of the following options:
0 – A call is sent to the dial-attendant context in order to dial employee based on the caller ID number.
1 – A call is sent to the dial-employee context to allow the caller to choose the employee extension that should be dialed dial.
2 – Allow employees to check the voicemail. A call is sent to the VoicemailMain application, without parameters, meaning that the application will ask the caller for both mailbox number and password.
3 – Allow employees to dial out. The call I sent to the DISA (Direct Inward Dialing Application) application. The caller is expected to type the password 123 after which he is allowed to dial-out as if he was using the local SIP phone.

If no choice I made by the caller within the RESP_TOUT (10 seconds), the call is hanged up.
In case the caller hangs up the caller, before making any choice, a debug message I logged using the Log component.


This context dials one of the employees based on the caller’s area code.

Asterisk GUI - dialing employees based on caller area code

This very simple context sets the first four digits of the caller ID number to the area_code channel variable.
The select-attendant macro is call with the area_code value in order to find appropriate employee.
The last step of this context is dialing the SIP endpoint returned as a result of the previous macro call.


This context enables external caller to reach an extension.

The caller is prompted to type in the three digit extension of the employee he wishes to reach. If caller types the valid extension, the call is sent to the dial-ext context, otherwise the call is terminated.

Global variables

Dial timeout – 20sec.

Digit timeout – 3sec.

Response timeout – 10sec.

Channel variables

Selected Sip extension for this call. This variable is set by the select-attendant macro.

This variable holds the first four digits of the caller ID number.

Default mailbox for the SIP peer.



This macro selects extension based on the first four digits of the caller ID. The associated extension is read from the database.

If no value is passed in the area_code argument, this macro will read the default extension. If the value of the area_code argument is not empty, the macro will read the associated extension for that area code.
After the value is read from the database, the macro returns the control to the calling context.

In order to function properly, sample dialplan requires that some of the resources are already configured in the Asterisk server (i.e. SIP endpoints, voice mailboxes, sound files …).


Deploy the dial plan

The output of Visual Dialplan is standard Asterisk code (extension.conf).
Please find below the output of the dial plan described above.

You can use this code and deploy it to your Asterisk server manually or you can use Visual Dialplan and deploy it from Visual Dialplan automatically, with a single press of a button.

Simply select “Dialplan” and then “Deploy” from the main many and Visual Dialplan will SSH to your remote Asterisk server, deploy the dial plan, and reload it into the Asterisk PBX.¬†You’ll be presented with a box to confirm the remote deployment. Just click yes and few seconds later a confirmation window will appear.

Make sure you validate your Asterisk dial plan before you deploy it to Asterisk server. This will make the whole process go a lot smoother.

Here are the URLs for download:

Download Visual Dialplan here: Visual Dialplan download

There is no need to download dial plan used in this article since it is already provided with Visual Dialplan – just load dial plan titled “04_quick_office.vdp” (Small office dial plan example).

If you still want to do this manually, here is the code you would need to copy-paste into your extensions.conf file and then reload the dialplan at Asterisk server.

; ------------
; Generated with Visual Dialplan.


; Dial timeout - 20sec.
; Digit timeout - 3sec.
; Response timeout - 10sec.

; Context for the SIP outbound calls.

exten => _1XX,1,Goto(dial-ext,${EXTEN},1)
exten => *1,1,Set(mailbox=${CALLERID(number)})
exten => *1,n,VoicemailMain(${mailbox})
exten => *1,n,Hangup()
exten => _X.,1,Dial(Zap/g1/${EXTEN},${DIAL_TOUT},HrS(600)TWK)

; Context used for dialing the local extensions.

exten => _1XX,1,Log(DEBUG,Dialing local extension ${EXTEN})
exten => _1XX,n,Dial(SIP/${EXTEN},${DIAL_TOUT},htwk)
exten => _1XX,n,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL"]?lbl_dial-ext_1:)
exten => _1XX,n,GotoIf($["${DIALSTATUS}" = "NOANSWER"]?lbl_dial-ext_1:)
exten => _1XX,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?lbl_dial-ext_1:)
exten => _1XX,n(lbl_dial-ext_0),Hangup()
exten => _1XX,n(lbl_dial-ext_1),MailboxExists(${EXTEN})
exten => _1XX,n,GotoIf($["${VMBOXEXISTSSTATUS}" = "FAILED"]?lbl_dial-ext_2:)
exten => _1XX,n,VoiceMail(${EXTEN},u)
exten => _1XX,n,GotoIf($["${VMSTATUS}" = "FAILED"]?lbl_dial-ext_3:)
exten => _1XX,n,Goto(lbl_dial-ext_0)
exten => _1XX,n(lbl_dial-ext_3),Log(ERROR,Caller ${CALLERID(all)}
failed to leave a voicemail for ${EXTEN} mailbox.)
exten => _1XX,n,Goto(lbl_dial-ext_0)
exten => _1XX,n(lbl_dial-ext_2),Hangup()

; Context for incoming external (zap) calls.

exten => s,1,Answer()
exten => s,n,Playback(welcome)
exten => s,n(lbl_dial-in_0),Set(TIMEOUT(response)=10)
exten => s,n,Set(TIMEOUT(digit)=3)
exten => s,n,Background(main-menu,m)
exten => s,n,WaitExten(${RESP_TOUT})
exten => s,n,Hangup()
exten => 0,1,Goto(dial-attendant,s,1)
exten => h,1,Log(VERBOSE,Caller ${CALLERID(all)} hung up.)
exten => h,n,Hangup()
exten => 2,1,VoicemailMain()
exten => 2,n,Goto(s,lbl_dial-in_0)
exten => 1,1,Goto(dial-employee,s,1)
exten => 3,1,DISA(123,sip)

; Dial attendant.

exten => s,1,Set(area_code=${CALLERID(number):0:4})
exten => s,n,Macro(select-attendant,${area_code})
exten => s,n,RetryDial(,5,2,SIP/${attendant},${DIAL_TOUT},A(attendant-msg)hm()twk)

; Dial employee.

exten => s,1,Set(TIMEOUT(response)=${RESP_TOUT})
exten => s,n,Set(TIMEOUT(digit)=${DIGIT_TOUT})
exten => s,n,Background(select-emp)
exten => s,n,WaitExten(${RESP_TOUT})
exten => s,n,Playback(goodbye)
exten => s,n,Hangup()
exten => _1XX,1,Goto(dial-ext,${EXTEN},1)

; This macro selects attendant based on the first four digit of the caller ID.

exten => s,1,GotoIf($["${LEN(${ARG1})}" = "0"]?:lbl_macro-select-attendant_0)
exten => s,n,Set(attendant=${DB(attendant/default)})
exten => s,n(lbl_macro-select-attendant_1),MacroExit()
exten => s,n(lbl_macro-select-attendant_0),Set(attendant=${DB(attendant/${ARG1})})
exten => s,n,Goto(lbl_macro-select-attendant_1)
; ------------