
There’s a lot of long manual processes in the Teams Admin Center, like entering configuration profiles for devices like Phones, Panels, Displays, and Teams Rooms on Android. If you work as a consultant, you probably have to redo all this work on each tenant you work on. People maybe add 50-100 profiles for each tenant. This is really time-consuming.
My friend Jens Madsen asked me if it was possible to automate this? Yes, it is! Thanks for the idea Jens, and the extensive CSV file with predefined profiles for various countries/timezones.
You can find the CSV file here. (If it is downloaded as xls, open and save as CSV with comma as separator)
Now you can save hours of work and almost by one click upload this automatically. Only thing you need before running the script is a token from the Teams Admin Center.
You get this by opening the dev mode of your browser (F12 in Edge Chromium) and click network. Then go to the configuration profiles pages for one of the device types. In this case, Displays. In the Dev tab, look for the name ‘configProfiles’. Here you can find a token. Copy the token and paste it into the script when running it. That’s it!

### Teams Devices Configuration Profiles Uploader ### | |
### Version 1.0 ### | |
### Author: Alexander Holmeset ### | |
### Email: [email protected] ### | |
### Twitter: twitter.com/alexholmeset ### | |
### Blog: alexholmeset.blog ### | |
### Thanks to Jens Madsen for idea and extensive CSV ### | |
### with predefined configuration profiles. ### | |
### https://twitter.com/JensHMadsen ### | |
$PowerShellVersion = ((Get-Host).Version).Major | |
If($PowerShellVersion -eq 7){ | |
Write-Host "PowerShell 7 does not support interatctive input longer than 1024 characters." | |
Write-Host "Open script in editor and paste token in token variable at line 25 instead of read host command." | |
Write-Host "Then remove line 11 to 20." | |
return | |
} | |
Write-Host "================ Teams Devices Configuration Profiles Uploader ================" | |
Write-Host "" | |
$Token = Read-Host "Enter Teams Admin Center token to authenticate" | |
#Checking if token is valid. | |
Try{ | |
$URL = "https://admin.devicemgmt.teams.microsoft.com/api/v2/configProfiles" | |
$header = @{Authorization = "Bearer $token"} | |
$ConfigProfiles = (((Invoke-RestMethod -Uri $URL -Method GET -Headers $header -ContentType "application/json").paginatedconfigprofiles).baseinfo).id | |
} | |
Catch{Write-Host "";Write-Host "Authentication failed!" -ForegroundColor red;Return} | |
Write-Host "" | |
Write-Host "Authentication OK!" -ForegroundColor Green | |
Write-Host "" | |
function UploadConfigProfiles { | |
$URL = "https://admin.devicemgmt.teams.microsoft.com/api/v2/configProfiles" | |
$header = @{Authorization = "Bearer $token"} | |
$DeviceProfiles = Import-Csv (Read-Host "Enter full path of CSV file included filename") | |
foreach($DeviceProfile in $DeviceProfiles){ | |
$body = @" | |
{ | |
"identity":"$($DeviceProfile.identity)", | |
"deviceType":"$($DeviceProfile.deviceType)", | |
"description":"$($DeviceProfile.description)", | |
"configProfileCreationType":$($DeviceProfile.configProfileCreationType), | |
"deviceLock":"$($DeviceProfile.deviceLock)", | |
"deviceLockTimeout":"$($DeviceProfile.deviceLockTimeout)", | |
"deviceLockPin":"$($DeviceProfile.deviceLockPin)", | |
"language":"$($DeviceProfile.language)", | |
"timeZone":"$($DeviceProfile.timeZone)", | |
"timeZoneId":"$($DeviceProfile.timeZoneId)", | |
"dateFormat":"$($DeviceProfile.dateFormat)", | |
"timeFormat":"$($DeviceProfile.timeFormat)", | |
"displayScreenSaver":"$($DeviceProfile.displayScreenSaver)", | |
"screenSaverTimeout":"$($DeviceProfile.screenSaverTimeout)", | |
"displayBacklitBrightness":"$($DeviceProfile.displayBacklitBrightness)", | |
"displayBacklitTimeout":"$($DeviceProfile.displayBacklitTimeout)", | |
"displayHighContrast":"$($DeviceProfile.displayHighContrast)", | |
"silentMode":"$($DeviceProfile.silentMode)", | |
"officeStartHours":"$($DeviceProfile.officeStartHours)", | |
"officeEndHours":"$($DeviceProfile.officeEndHours)", | |
"powersaving":"$($DeviceProfile.powersaving)", | |
"loggingEnabled":"$($DeviceProfile.loggingEnabled)", | |
"loggingTypes":"$($DeviceProfile.loggingTypes)", | |
"networkDhcp":"$($DeviceProfile.networkDhcp)", | |
"networkWifi":"$($DeviceProfile.networkWifi)", | |
"networkPcPort":"$($DeviceProfile.networkPcPort)", | |
"deviceDefaultAdminPassword":"$($DeviceProfile.deviceDefaultAdminPassword)", | |
"screenCapture":"$($DeviceProfile.screenCapture)", | |
"dhcpEnabled":"$($DeviceProfile.dhcpEnabled)", | |
"hostName":"$($DeviceProfile.hostName)", | |
"domainName":"$($DeviceProfile.domainName)", | |
"ipAddress":"$($DeviceProfile.ipAddress)", | |
"subnetMask":"$($DeviceProfile.subnetMask)", | |
"defaultGateway":"$($DeviceProfile.defaultGateway)", | |
"primaryDNS":"$($DeviceProfile.primaryDNS)", | |
"secondaryDNS":"$($DeviceProfile.secondaryDNS)", | |
"theme":{"name":"$($DeviceProfile.theme)"}, | |
"usageStateIndicatorBusyStateColor":{"name":"$($DeviceProfile.usageStateIndicatorBusyStateColor)"} | |
} | |
"@ | |
Invoke-RestMethod -Uri $URL -Method POST -Headers $header -ContentType "application/json" -Body $body | |
} | |
Write-Host "Configuration profiles upload is completed!" | |
} | |
function DeleteConfigProfiles { | |
Write-Host "" | |
Write-Host "Are you sure you want to delete all configuration profiles?" | |
Write-Host "" | |
$input = Read-Host "Type Yes or No." | |
switch ($input) | |
{ | |
'Yes' { | |
If($input -like "Yes"){ | |
Write-Host "" | |
Write-Host "Deletion of configuration profiles initiated!" | |
Write-Host "" | |
} | |
} 'No' { | |
Write-Host "" | |
Write-Host 'Script aborted!' -ForegroundColor Red | |
return | |
} | |
} | |
$URL = "https://admin.devicemgmt.teams.microsoft.com/api/v2/configProfiles" | |
$header = @{Authorization = "Bearer $token"} | |
while ($ConfigProfilesCount -ne 0 ) { | |
$ConfigProfiles = (((Invoke-RestMethod -Uri $URL -Method GET -Headers $header -ContentType "application/json").paginatedconfigprofiles).baseinfo).id | |
$ConfigProfilesCount = $ConfigProfiles.Count | |
foreach($ConfigProfile in $ConfigProfiles){ | |
$count2-- | |
Write-Host "" | |
"Configuration profile deleted!" | |
$url2 = "https://admin.devicemgmt.teams.microsoft.com/api/v2/configProfiles/$ConfigProfile" | |
Invoke-RestMethod -Uri $URL2 -Method DELETE -Headers $header | |
} | |
} | |
If($input -like "Yes"){ | |
write-Host "" | |
Write-Host "Configuration Profiles deleteion completed!" | |
} | |
} | |
Write-Host "" | |
Write-Host "1: Press '1' to uplload config prolfiles to Teams Admin Center." | |
Write-Host "2: Press '2' to delete all config profies from Teams Admin Center." | |
Write-Host "Q: Press 'Q' to quit." | |
Write-Host "" | |
$input = Read-Host "Please make a selection" | |
switch ($input) | |
{ | |
'1' { | |
Write-Host "" | |
UploadConfigProfiles | |
} '2' { | |
Write-Host "" | |
DeleteConfigProfiles | |
} | |
'q' { | |
return | |
} | |
} | |
[…] https://alexholmeset.blog/2021/12/18/teams-devices-configuration-profiles-uploader/ […]
LikeLike
thank your for this great script. Not too sure I will have a super-global customer like the CSV files implies, but if I do, I already know how to handle it. 😉
best regards from Vienna, Austria
HST
LikeLike
Thanks 🙂 yeah, I guess its not often you need that an extensive list, but at least you have a list to choose from now, hehe
LikeLike
Hello Alexander,
First of all, thanks for you Script.
I have an issue with it. It’s run with this error but the configuration profiles added successfully.
Error: Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At C:\Users\XXXXXXXX\TeamsDevicesConfigurationProfiles.ps1:98 char:1
+ Invoke-RestMethod -Uri $URL -Method POST -Headers $header -ContentTy …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Could you please help meon this ?
Many thanks in advance.
LikeLike
Could be Microsoft has changed something, il test tomorrow.
LikeLike
It looks like its working. Is the profiles file in .csv format? Theres this stupid thing when you upload to onedrive, and it opens in Excel web, when you save, it saves as XLSX format.
LikeLike
Thanks for your reply.
Yes, profiles file is in csv format (with comma delimited).
Profiles are created but after creating all profiles i have this error.
LikeLike
I found the issue.
I left only one line in the csv file and deleted all the others but the file kept the lines empty.
Thanks for your help again.
LikeLike
Ah, i didnt let it finish. So the error is at the end after all profiles is uploaded to the admin portal?
LikeLike