Asterisk Dialplan Extensions: Syntax, Priorities, Applications, and Contexts
Learn how Asterisk extensions work in extensions.conf, including syntax, priorities, applications, contexts, pattern matching, call flow, and troubleshooting.
An Asterisk extension is a sequence of dialplan instructions that controls how Asterisk handles a call. Despite its name, an extension is not necessarily a physical telephone. It may be a number, feature code, incoming-call destination, pattern, or named dialplan entry.
A call enters a context, Asterisk matches an extension in that context, and the matching extension executes its priorities in order. Each priority invokes an Asterisk application, such as Answer(), Playback(), Dial(), or Hangup().
What an Asterisk Extension Does
The dialplan is the set of routing and call-processing instructions followed by Asterisk. An extension is one named or numbered sequence within that dialplan.
For example, extension 200 might answer a call, play an announcement, and hang up. Extension 201 might call a PJSIP endpoint. A feature code such as *98 might invoke a service, while a pattern might match a whole family of outbound numbers.
- An extension can represent a numeric internal destination.
- It can represent a service code or feature.
- It can be the target for an incoming trunk call.
- It can match a range of dialed values through a pattern.
- It can be a named entry point used by dialplan logic.
Each extension contains ordered priorities. A priority is one step in the sequence, and each step calls an application with optional arguments.
Where Extensions Are Configured
Static dialplan definitions are traditionally stored in /etc/asterisk/extensions.conf. Definitions are organized under context sections, such as [internal] or [training].
[training]
exten => 200,1,Answer()
same => n,Playback(hello-world)
same => n,Hangup()
Higher-level PBX systems may generate or manage the dialplan. In a managed installation, direct edits to extensions.conf may be overwritten or ignored. Identify the authoritative customization method before changing production routing.
Extension Definition Syntax
The standard form is:
exten => extension_name,priority,application(arguments)
The => separator separates the exten keyword from the extension name and its instructions. Whitespace is flexible, but consistent alignment and use of same => make a dialplan easier to read.
A context header is different from an extension definition. A header such as [internal] names a group of extensions; it does not itself execute an application.
Extension Names, Special Entries, and Patterns
The extension-name field commonly contains an internal number such as 200. It may also contain a service code, label, or special entry point.
A leading underscore marks a pattern extension. In _3XXX, X matches a digit from 0 through 9, so the pattern matches four-digit values beginning with 3.
[internal]
exten => _3XXX,1,NoOp(Matched internal pattern: ${EXTEN})
same => n,Dial(PJSIP/${EXTEN},20)
same => n,Hangup()
Exact matching is preferred when one specific destination is intended. Patterns are useful for number ranges, but broad patterns can accidentally expose destinations or outbound routes.
Priorities and Execution Order
A priority determines when an application runs within a matched extension. The usual entry point is priority 1.
[training]
exten => 200,1,Answer()
same => n,Playback(hello-world)
same => n,Hangup()
These steps execute as priority 1, priority 2, and priority 3. The n value means “the next priority,” allowing Asterisk to calculate the sequential number.
Priorities belong to a particular extension in a particular context. Priority 2 of 200 is unrelated to priority 2 of 201, and an extension with the same name in another context has a separate sequence.
Named priorities or labels provide readable branch targets where supported. A label can identify a meaningful location such as failed rather than requiring a fragile hard-coded number. Execution can reach a label with a transfer such as Goto(failed), or with a fully qualified destination such as Goto(context,extension,failed).
When execution reaches the end of the available priorities, the call normally terminates unless an application has already transferred execution, bridged the call, or otherwise ended the channel. Do not assume that every application leaves the call in the same state.
Applications and Arguments
An Asterisk application is a callable action performed by a dialplan step. An application’s arguments configure its behavior. Argument order is significant, so consult the documentation for the Asterisk version and application in use.
Applications may affect call state, collect digits, play media, route calls, invoke external logic, or terminate a channel. An application can also return control to the next priority, transfer control elsewhere, or prevent later priorities from running.
Basic Internal Extension
[training]
exten => 200,1,Answer()
same => n,Playback(hello-world)
same => n,Hangup()
When a call matches 200 in the training context, Asterisk answers it, plays the built-in hello-world prompt, and hangs up.
Calling a PJSIP Endpoint
[internal]
exten => 201,1,NoOp(Calling endpoint 201)
same => n,Dial(PJSIP/201,20)
same => n,NoOp(Dial result: ${DIALSTATUS})
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
Dial(PJSIP/201,20) attempts to call endpoint 201 for up to 20 seconds. If the call is not answered, Dial() may return control to the next priority. The DIALSTATUS variable can help distinguish outcomes such as unavailable, busy, or no answer.
Production logic should intentionally handle those outcomes, for example by sending a busy caller to voicemail, offering an alternate destination, or playing an unavailable announcement.
Feature Code
[internal-services]
exten => *98,1,NoOp(Feature code requested)
same => n,Playback(vm-enter-num-to-call)
same => n,Hangup()
A feature code is an extension name used for behavior rather than a physical phone. Its meaning is defined entirely by the dialplan.
Contexts and Routing Permissions
A context is a named collection of extensions. Contexts form dialplan boundaries and are central to routing permissions. A channel receives its context through channel, endpoint, trunk, or provider configuration.
The same extension number can safely have different behavior in different contexts:
[internal-users]
exten => 100,1,Dial(PJSIP/100,20)
same => n,Hangup()
[inbound-trunk]
exten => 100,1,Playback(company-directory)
same => n,Hangup()
An internal caller in internal-users and an inbound trunk caller in inbound-trunk can both dial 100, but Asterisk selects the definition in the channel’s current context.
An include makes extensions from another context available for matching:
[office-users]
include => internal-services
Applications such as Goto() can explicitly transfer execution to another extension or context. Includes affect what can be matched; they do not mean that every call automatically changes context.
Call Matching and the Execution Lifecycle
- An incoming channel or dialing party supplies a called value, or the call enters a default entry point.
- Asterisk determines the channel’s context.
- Asterisk performs exact extension matching and, when appropriate, pattern matching.
- The selected extension begins at its entry priority, normally priority 1.
- Applications execute in priority order.
- An application may continue normally, transfer execution, bridge the call, collect digits, or terminate the channel.
- The call completes, is transferred, or ends when no further execution remains.
The called number normally selects the initial extension. Later routing decisions may use caller identity, the ${EXTEN} value, channel variables, time conditions, authentication state, or the result of another application.
Dialplan Flow Control
Goto() transfers execution to another priority, extension, or context. A fully qualified form identifies all three locations:
same => n,Goto(internal-services,*98,1)
GotoIf() provides conditional routing. A condition can inspect a channel variable or application result:
same => n,NoOp(Dial result is ${DIALSTATUS})
same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavailable)
same => n(busy),Playback(tt-weasels)
same => n,Hangup()
same => n(unavailable),VoiceMail(201@default)
same => n,Hangup()
The exact condition and media choices should be adapted to the application and Asterisk version. The important design principle is to provide intentional destinations for each meaningful outcome.
Dial() commonly returns control to the next priority when the called party is not connected or when an option causes it to return. Always provide post-Dial() behavior instead of assuming the caller will receive useful handling automatically.
Special Entries for Invalid Input and Timeouts
Menu and digit-collection logic commonly uses i for invalid input and t for timeout. These entries can play feedback and return the caller to a menu, but loops should have a limit or an intentional exit.
[ivr]
exten => s,1,Answer()
same => n,Playback(main-menu)
same => n,WaitExten(5)
exten => i,1,Playback(pbx-invalid)
same => n,Goto(s,1)
exten => t,1,Playback(vm-goodbye)
same => n,Hangup()
For more menu-specific design, see invalid entries and timeouts and automated attendant design.
Testing and Validation
Make small changes, reload them, inspect the loaded dialplan, and test one call path at a time.
asterisk -rvvv
core set verbose 5
dialplan reload
dialplan show
a core show channels
The command above includes an accidental-looking prefix in the last line if copied literally; use the correct CLI command shown here:
core show channels
dialplan show displays the active dialplan. Depending on the Asterisk version, you can narrow inspection by specifying a context or extension, for example dialplan show 200@internal.
Verbose console output helps identify the selected context, matched extension, current priority, application arguments, transfers, and termination conditions. Begin with a harmless Playback() or Echo() test before deploying outbound routing or external logic.
Use comments, descriptive context names, labels, and consistent formatting. Keep changes under safe change management, and verify the active configuration after every reload.
Troubleshooting Dialplan Extensions
Common Failure Scenarios
If a caller receives an extension-not-found message, identify the context assigned to the channel, verify the dialed digits against the exact or pattern extension, and confirm that the dialplan was reloaded.
If execution stops after the first action, inspect the last executed priority. The next priority may be missing, an explicit number may be duplicated, or the previous application may have transferred or terminated the call.
If an inbound caller can reach prohibited destinations, inspect the inbound context, its includes, and all reachable pattern extensions. Move the trunk to a restricted context and allow only the required destinations.
Exam-Relevant Notes
- An extension is a dialplan sequence, not necessarily a physical phone.
- A context contains extensions and acts as a routing and permission boundary.
- Priority controls execution order; priority 1 is normally the entry point.
nmeans the next sequential priority.- Applications perform actions; arguments configure those actions and are order-sensitive.
- A leading underscore identifies a pattern extension.
s,i,t,h, andeare special extension names with distinct call-flow roles.Dial()may return to a following priority, so post-dial handling is important.DIALSTATUSis commonly used to inspect the result of aDial()attempt.- Includes expose extensions from another context, so review them as part of the security model.
Related Asterisk Topics
Continue with what a dialplan is, Asterisk contexts, and dialplan priorities. Application-specific references include Answer(), Playback(), Dial(), Goto(), and Hangup(). For channel data used in routing decisions, see predefined channel variables.