There are several elements used to build an XML dialplan. In general, the dialplan groups logically similar functions and calling activities into a ‘context’. Within a context are extensions, each with ‘condition’ rules and associated ‘actions’ to perform when the condition rules match.

The following is a sample dialplan to illustrate these concepts. We have left out the XML “wrapper” to help make the basic concepts more clear:

<context name="example">
    <extension name="500">
        <condition field="destination_number" expression="^500$">
            <action application="bridge" data="user/500"/> 
        </ condition>
    </ extension>
    <extension name="501">
        <condition field="destination_number" expression="^501$">
            <action application="bridge" data="user/501"/>
            <action application="answer"/>
            <action application="sleep" data="1000"/>
            <action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/>
        </ condition>
    </ extension>
</ context >

Each rule is processed in order until you reach the action tag which tells SBC what action to perform. You are not limited to only one condition or action tag for a given extension.
In our above example, a call to extension 501 rings the extensions. If the user does not answer, the second action answers the call, and following actions delay for 1000 milliseconds (which is 1 second) and connect the call to the voicemail system.


Contexts are a logical grouping of extensions. You may have multiple extensions contained within a single context.
The context tag has a required parameter of ‘name’. There is one reserved name, any, which matches any context. The name is used by incoming call handlers (like the [Sofia] SIP driver) to select the dialplan that runs when it needs to route a call. There is often more than one context in a dialplan.
A fully qualified context definition is shown below. Typically you’ll not need all the trimmings, but they are shown here for completeness.

<?xml version="1.0"?>
    <document type="freeswitch/xml">
        <section name="dialplan" description="Regex/XML Dialplan">
        <!-- the default context is a safe start -->
            <context name="default">
                <!-- one or more extension tags -->
            < !-- more optional contexts -->


Extensions are destinations for a call. This is the meat of SBC routing dialed numbers. They are given a name and contain a group of conditions, that if met, will execute certain actions.
A ‘name’ parameter is required: It must be a unique name assigned to an extension for identification and later use.
For example:

<extension name="Your extension name here">
        <action(s) .../>
<extension name="500" continue="true">


Dialplan conditions are typically used to match a destination number to an extension. They have, however, much more power than may appear on the surface.
SBC has a set of built-in variables used for testing. In this example, the built-in variable destination_number is compared against the regular expression ^500$.
This comparison is ‘true’ if is set to 500.

<extension name="500">
    <condition field="destination_number" expression="^500$">
        <action application="bridge" data="user/500"/> 

Each condition is parsed with the Perl Compatible Regular Expression library. (go here for PCRE syntax information).

If a regular expression contains any terms wrapped in parentheses, and the expression matches, the variables $1,$2..$N will be set to the matching contents within the parenthesis, and may be used in subsequent action tags within this extension’s block.

For example, this simple expression matches a four digit extension number, and captures the last two digits into $1.

<condition field="destination_number" expression="^\d\d(\d\d)$">
    <action application="bridge" data="sofia/internal/$"/>

A destination number of 3425 would set $1 to 25 and then bridge the call to the phone at

Multiple Conditions (Logical AND)

You can emulate the logical AND operation available in many programming languages using multiple conditions. When you place more than one condition in an extension, all conditions must match before the actions will be executed. For example, this block will only execute the actions if the destination number is 500 AND it is Sunday.

 <condition field="destination_number" expression="^500$"/>
  <condition wday="1">

Keep in mind that you must observe correct XML syntax when using this structure. Be sure to close all conditions except the last one with />. The last condition contains the final actions to be run, and is closed on the line after the last action.
By default, if any condition is false, SBC will move on to the anti-actions or the next extension without even evaluating any more conditions.

Multiple Conditions (Logical OR, XOR)

It is possible to emulate the logical OR operation available in many programming languages, using multiple conditions. In this situation, if one of the conditions matches, the actions are executed.
For example, this block executes its actions if the destination number is 501 OR the destination number is 502.

 <condition field="destination_number" expression="^501|502$">

This method works well if your OR condition is for the same field. However, if you need to use two or more different fields then use the new regex syntax

  <extension name="Regex OR example 1" continue="true">
    <condition regex="any">
      <!-- If either of these is true then the subsequent actions are added to execute list -->
      <regex field="caller_id_name" expression="Some User"/>
      <regex field="caller_id_number" expression="^1001$"/>
      <action application="log" data="INFO At least one of the conditions matched!"/>
      <!-- If *none* of the regexes is true then the anti-actions are added to the execute list -->
      <anti-action application="log" data="WARNING None of the conditions matched!"/>

Using this method it becomes easier to match the caller’s name OR caller ID number and execute actions whether either is true.

A slightly more advanced use of this method is demonstrated here:

 <extension name="Regex OR example 2" continue="true">
    <condition regex="any" break="never">
      <regex field="caller_id_name" expression="^Michael\s*S?\s*Collins"/>
      <regex field="caller_id_number" expression="^1001|3757|2816$"/>
      <action application="set" data="calling_user=mercutioviz" inline="true"/>
      <anti-action application="set" data="calling_user=loser" inline="true"/>
      <action application="answer"/>
      <action application="sleep" data="500"/>
      <action application="playback" data="ivr/ivr-welcome_to_freeswitch.wav"/>
      <action application="sleep" data="500"/>
    <condition field="${calling_user}" expression="^loser$">
      <action application="playback" data="ivr/ivr-dude_you_suck.wav"/>
      <anti-action application="playback" data="ivr/ivr-dude_you_rock.wav"/>
  <extension name="Regex XOR example 3" continue="true">
    <condition regex="xor">
      <!-- If only one of these is true then the subsequent actions are added to execute list -->
      <regex field="caller_id_name" expression="Some User"/>
      <regex field="caller_id_number" expression="^1001$"/>
      <action application="log" data="INFO Only one of the conditions matched!"/>
      <!-- If *none* of the regexes is true then the anti-actions are added to the execute list -->
      <anti-action application="log" data="WARNING None of the conditions matched!"/>

Basically, for this new syntax you can have a condition to have a “regex” attr instead of “field” and “expression” etc. When there is a “regex” attr, that means you plan to have one or more tags that are similar to the condition tag itself that it has field and expression in it.

The value of the “regex” attr is either “all” or “any” or “xor indicating if all expressions must match or just any expression or only one must match(xor) . If it’s set to “any” it will stop testing the regex tags as soon as it finds one match, if it is set to “all”, it will stop as soon as it finds one failure.

From there it will behave like a normal condition tag either executing the actions or anti-actions and breaking based on the “break” attr.

The basic difference here is once there is a “regex” attr, the tags parsed for “all” or “any” take the place of the single “field” and “condition”

 <extension name="Inbound_external"> 
    <condition regex="any"> 
      <regex field="${sip_from_host}" expression="domainA"/> 
      <regex field="${sip_from_uri}" expression="1234567890@domainB"/> 
      <regex field="${sip_from_uri}" expression="user@domainC"/> 
      <regex field="caller_id_name" expression="^(John Smith)$"/> 
      <regex field="caller_id_number" expression="^(55512341)|(55512342)|(55512343)$"/> 
      <action application="set" data="domain_name=domainZ"/> 
      <action application="transfer" data="${destination_number} XML domainZ"/> 

This is another example to show that all regex conditions must be true, then the action will get executed; otherwise, the anti-action will. This is the same logic as follows:

Basically, the <condition regex="all"> tells the parser, “Hey, execute the <action>’s only if all regexes PASS, otherwise execute any <anti-action>’s”.

<condition regex="all">
  <regex field="${sip_gateway}" expression="^${default_provider}$"/>
  <regex field="${emergency_call}" expression="^true$"/>
  <regex field="${db(select/emergency/autoanswer)}" expression="^1$"/>
  <!-- the following actions get executed if all regexes PASS -->
   <action application="set" data="call_timeout=60"/>
   <action application="set" data="effective_caller_id_name=${regex(${caller_id_name}|^Emerg(_.*)$|Auto%1)}"/>
   <action application="set" data="autoanswered=true"/>
   <action application="bridge" data="user/1000@${domain_name},sofia/gateway/1006_7217/${mobile_number}"/>
  <!-- the following anti-actions are executed if any of the regexes FAIL -->
   <anti-action application="set" data="effective_caller_id_name=${regex(${caller_id_name}|^Emerg(_.*)$|NotAuto%1)}"/>
   <anti-action application="set" data="call_timeout=30"/>
   <anti-action application="set" data="autoanswered=false"/>
   <anti-action application="bridge" data="user/1000@${domain_name},sofia/gateway/1006_7217/${mobile_number}"/>

Complex Condition/Action Rules

Here is a more complex example, performing time-based routing for a support organization. The user dials extension 1100. The actual support extension is 1105 and is staffed every day from 8am to 10pm, except Friday, when it is staffed between 8am and 1pm. At all other times, calls to 1100 are sent to the support after-hours mailbox.

<extension name="Time-of-day-tod">
    <!--if this is false, FreeSWITCH skips to the next *extension*.-->
    <condition field="destination_number" expression="^1100$" break="on-false"/>
    <!--Don't bother evaluating the next condition set if this is true.-->
    <condition wday="6" hour="8-12" break="on-true">    <!--Fri, 8am-12:59pm-->
        <action application="transfer" data="1105 XML default"/>
    <condition wday="1-5" hour="8-21" break="on-true">   <!--Sunday-Thursday, 8am-9:59pm-->
        <action application="transfer" data="1105 XML default"/>
    <condition> <!--this is a catch all, sending the call to voicemail at all other times. -->
        <action application="voicemail" data="default $domain 1105"/>

In this example, we use the break=never parameter to cause the first condition to ‘fall-through’ to the next condition no matter if the first condition is true or false. This is useful to set certain flags as part of extension processing. This example sets the variable begins_with_one if the destination number begins with 1.

<extension name="break-demo">
 <!-- because break=never is set, even when the destination does not begin
      with 1, we skip the action and keep going -->
 <condition field="destination_number" expression="^1(\d+)$" break="never">
   <action application="set" data="begins_with_one=true"/>
 <condition field="destination_number" expression="^(\d+)$">
    ...other actions that may query begins_with_one...


Condition statements can match against channel variables, or against an array of built in variables.

Built-In Variables

The following variables, called ‘caller profile fields’, can be accessed from condition statements directly:

Dialplan Variable Description
context Why can we use the context as a field? Give us examples of usages please.
rdnis Redirected Number, the directory number to which the call was last presented.
destination_number Called Number, the number this call is trying to reach (within a given context)
dialplan Name of the dialplan module that are used, the name is provided by each dialplan module. Example: XML
caller_id_name Name of the caller (provided by the User Agent that has called us).
caller_id_number Directory Number of the party who called (caller) — can be masked (hidden)
ani Automatic Number Identification, the number of the calling party (caller) — cannot be masked
aniii The type of device placing the call ANI2
uuid Unique identifier of the current call? (looks like a GUID)
source Name of the FreeSWITCH module that received the call (e.g. PortAudio)
chan_name Name of the current channel (Example: PortAudio/1234).
network_addr IP address of the signaling source for a VoIP call.
year Calendar year, 0-9999
yday Day of year, 1-366
mon Month, 1-12 (Jan = 1, etc.)
mday Day of month, 1-31
week Week of year, 1-53
mweek Week of month, 1-6
wday Day of week, 1-7 (Sun = 1, Mon = 2, etc.) or “sun”, “mon”, “tue”, etc.
hour Hour, 0-23
minute Minute (of the hour), 0-59
minute-of-day Minute of the day, (1-1440) (midnight = 1, 1am = 60, noon = 720, etc.)
time-of-day Time range formatted: hh:mm[:ss]-hh:mm[:ss] (seconds optional) Example: “08:00-17:00”
date-time Date/time range formatted: YYYY-MM-DD hh:mm[:ss]~YYYY-MM-DD hh:mm[:ss]
(seconds optional, note tilde between dates) Example: 2010-10-01 00:00:01~2010-10-15 23:59:59

Need more help with this?
Don’t hesitate to contact us here.

Was this helpful?

Yes No
You indicated this topic was not helpful to you ...
Could you please leave a comment telling us why? Thank you!
Thanks for your feedback.