Configure Teams Direct Routing, Simple Deployment via PowerShell

A massive amount of organizations are delving into Teams even deeper and assessing the calling functionality as a replacement for their existing phone system. Of the different ways of implementing Teams calling, Direct Routing seems to be the standard for large organizations. The flexibility afforded through Direct Routing is exactly what is needed in a large environment, particularly where there are other on-premises integrations at play.

I have posted before about the set up involved in Direct Routing and while it isn’t the most complex configuration in the world, I find that doing it for multiple customers gets tedious. To make this a bit easier, I’ve built a script to automate the Direct Routing provisioning process (or at least most of it) and uploaded it to GitHub.


To run the process, first make sure you have Microsoft Teams PowerShell v.2.0.0 or higher. You can check this by opening PowerShell and running the below command, then checking the version in the output.

Get-Module MicrosoftTeams

If you are not on version 2.0.0 or higher, run the below command to update:

Update-Module MicrosoftTeams

If you don’t have the module at all, then you can install with:

Install-Module MicrosoftTeams

Once the module is in place, connect to the Microsoft Teams service by running the below and logging in with your admin credentials:


Finally, download the script into your current directory and import it:

Import-Module Add-SBC.ps1

With it imported, we’re ready to rock.

Running the process

To run the process, we need to have some information ready about our configuration. The below list of parameters are required:

  • PSTN Usage Name: This is a name for a new or existing PSTN Usage Record to be used
  • FQDN: The FQDN of our SBC
  • SBC Description: A Description for our SBC
  • Voice Routing Policy Name: A name for a new or existing Voice Routing Policy to be used
  • Voice Route Name: A name for a new or existing Voice Route to be used

In addition to the above, we have the following optional paramaters:

  • SIP Signalling Port: Specify a non-default SIP Signalling Port, default is 5067
  • Send SIP Options: Specify if Teams should send SIP options to the SBC (Default is $True)
  • Forward PAI: Specify if Teams should forward PAI headers (Default is $True)
  • Failover Response Codes: Specify non-default failover response codes (Default codes are ‘408, 503, 504’)
  • Failover Time Seconds: Specify a non-Default failover response time (Default is 10)
  • PIDFLO Supported: Define is SBC supports PIDF/LO for emergency calls (Default is $False)
  • Max Concurrent Sessions: Specify the number of concurrent sessions allowed (Default for this script is 20)
  • Number Pattern: Specify the number pattern for the Voice Route (Default is a catch-all “^(\+[0-9]{7,15})$”)
  • Forward Call History: Specify if call history be forwarded (default is $False)

When we have at a minimum the required parameters and have reviewed the optional ones (we can always change later if required) we can run the function. When the file is imported as above, we can run it as in the below example:

AddSBC -PSTNUsageName "SBC-EU" -FQDN "" -SBCDescription "EU Primary SBC" -SIPSignalingPort 5067 -SendSIPOptions $true -ForwardPai $true -FailoverResponseCodes '408, 503, 504' -FailoverTimeSeconds "10" -PidfLoSupported $false -MaxConcurrentSessions "200" -VoiceRoutingPolicyName "SBC-EU-VRP" -VoiceRouteName "SBC-EU-VR" -NumberPattern "^(\+[0-9]{7,15})$" -ForwardCallHistory $false

Any existing Voice Routes, Voice Route Policies or PSTN Usages will be used if specified in the parameters so no need to worry about messing up what’s in place. The function will output progress as it goes to the Shell so we can track it’s activities. There is a 100 second pause between each activity for replication so don’t worry if it seems to be stalled. The full output is below:

The script is located on GitHub and a copy of the source is below:

##Autor: Sean McAvinue
##Twitter: @Sean_McAvinue
Function AddSBC {
    Adds and SBC for Teams Direct Routing
    -A name for the new PSTN usage record
    -FQDN of the SBC
    .PARAMETER SBCDescription
    -Description for the SBC
    .PARAMETER SIPSignalingPort (Optional)
    -the SIP Signaling Port, default value is 5067
    .PARAMETER SendSIPOptions (Optional)
    -Option to Send SIP Options, Default is $TRUE
    .PARAMETER ForwardPai (Optional)
    -Option to forward Pai Header, Default is $TRUE
    .PARAMETER FailoverResponseCodes (Optional)
    -the supportd failover response codes for direct routing, default is '408, 503, 504'
    .PARAMETER FailoverTimeSeconds (Optional)
    -the failover time (seconds), default is 10
    .PARAMETER PidfLoSupported (Optional)
    -SBC supports PIDF/LO for emergency calls, default is $FALSE
    .PARAMETER MaxConcurrentSessions (Optional)
    -Max supported concurrent sessions by SBC
    .PARAMETER VoiceRoutingPolicyName
    -Name for the Voice Routing Policy
    .PARAMETER VoiceRouteName
    -Name for the Voice Route
    .PARAMETER NumberPattern (Optional)
    -Number Pattern for the Voice Route
    .PARAMETER ForwardCallHistory (Optional)
    -Should call history be forwarded, default is $FALSE
    AddSBC -PSTNUsageName "SBC-EU" -FQDN "" -SBCDescription "EU Primary SBC" -SIPSignalingPort 5067 -SendSIPOptions $true -ForwardPai $true -FailoverResponseCodes '408, 503, 504' -FailoverTimeSeconds "10" -PidfLoSupported $false -MaxConcurrentSessions "200" -VoiceRoutingPolicyName "SBC-EU-VRP" -VoiceRouteName "SBC-EU-VR" -NumberPattern "^(\+[0-9]{7,15})$" -ForwardCallHistory $false
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $false)]
        $SIPSignalingPort = "5067",
        [parameter(Mandatory = $false)]
        $SendSIPOptions = $True,
        [parameter(Mandatory = $false)]
        $ForwardPai = $True,
        [parameter(Mandatory = $false)]
        $FailoverResponseCodes = '408, 503, 504',
        [parameter(Mandatory = $false)]
        $FailoverTimeSeconds = "10",
        [parameter(Mandatory = $false)]
        $PidfLoSupported = $false,
        [parameter(Mandatory = $false)]
        $MaxConcurrentSessions = 20,
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $false)]
        $NumberPattern = "^(\+[0-9]{7,15})$",
        [parameter(Mandatory = $false)]
        $ForwardCallHistory = $False
    ##Adds PSTN Usage Record##
    $CurrentPSTNUsage = Get-CsOnlinePstnUsage
    if (!($CurrentPSTNUsage.usage -contains "SBC")) {
        write-host "$PSTNUsageName does not exist, creating new" -ForegroundColor yellow
        Set-CsOnlinePstnUsage -Identity global -Usage @{add = "$PSTNUsageName" }
    else {
        write-host "$PSTNUsageName exists, using existing" -ForegroundColor yellow
    write-host "Pausing for PSTN Usage Replication" -ForegroundColor yellow
    start-sleep 100
    ##Add SBC to Direct Routing Configuration##
    write-host "Creating SBC"
    try {
        New-CsOnlinePSTNGateway -Fqdn $FQDN -Description $SBCDescription -Enabled $true -SipSignalingPort $SIPSignalingPort -SendSipOptions $SendSIPOptions -ForwardCallHistory $ForwardCallHistory -ForwardPai $ForwardPai -FailoverResponseCodes $FailoverResponseCodes -FailoverTimeSeconds $FailoverTimeSeconds -PidfLoSupported $PidfLoSupported -MaxConcurrentSessions $MaxConcurrentSessions -ErrorAction stop                   
    catch {
        Write-host "Error Creating SBC, stopping!" $Error -ForegroundColor red
    write-host "Pausing for SBC Replication" -ForegroundColor yellow
    start-sleep 100
    ##Add Voice Routing Policy##
    if (Get-CsOnlineVoiceRoutingPolicy -Identity $VoiceRoutingPolicyName -ErrorAction silentlycontinue) {
        write-host "Voice Routing Policy $VoiceRoutingPolicyName  exists already, using existing" -ForegroundColor yellow
    else {
        write-host "Creating Voice Routing Policy $VoiceRoutingPolicyName" -ForegroundColor yellow
        New-CsOnlineVoiceRoutingPolicy -Identity $VoiceRoutingPolicyName -OnlinePstnUsages $PSTNUsageName
    write-host "Pausing for Voice Routing Policy Replication" -ForegroundColor yellow
    start-sleep 100
    ##Create a new Voice Route
    if (get-csonlinevoiceroute -Identity $VoiceRouteName -ErrorAction silentlycontinue) {
        write-host "Voice Route $VoiceRouteName already exists, updating existing"
        set-CsOnlineVoiceRoute -Identity $VoiceRouteName -OnlinePstnUsages @{add = "$PSTNUsageName" } -OnlinePstnGatewayList @{add = "$FQDN" } 
    else {
        New-CsOnlineVoiceRoute -Identity $VoiceRouteName -OnlinePstnUsages @{add = "$PSTNUsageName" } -OnlinePstnGatewayList @{add = "$FQDN" } -NumberPattern $NumberPattern

2 thoughts on “Configure Teams Direct Routing, Simple Deployment via PowerShell

  1. Pingback: Configure Microsoft Teams Common Area Phones – Sean McAvinue

  2. Pingback: Replace Teams Outbound Caller ID with Resource Account Number – Sean McAvinue

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s