In modern enterprise unified communications architectures powered by Microsoft Teams Phone, assigning telephone numbers to users, call queues, auto attendants, and shared common area phones is a core administrative task. Historically, administrators assigned phone numbers using legacy Skype for Business cmdlets such as Set-CsUser -OnPremLineURI. However, Microsoft has completely modernized telephone number lifecycle management, introducing the dedicated Set-CsPhoneNumberAssignment, Get-CsPhoneNumberAssignment, and Remove-CsPhoneNumberAssignment cmdlets in the Microsoft Teams PowerShell module.
This modernized framework provides a unified interface across all three primary telephone connectivity models: Microsoft Calling Plans, Operator Connect, and Direct Routing (SBC). In addition to assigning telephone numbers and extension formats (E.164), Set-CsPhoneNumberAssignment binds emergency location identifiers directly to the user’s phone identity, ensuring regulatory compliance with dynamic emergency calling laws. This guide covers how to query available phone numbers, assign telephone numbers with extensions, bind emergency civic locations, and automate batch provisioning via PowerShell.
Understanding Modern Phone Number Assignment Types
The Set-CsPhoneNumberAssignment cmdlet supports all three primary PSTN connectivity architectures available in Microsoft Teams Phone:
CallingPlan: Telephone numbers purchased directly from Microsoft or ported into Microsoft 365. The telephony infrastructure and PSTN breakout are managed entirely in the cloud by Microsoft.OperatorConnect: Numbers provided and provisioned by certified telecommunications carriers via the Operator Connect partner program, managed through Microsoft cloud APIs.DirectRouting: Enterprise-managed numbers routed through on-premises or cloud-hosted Session Border Controllers (SBCs) connected to custom SIP trunks.
Regardless of the connectivity type, all telephone numbers must be formatted according to the international ITU-T E.164 standard (e.g., +442079460123), optionally followed by an extension parameter (e.g., ;ext=104).
Connecting to Teams PowerShell and Auditing Current Numbers
To administer telephone numbers, launch an elevated PowerShell console and authenticate with Microsoft 365 tenant credentials having the Teams Administrator role:
# Import the Teams PowerShell module and authenticate
Import-Module MicrosoftTeams
Connect-MicrosoftTeams
Before assigning a number to a user, inspect all unassigned or available phone numbers configured within your tenant using Get-CsPhoneNumberAssignment:
# List available unassigned numbers in the tenant
Get-CsPhoneNumberAssignment -ActivationState Activated -Capabilities PhoneCall |
Where-Object { -not $_.AssignedPstnTargetId } |
Select-Object TelephoneNumber, NumberType, City
To inspect the telephone number currently assigned to a specific user:
# Query telephone number assignment for a specific user
Get-CsPhoneNumberAssignment -AssignedPstnTargetId "[email protected]"
Assigning a Direct Routing Phone Number
When provisioning a telephone number routed through your enterprise SBC (Direct Routing), specify the user’s User Principal Name (UPN), the E.164 phone number, and declare the -PhoneNumberType DirectRouting parameter:
# Assign a Direct Routing phone number to a user
Set-CsPhoneNumberAssignment -Identity "[email protected]" `
-PhoneNumber "+442079460123" `
-PhoneNumberType DirectRouting
To assign a phone number that includes an internal extension for three-digit or four-digit branch dialing:
# Assign a phone number with an internal extension
Set-CsPhoneNumberAssignment -Identity "[email protected]" `
-PhoneNumber "+442079460123;ext=104" `
-PhoneNumberType DirectRouting
Assigning Calling Plan or Operator Connect Numbers with Emergency Locations
For Calling Plan and Operator Connect telephone numbers, telecommunications regulations (such as Kari’s Law and RAY BAUM’S Act in the United States, as well as European emergency routing directives) mandate that every assigned geographic phone number must be associated with a verified emergency civic address.
First, retrieve the unique LocationId of the verified office location:
# Retrieve verified emergency location identifiers
Get-CsOnlineLisCivicAddress | Select-Object CivicAddressId, Description, City, PostCode
Then, assign the telephone number alongside the mandatory -LocationId parameter:
# Assign Calling Plan number with validated emergency location
Set-CsPhoneNumberAssignment -Identity "[email protected]" `
-PhoneNumber "+442079460125" `
-PhoneNumberType CallingPlan `
-LocationId "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Updating or Reassigning Emergency Locations for Active Users
When an employee relocates to a different office branch or floor, their assigned emergency address must be updated without unassigning their existing phone number. Pass the new LocationId to Set-CsPhoneNumberAssignment:
# Update emergency location for an existing assigned phone number
Set-CsPhoneNumberAssignment -Identity "[email protected]" `
-PhoneNumber "+442079460125" `
-PhoneNumberType CallingPlan `
-LocationId "b2c3d4e5-f6a7-8901-bcde-f12345678901"
Unassigning Phone Numbers from Deprovisioned Users
When an employee leaves the organization or transitions away from a telephony-enabled role, release the telephone number back to the tenant pool using Remove-CsPhoneNumberAssignment:
# Unassign telephone number and return it to the available pool
Remove-CsPhoneNumberAssignment -Identity "[email protected]" `
-PhoneNumber "+442079460123" `
-PhoneNumberType DirectRouting
Automating Bulk Phone Number Provisioning via CSV
In large enterprise deployments, manual single-user provisioning is inefficient. Automate the onboarding workflow by importing a structured CSV file containing user email addresses, telephone numbers, number types, and optional location IDs:
# Import CSV containing onboarding telephony batch
$Assignments = Import-Csv -Path "C:\Deploy\TeamsPhoneAssignments.csv"
foreach ($Entry in $Assignments) {
Write-Host "Assigning $($Entry.PhoneNumber) to $($Entry.UserPrincipalName)..." -ForegroundColor Cyan
try {
$Params = @{
Identity = $Entry.UserPrincipalName
PhoneNumber = $Entry.PhoneNumber
PhoneNumberType = $Entry.PhoneNumberType
ErrorAction = "Stop"
}
if ($Entry.LocationId) {
$Params.LocationId = $Entry.LocationId
}
Set-CsPhoneNumberAssignment @Params
Write-Host "Successfully assigned $($Entry.PhoneNumber)" -ForegroundColor Green
}
catch {
Write-Warning "Failed to assign $($Entry.PhoneNumber) to $($Entry.UserPrincipalName): $_"
}
}
Troubleshooting Common Phone Number Assignment Errors
When administering Teams Phone assignments, watch out for these common issues:
- Missing Teams Phone Standard License: Attempting to assign a telephone number to a user without an active Microsoft Teams Phone Standard license will result in a
UserIsNotLicensedExceptionerror. Ensure licensing is assigned in Microsoft Entra ID prior to executing the cmdlet. - Invalid E.164 Formatting: Numbers missing the leading international plus prefix (
+) or country code (e.g., entering02079460123instead of+442079460123) will be rejected by validation filters. - Number Already Assigned: If a number is currently bound to another user or a deprovisioned resource account,
Set-CsPhoneNumberAssignmentwill throw a conflict error. Locate the conflicting assignment usingGet-CsPhoneNumberAssignment -TelephoneNumber "+442079460123"and release it withRemove-CsPhoneNumberAssignmentbefore reassigning. - Direct Routing Enterprise Voice Flag: When assigning Direct Routing numbers, verify that the user’s Enterprise Voice capability is enabled.
Set-CsPhoneNumberAssignmentenables Enterprise Voice automatically on modern module releases, but verification can be performed usingGet-CsOnlineUser -Identity $User | Select-Object EnterpriseVoiceEnabled.
Using Set-CsPhoneNumberAssignment provides a modern, standardized, and auditable methodology for administering enterprise telephone numbers across global Microsoft Teams deployments.