Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


Div
classtoc

In This Article

Table of Contents
stylesquare


Overview

This article covers provisioning a single user for Teams Direct Routing, and also using a CSV file to provision multiple users at the same time.Regardless of which method you use to provision your users, first connect to your Microsoft Teams services using PowerShell.  If needed, review the Teams Direct Routing - 01 - Planning and Prerequisites article for details.users for Teams direct routing in the Teams Admin Center (TAC) and PowerShell. 


Warning

IMPORTANT

Make sure your user accounts have been licensed before running these commandsconfiguring them for direct routing.  They should have a license that includes MS Teams, and the Teams Phone add-on license.  Details on licensing requirements can be found in the Teams Direct Routing - 01 - Planning and Prerequisites article.

Additionally, you should never remove a Teams Phone add-on license from a Teams user configured for direct routing until you have removed the direct routing configuration.  

Removing the Teams Phone add-on license will not remove the user's direct routing configuration.  The phone number assigned to the user will remain associated with the user account, and the phone number cannot be assigned to another user until it is cleared, or you delete the user account from your environment.

If you need to clear the phone number from an unlicensed user account, you will need to re-assign a Teams Phone add-on license, and properly remove (deprovision) the user's direct routing configuration.


Tip

TIP

If you are switching a user from a Microsoft calling plan to Teams direct routing, remove the phone number from the user, and then remove the calling plan license.  Make sure you keep the Teams Phone add-on license assigned.

Check the User's Status

The below commands can be used to view the voice properties of one or more users.  This can be useful for checking the status of a user before and after configuring them for Direct Routing.


Provision a User with the Teams Admin Center

These steps show you how to configure a single user account for Teams direct routing in the Teams Admin Center (TAC).  The TAC does not provide any feedback on a user's current direct routing status.  If you need to check the status of a user's configuration, or do any troubleshooting, you should use PowerShell. 

Info

NOTE

Make sure the user account has been properly licensed before configuring them for direct routing.  The user account should have a license that includes MS Teams, and the Teams Phone add-on license.  Details on licensing requirements can be found in the Teams Direct Routing - 01 - Planning and Prerequisites article.


Sign into the Teams Admin Center (TAC):  https://admin.teams.microsoft.com 

Assign a Direct Routing Phone Number

Users > Manage Users > Click on a user's Display Name to view their settings

Next to General Information, click Edit.

Image Added


In the right-hand flyout pane:

  • Phone Number Type:  Direct Routing
  • Assigned Phone Number:  Enter a phone number including the country code

Image Added


Click the Apply button at the bottom of the flyout pane.

Image Added


The user account's properties will update to show the applied changes.

Image Added


Assign the Voice Routing & Tenant Dial Plan Policies

Select the user account's Polices tab

Image Added


Edit the Assigned Policies

Image Added


In the right-hand flyout pane, towards the bottom of the policy list, select one of the Evolve IP policy configurations for the following:

  • Dial Plan:  EvolveIP-TenantDialPlan
  • Voice Routing Policy:  EvolveIP-<PolicyName>

Image Added


Click the Apply button at the bottom of the flyout pane.

Image Added


The user's policy assignments will update to show the applied changes.

Image Added


Info

NOTE

It can take up to 24 hours for Microsoft's services to apply the changes.  Normally it takes 10-30 minutes.




Provision Using PowerShell

These steps show you how to configure one or more user accounts for Teams direct routing using PowerShell.  Before performing these steps make sure you are connected to your Microsoft Teams services using PowerShell.  If needed, review the Teams Direct Routing - 01 - Planning and Prerequisites article for details.

Warning

IMPORTANT

The commands in this article require the latest Microsoft Teams PowerShell module.  If needed, use the Update-Module -Name MicrosoftTeams command to make sure you're on the latest version.


Info

NOTE

Make sure all user accounts have been properly licensed before configuring them for direct routing.  The user accounts should have a license that includes MS Teams, and the Teams Phone add-on license.  Details on licensing requirements can be found in the Teams Direct Routing - 01 - Planning and Prerequisites article.

Check a User's Status

The below commands can be used to view the voice properties of one or more users.  This can be useful for checking the status of a user before and after configuring them for direct routing.

Code Block
languagepowershell
themeConfluence
linenumberstrue
# View a list of the user's properties related to Direct Routing
Get-CsOnlineUser user@domain.com | FL Displ*, UserPri*, SipA*, IsSipEnabled, Inter*, TeamsUpgradeE*, Enterprise*, OnlineVoiceR*, TeamsCall*, TenantD*, OnlineDial*, LineURI

# View all of the user's properties
Get-CsOnlineUser user@domain.com | FL *

# Export a list of all voice users and their properties to a CSV file
$CsvFilePath = "C:\Path\to\file.csv"

Get-CsOnlineUser -ResultSize Unlimited | Select 
Code Block
languagepowershell
themeConfluence
linenumberstrue
# Review a list of the user's properties related to Direct Routing
Get-CsOnlineUser user@domain.com | FL Displ*, UserPri*, SipA*, EnabledIsSipEnabled, Inter*, TeamsUpgradeE*, Enterprise*, OnlineVoiceR*, TeamsCall*, TenantD*, VoicePOnlineDial*, HostedVoicemail*, OnlineDial*, OnPremLineURI, LineURI

# Review all of the user's properties
Get-CsOnlineUser user@domain.com | FL *

# Export a list of all voice users and their properties to a CSV file
$CsvFilePath = "C:\Path\to\file.csv"

Get-CsOnlineUser -ResultSize Unlimited | Select Displ*, UserPri*, SipA*, Enabled, Inter*, TeamsUpgradeE*, Enterprise*, OnlineVoiceR*, TeamsCall*, TenantD*, VoiceP*, HostedVoicemail*, OnlineDial*, OnPremLineURI, LineURI | Export-Csv $CsvFilePath -nti

Here's a description of the more important properties outputted with the above commands:

 LineURI | Export-Csv $CsvFilePath -nti

Here's a description of the more important properties outputted with the Get-CsOnlineUser command:

  • IsSipEnabled - Indicates whether the user is enabled for MS Teams.  If this is showing False, then the user account cannot be configured for direct routing.
  • EnterpriseVoiceEnabled - Indicates whether the user has been enabled for Enterprise Voice features (aka. Teams Phone).  Enterprise voice has to be enabled for Teams Direct Routing to work.
  • LineURI - Shows the provisioned phone number assigned to the user. 
  • InterpretedUserType - This can help with troubleshooting users that are not working as expected.  Unfortunately, there's a lot of "UserTypes", and Microsoft does not have them documented.  People in the Teams community have tried creating some documentation of their own, and doing a Google search for InterpretedUserType will turn up some results, which may help.  If not, you'll need to open a support case with Microsoft.
  • TeamsUpgradeEffectiveMode - For Teams direct routing to work, this should show TeamsOnly.
  • OnlineVoiceRoutingPolicy - If this is blank, the user is not assigned a voice routing policy.  When a user is configured for Teams direct routing, this should be set to an Evolve IP voice routing policy.  To view a list of voice routing policies in your tenant use the Get-CsOnlineVoiceRoutingPolicy command.
  • TenantDialPlan - If this is blank, the user is assigned to the Global tenant dial plan. To view a list of dial plans in your tenant use the Get-CsTenantDialPlan command.
  • TeamsCallingPolicy - If this is blank, the user is assigned to the Global calling policy. To view a list of calling policies use the Get-CsTeamsCallingPolicy command.
  • TeamsCallParkPolicy - If this is blank, the user is assigned to the Global call park policy. To view a list of call park policies use the Get-CsTeamsCallParkPolicy command.
  • OnlineDialinConferencingPolicy - If this shows ServiceAllowed, the user is enabled for Microsoft's Audio Conferencing.  If this is blank, the user is not enabled for Audio Conferencing.
  • OnlineDialOutPolicy - This policy defines the dial out restrictions from an audio conference.  A table of the different policies and their restrictions can be found in this Microsoft article.


The below commands can be used to view just the voice properties of one or more users.

Code Block
languagepowershell
themeConfluence
linenumberstrue
# View a user's voice properties 
Get-CsOnlineVoiceUser user@domain.com 

# View a list of all users
Get-CsOnlineVoiceUser | FT Name, Number, Location, PstnConnectivity, UsageLocation, EnterpriseVoiceEnabled

# View a list of all users and their Enterprise Voice status 
Get-CsOnlineVoiceUser -EnterpriseVoiceStatus All | FT Name, Number, EnterpriseVoiceEnabled

# View a list of users who have phone numbers assigned
Get-CsOnlineVoiceUser -NumberAssigned | FT Name, Number, EnterpriseVoiceEnabled

# View a list of users who don't have a number assigned
Get-CsOnlineVoiceUser -NumberNotAssigned | FT Name, Number, EnterpriseVoiceEnabled

# Export a list of all voice users and their properties to a CSV file
$CsvFilePath = "C:\Path\to\file.csv"

Get-CsOnlineVoiceUser | Export-Csv $CsvFilePath -nti

The Get-CsOnlineVoiceUser command contains the following properties:

  • Name - The name of the user account.
  • Id - The user account's Azure AD object ID.
  • SipDomain - The user account's SIP domain.
  • DataCenter - Shows where the user account is homed in Microsoft's services.
  • TenantId - Shows the Azure AD tenant ID
  • Number - Shows the provisioned phone number assigned to the user. 
  • Location - Shows the LIS location ID associated with the user account.  Location IDs can be found using the Get-CsOnlineLisLocation command.
  • PstnConnectivity - A value of OnPremises represents direct routing.
  • UsageLocation - The user account's usage location set in the M365 admin center.
  • EnterpriseVoiceEnabled - Indicates whether the user has been enabled for Enterprise Voice features (aka. Teams Phone).  Enterprise voice has to be enabled for Teams Direct Routing to work
  • Enabled - Indicates whether the user is enabled for MS Teams or Skype for Business Online.  If enabled is showing False, then the user account is either disabled (sign-in is blocked), or it doesn't have a license that includes MS Teams or Skype for Business Online.
  • EnterpriseVoiceEnabled - Indicates whether the user has been enabled for Enterprise Voice.  Enterprise voice has to be enabled for Teams Direct Routing to work.
  • OnPremLineURI - Specifies the Evolve IP provisioned phone number assigned to the user. The phone number must be specified using the E.164 format and be prefixed with "tel:".
  • LineURI - Shows the Evolve IP provisioned phone number assigned to the user based on the value of the OnPremLineURI parameter.  If this parameter has a phone number, and OnPremLineURI is blank, the user has been assigned a phone number from Microsoft.
  • InterpretedUserType - This can help with troubleshooting users that are not working as expected.  Unfortunately, there's a lot of "UserTypes", and Microsoft does not have them documented.  People in the Teams community have tried creating some documentation of their own, and doing a google search for InterpretedUserType will turn up some results, which may help.  If not, you'll need to open a support case with Microsoft.
  • TeamsUpgradeEffectiveMode - For Teams direct routing to work, this should show TeamsOnly.
  • OnlineVoiceRoutingPolicy - If this is blank, the user is not assigned a voice routing policy.  When a user is configured for Teams direct routing, this should be set to an Evolve IP voice routing policy.  To view a list of voice routing policies in your tenant use the Get-CsOnlineVoiceRoutingPolicy command.
  • TenantDialPlan - If this is blank, the user is assigned to the Global tenant dial plan. To view a list of dial plans in your tenant use the Get-CsTenantDialPlan command.
  • TeamsCallingPolicy - If this is blank, the user is assigned to the Global calling policy. To view a list of calling policies use the Get-CsTeamsCallingPolicy command.
  • TeamsCallParkPolicy - If this is blank, the user is assigned to the Global call park policy. To view a list of call park policies use the Get-CsTeamsCallParkPolicy command.
  • VoicePolicy - When enabled for Direct Routing, this should show HybridVoice.  If it shows BusinessVoice, the user has been assigned a Microsoft calling plan.  If it's blank, the user has not been assigned a Teams Phone add-on license.
  • HostedVoicemail - Enables a user's voice mail calls to be routed to a hosted version of Microsoft Exchange Server. It also enables Skype for Business users to directly place a call to another user's voice mail.  It is recommended to enable this for all Teams users.
  • HostedVoicemailPolicy - If this shows BusinessVoice, the user's voicemail is hosted by Microsoft.  At this time Evolve IP does not plan to host voice mailboxes.  So, BusinessVoice should be the value you see.
  • OnlineDialinConferencingPolicy - If this shows ServiceAllowed, the user is enabled for Microsoft's Audio Conferencing.  If this is blank, the user is not enabled for Audio Conferencing.
  • OnlineDialOutPolicy - This policy defines the dial out restrictions from an audio conference.  A table of the different policies and their restrictions can be found in this Microsoft article.


Provision a Single Teams User


Get the name of the EIP Voice Routing Policy, which has to be entered into the below block of PowerShell code.

Code Block
languagepowershell
themeConfluence
linenumberstrue
Get-CsOnlineVoiceRoutingPolicy | Where { $_.Identity -like "*Evolve*" }


Get the name of the EIP Tenant Dial Plan, which has to be entered in the below block of PowerShell code.

Code Block
languagepowershell
themeConfluence
linenumberstrue
Get-CsTenantDialPlan | Where { $_.Identity -like "*Evolve*" }


Provision a User for Direct Routing

Info

NOTE

Microsoft requires that all phone numbers be in the E.164 format.  This means the following:

  • Prefix the phone number with "tel:"Must include the country code
  • Include a "+" before the country code
  • No special characters or spaces to make the number human readable
  • Example:  +12154567890


Warning

IMPORTANT

In the below PowerShell code, be sure to change the relevant data on lines 2, 5, 8, & 11 to match your configuration and specific user.


Code Block
languagepowershell
themeConfluence
linenumberstrue
# Enter the name of the Evolve IP voice routing policy
$VrPolicyName = "EvolveIP-USEast"

# Enter the name of the Evolve IP tenant dial plan
$TdpPolicyName = "EvolveIP-TenantDialPlan"

# Enter the user's user principal name
$UPN = "user@domain.com"

# Enter the user's telephone number (no spaces, dashes, or parentheses)
$Phone = "tel:+16105551234"


### Begin User Provisioning ###

# This will check if the user's coexistence mode is set to TeamsOnly for Direct
# Routing. If it is not set to TeamsOnly, it will be set.
 
If ((Get-CsOnlineUser $UPN).TeamsUpgradeEffectiveMode -ne "TeamsOnly") {
  Grant-CsTeamsUpgradePolicy -Identity $UPN -PolicyName UpgradeToTeams
}

# This will configure the user's account for direct routing and add the account
# to the voice routing policy & tenant dial plan

Set-CsUserCsPhoneNumberAssignment -Identity $UPN -OnPremLineUriPhoneNumber $Phone -EnterpriseVoiceEnabled $true -HostedVoiceMail $truePhoneNumberType DirectRouting
Grant-CsOnlineVoiceRoutingPolicy -Identity $UPN -PolicyName $VrPolicyName
Grant-CsTenantDialPlan -Identity $UPN -PolicyName $TdpPolicyName

### End User Provisioning ###


Provision from a CSV File


CSV File Requirements

Create or use an existing CSV file that contains the following required fields:

  • DisplayName - User account display Name

  • UserUPN - User account's User Principal Name (Office 365 sign in address)

  • PhoneNumber - Assigned phone number including the country code (no special characters or spaces)

  • Location - Determines which location a user will be assigned

Here's an example for the US region:

DisplayName

UserUPN

PhoneNumber

Location

George Kastanza

jkastanza@seinfeild.com

16105551234

east

Elaine Benes

ebenes@seinfeild.com

16105551235

west


Here's an example for the EU region:

DisplayName

UserUPN

PhoneNumber

Location

Cosmo Kramer

ckramer@seinfeild.com

31884281234

NNpeer01

Newman

newman@seinfeild.com

31884221234

NNpeer02


Provision Users from a CSV File

Tip

TIP

Paste the below PowerShell code into an editor like the PowerShell ISE or VSCode, and run it from there.


First, get the name of your Voice Routing Policies and Tenant Dial Plan, which has to be entered into the below block of US or EU PowerShell code on lines 8, 9, & 12.

Code Block
languagepowershell
themeConfluence
linenumberstrue
Get-CsOnlineVoiceRoutingPolicy | Where { $_.Identity -like "*Evolve*" }
Get-CsTenantDialPlan | Where { $_.Identity -like "*Evolve*" }


Next, use these blocks of code, depending on your region, with the output from the previous query on lines 8, 9, & 12.  Also define the path to your CSV file on line 5.


Expand
titleExpand for US PowerShell Code


Code Block
languagepowershell
themeConfluence
linenumberstrue
[CmdletBinding()]
Param ()

# Path to the CSV file
$UserData = Import-Csv "C:\Path\to\file.csv"

# Enter the name of your voice routing policies here 
$VrPolicyNameEast = "EvolveIP-USEast"
$VrPolicyNameWest = "EvolveIP-USWest"

# Enter the name of your tenant dial plan here
$TdpPolicyName = "EvolveIP-TenantDialPlan"

# The following will loop through each entry in the CSV file and output the provisioning status to the console

ForEach ($User in $UserData) {
  
    Write-Host "`nPROVISIONING: $($User.DisplayName) ($($User.UserUPN))"

    # This will check the user's location and associate it with the correct routing policy
    If ($User.Location.trim() -eq "east") { $Vrp = $VrPolicyNameEast } 
    ElseIf ($User.Location.trim() -eq "west") { $Vrp = $VrPolicyNameWest }
    Else { Write-Host "No location defined. Continuing to the next user." -ForegroundColor Yellow; Continue }

    # This will check the user's phone number, and set it to the E.164 format 
    $PhoneNumber = ""
    $PhoneNumber = $User.PhoneNumber.trim()
    
    # Check the length of the number, and assume $PhoneNumber"+" = $User.PhoneNumber.trim()
    is not included in the number
    If ($PhoneNumber -notmatch "^\d+$" -or $PhoneNumber.Length -lt 10 -or $PhoneNumber.Length -gt 11) {
        Write-Host "User phone number is not valid: $($PhoneNumber)" -ForegroundColor Yellow
        Write-Host "Continuing to the next user." -ForegroundColor Yellow
        Continue
    }
    
    # Check if the phone number starts with the US country code, and add the "+" to Continue
the front of the }number
    If (-not($PhoneNumber.StartsWith('1')) -and $PhoneNumber.Length -eq 10) { $PhoneNumber = "tel:+1$($PhoneNumber)" }
    ElseIf ($PhoneNumber.StartsWith('1') -and $PhoneNumber.Length -eq 11) { $PhoneNumber = "tel:+$($PhoneNumber)" }
    Else { 
        Write-Host "User phone number is not valid: $($PhoneNumber)" -ForegroundColor Yellow
        Write-Host "Continuing to the next user." -ForegroundColor Yellow
        Continue
    }
    
    # This will define the user's direct routing properties
    $CsUserProp = @{
        Identity               = $User.UserUpn
        EnterpriseVoiceEnabled = $True
  PhoneNumber      HostedVoiceMail        = $True$PhoneNumber
          OnPremLineUri          = $PhoneNumber  PhoneNumberType = "DirectRouting"
    }

    # This will check if the user's coexistence mode is set to TeamsOnly. If not, it will be set.
    If ((Get-CsOnlineUser $CsUserProp.Identity).TeamsUpgradeEffectiveMode -ne "TeamsOnly") {
        Try {
            Grant-CsTeamsUpgradePolicy -Identity $CsUserProp.Identity -PolicyName UpgradeToTeams -ErrorAction Stop
            Write-Host "User set to TeamsOnly coexistence mode."
        } Catch { Write-Host "Failed to set user to TeamsOnly coexistence mode. Continuing to the next user." -ForegroundColor Yellow; Continue }
    }

  # This will configure the user's account for direct routing & add the account to your voice routing policy
    Try {         
        Set-CsUserCsPhoneNumberAssignment @CsUserProp -ErrorAction Stop
        Write-Host "User enabled for direct routing."
    } Catch { Write-Host "Failed to enable user for direct routing. Continuing to the next user." -ForegroundColor Yellow; Continue }
  
    Try {
        Grant-CsOnlineVoiceRoutingPolicy -Identity $User.UserUPN -PolicyName $Vrp -ErrorAction Stop
        Write-Host "User assigned a VRP: $($Vrp)"
    } Catch { Write-Host "Failed to assign the VRP: $($Vrp)" -ForegroundColor Yellow }

    Try {
        Grant-CsTenantDialPlan -Identity $User.UserUPN -PolicyName $TdpPolicyName -ErrorAction Stop
        Write-Host "User assigned a Tenant Dial Plan: $($TdpPolicyName)"
    } Catch { Write-Host "Failed to assign a Tenant Dial Plan: $($TdpPolicyName)" -ForegroundColor Yellow }

} # End ForEach


spacer


Expand
titleExpand for EU PowerShell Code


Code Block
languagepowershell
themeConfluence
linenumberstrue
[CmdletBinding()]
Param ()

# Path to the CSV file
$UserData = Import-Csv "C:\Path\to\file.csv"

# Enter the name of your voice routing policies here
$VrPolicyNameNNpeer01 = "EvolveIP-NLNNpeer01"
$VrPolicyNameNNpeer02 = "EvolveIP-NLNNpeer02"

# Enter the name of your tenant dial plan here
$TdpPolicyName = "EvolveIP-TenantDialPlan"

# The following will loop through each entry in the CSV file and output the provisioning status to the console

ForEach ($User in $UserData) {
  
    Write-Host "`nPROVISIONING: $($User.DisplayName) ($($User.UserUPN))"

    # This will check the user's location and associate it with the correct routing policy
    If ($User.Location.trim() -eq "NNpeer01") { $Vrp = $VrPolicyNameNNpeer01 }
    ElseIf ($User.Location.trim() -eq "NNpeer02") { $Vrp = $VrPolicyNameNNpeer02 }
    Else { Write-Host "No location defined. Continuing to next user." -ForegroundColor Yellow; Continue }

    # This will define the user's direct routing properties
    $CsUserProp = @{
        Identity               = $User.UserUpn
           EnterpriseVoiceEnabled = $True  
        HostedVoiceMailPhoneNumber          = $True
        OnPremLineUri"+$($User.PhoneNumber)"          
        PhoneNumberType    = "tel:+$($User.PhoneNumber)DirectRouting"
    }

    # This will check if the user's coexistence mode is set to TeamsOnly. If not, it will be set.
    If ((Get-CsOnlineUser $CsUserProp.Identity).TeamsUpgradeEffectiveMode -ne "TeamsOnly") {
        Try {
            Grant-CsTeamsUpgradePolicy -Identity $CsUserProp.Identity -PolicyName UpgradeToTeams -ErrorAction Stop
            Write-Host "User set to TeamsOnly coexistence mode."
        } Catch { Write-Host "Failed to set user to TeamsOnly coexistence mode. Continuing to next user." -ForegroundColor Yellow; Continue }
    }

  # This will configure the user's account for direct routing & add the account to your voice routing policy
    Try {         
        Set-CsUserCsPhoneNumberAssignment @CsUserProp -ErrorAction Stop
        Write-Host "User enabled for direct routing."
    } Catch { Write-Host "Failed to enable user for direct routing. Continuing to next user." -ForegroundColor Yellow; Continue }
  
    Try {
        Grant-CsOnlineVoiceRoutingPolicy -Identity $User.UserUPN -PolicyName $Vrp -ErrorAction Stop
        Write-Host "User assigned a VRP: $($Vrp)"
        Write-Host "User successfully provisioned for direct routing" -ForegroundColor Green
    } Catch { Write-Host "Failed to assign the VRP: $($Vrp)" -ForegroundColor Yellow }

    Try {
        Grant-CsTenantDialPlan -Identity $User.UserUPN -PolicyName $TdpPolicyName -ErrorAction Stop
        Write-Host "User assigned a Tenant Dial Plan: $($TdpPolicyName)"
    } Catch { Write-Host "Failed to assign a Tenant Dial Plan: $($TdpPolicyName)" -ForegroundColor Yellow }

} # End ForEach


spacer