Documenting with PowerShell: Syncing Unifi devices to IT-Glue

This blog should be used in together with my previous blog about Unifi documentation. This script syncs all devices to IT-Glue and makes sure the configurations are in sync with eachother.

It will overwrite any changes you’ve made to the configurations, so treat with care.

$ITGkey = "ITGlueKey"
$ITGbaseURI = ""
$UnifiBaseUri = ""
$UnifiUser = "APIUSER"
$UnifiPassword = "APIPASSWORD"

#Settings IT-Glue logon information
If (Get-Module -ListAvailable -Name "ITGlueAPI") { 
    Import-module ITGlueAPI 
Else { 
    Install-Module ITGlueAPI -Force
    Import-Module ITGlueAPI
Add-ITGlueBaseURI -base_uri $ITGbaseURI
Add-ITGlueAPIKey $ITGkey
write-host "Checking if products exist in IT-Glue, and if not creating them."
$unifiAllModels = @"
[{"c":"BZ2","t":"uap","n":"UniFi AP"},{"c":"BZ2LR","t":"uap","n":"UniFi AP-LR"},{"c":"U2HSR","t":"uap","n":"UniFi AP-Outdoor+"},
{"c":"U2IW","t":"uap","n":"UniFi AP-In Wall"},{"c":"U2L48","t":"uap","n":"UniFi AP-LR"},{"c":"U2Lv2","t":"uap","n":"UniFi AP-LR v2"},
{"c":"U2M","t":"uap","n":"UniFi AP-Mini"},{"c":"U2O","t":"uap","n":"UniFi AP-Outdoor"},{"c":"U2S48","t":"uap","n":"UniFi AP"},
{"c":"U2Sv2","t":"uap","n":"UniFi AP v2"},{"c":"U5O","t":"uap","n":"UniFi AP-Outdoor 5G"},{"c":"U7E","t":"uap","n":"UniFi AP-AC"},
{"c":"U7EDU","t":"uap","n":"UniFi AP-AC-EDU"},{"c":"U7Ev2","t":"uap","n":"UniFi AP-AC v2"},{"c":"U7HD","t":"uap","n":"UniFi AP-HD"},
{"c":"U7SHD","t":"uap","n":"UniFi AP-SHD"},{"c":"U7NHD","t":"uap","n":"UniFi AP-nanoHD"},{"c":"UCXG","t":"uap","n":"UniFi AP-XG"},
{"c":"UXSDM","t":"uap","n":"UniFi AP-BaseStationXG"},{"c":"UCMSH","t":"uap","n":"UniFi AP-MeshXG"},{"c":"U7IW","t":"uap","n":"UniFi AP-AC-In Wall"},
{"c":"U7IWP","t":"uap","n":"UniFi AP-AC-In Wall Pro"},{"c":"U7MP","t":"uap","n":"UniFi AP-AC-Mesh-Pro"},{"c":"U7LR","t":"uap","n":"UniFi AP-AC-LR"},
{"c":"U7LT","t":"uap","n":"UniFi AP-AC-Lite"},{"c":"U7O","t":"uap","n":"UniFi AP-AC Outdoor"},{"c":"U7P","t":"uap","n":"UniFi AP-Pro"},
{"c":"U7MSH","t":"uap","n":"UniFi AP-AC-Mesh"},{"c":"U7PG2","t":"uap","n":"UniFi AP-AC-Pro"},{"c":"p2N","t":"uap","n":"PicoStation M2"},
{"c":"US8","t":"usw","n":"UniFi Switch 8"},{"c":"US8P60","t":"usw","n":"UniFi Switch 8 POE-60W"},{"c":"US8P150","t":"usw","n":"UniFi Switch 8 POE-150W"},
{"c":"S28150","t":"usw","n":"UniFi Switch 8 AT-150W"},{"c":"USC8","t":"usw","n":"UniFi Switch 8"},{"c":"US16P150","t":"usw","n":"UniFi Switch 16 POE-150W"},
{"c":"S216150","t":"usw","n":"UniFi Switch 16 AT-150W"},{"c":"US24","t":"usw","n":"UniFi Switch 24"},{"c":"US24P250","t":"usw","n":"UniFi Switch 24 POE-250W"},
{"c":"US24PL2","t":"usw","n":"UniFi Switch 24 L2 POE"},{"c":"US24P500","t":"usw","n":"UniFi Switch 24 POE-500W"},{"c":"S224250","t":"usw","n":"UniFi Switch 24 AT-250W"},
{"c":"S224500","t":"usw","n":"UniFi Switch 24 AT-500W"},{"c":"US48","t":"usw","n":"UniFi Switch 48"},{"c":"US48P500","t":"usw","n":"UniFi Switch 48 POE-500W"},
{"c":"US48PL2","t":"usw","n":"UniFi Switch 48 L2 POE"},{"c":"US48P750","t":"usw","n":"UniFi Switch 48 POE-750W"},{"c":"S248500","t":"usw","n":"UniFi Switch 48 AT-500W"},
{"c":"S248750","t":"usw","n":"UniFi Switch 48 AT-750W"},{"c":"US6XG150","t":"usw","n":"UniFi Switch 6XG POE-150W"},{"c":"USXG","t":"usw","n":"UniFi Switch 16XG"},
{"c":"UGW3","t":"ugw","n":"UniFi Security Gateway 3P"},{"c":"UGW4","t":"ugw","n":"UniFi Security Gateway 4P"},{"c":"UGWHD4","t":"ugw","n":"UniFi Security Gateway HD"},
{"c":"UGWXG","t":"ugw","n":"UniFi Security Gateway XG-8"},{"c":"UP4","t":"uph","n":"UniFi Phone-X"},{"c":"UP5","t":"uph","n":"UniFi Phone"},
{"c":"UP5t","t":"uph","n":"UniFi Phone-Pro"},{"c":"UP7","t":"uph","n":"UniFi Phone-Executive"},{"c":"UP5c","t":"uph","n":"UniFi Phone"},
{"c":"UP5tc","t":"uph","n":"UniFi Phone-Pro"},{"c":"UP7c","t":"uph","n":"UniFi Phone-Executive"}]
$configTypes = @"
[{"t":"uap","n":"Unifi AP"},{"t":"usw","n":"Unifi Switch"},{"t":"ugw","n":"Unifi Gateway"},{"t":"uph","n":"Unifi VOIP"}]
"@ | ConvertFrom-Json

$unifiAllModels = $unifiAllModels | ConvertFrom-Json
$unifiModels = $unifiAllModels | Sort-Object n -Unique
$ITGConfigTypes = (Get-ITGlueConfigurationTypes).data
write-host "Check Config Types and creating if required" -ForegroundColor Green
foreach ($ConfType in $configTypes) {
    if ($ConfType.n -notin $ {
        write-host "Creating $($Model.n)" -ForegroundColor Green
        New-ITGlueConfigurationTypes -data @{
            type       = 'configuration-types'
            attributes = @{
                name = $ConfType.n

$ExistingModels = (Get-ITGlueModels -page_size 1000).data
write-host "Checkings manufacture and creating if required" -ForegroundColor Green
$Manafacture = (Get-ITGlueManufacturers -filter_name "UniFi").data
if (!$Manafacture) {
    New-ITGlueManufacturers -data @{
        type       = 'manufacturers'
        attributes = @{
            name = 'uniFi-2'
    $Manafacture = (Get-ITGlueManufacturers -filter_name "UniFi").data
write-host "Grabbing active status"
$ConfigurationStatusId = (Get-ITGlueConfigurationStatuses -filter_name 'Active').data.ID | Select-Object -Last 1
write-host "Checkings models and creating if required" -ForegroundColor Green
foreach ($Model in $unifiAllModels) {
    if ($model.n -notin $ {
        write-host "Creating $($Model.n)" -ForegroundColor Green
        New-ITGlueModels -data @{
            type       = 'models'
            attributes = @{
                'manufacturer-id' = $
                name              = $model.n


write-host "Start configuration syncing process." -foregroundColor green

$UniFiCredentials = @{
    username = $UnifiUser
    password = $UnifiPassword
    remember = $true
} | ConvertTo-Json

write-host "Logging in to Unifi API." -ForegroundColor Green
try {
    Invoke-RestMethod -Uri "$UnifiBaseUri/login" -Method POST -Body $uniFiCredentials -SessionVariable websession
catch {
    write-host "Failed to log in on the Unifi API. Error was: $($_.Exception.Message)" -ForegroundColor Red
write-host "Collecting sites from Unifi API." -ForegroundColor Green
try {
    $sites = (Invoke-RestMethod -Uri "$UnifiBaseUri/self/sites" -WebSession $websession).data
catch {
    write-host "Failed to collect the sites. Error was: $($_.Exception.Message)" -ForegroundColor Red

foreach ($site in $sites) {
    $ITGlueOrgID = $site.desc.split('()')[1]
    if (!$ITGlueOrgID) {
        write-host "Could not get IT-Glue OrgID for site $($site.desc). Moving on to next site." -ForegroundColor Yellow
    else {
        write-host "Documenting $($site.desc), using ITGlue ID: $ITGlueOrgID" -ForegroundColor Green

    $unifiDevices = Invoke-RestMethod -Uri "$UnifiBaseUri/s/$($" -WebSession $websession
    foreach ($device in $ {
 ($ExistingConfiguration = Get-ITGlueConfigurations -organization_id $ITGlueOrgID -filter_serial_number $device.serial) | select-object -last 1
        $DeviceName = if (!$ { "Unifi Device $($device.serial)" } else { $ }
        $ModelName = ($unifiAllModels | Where-Object { $_.c -eq $device.model }).n
        $modelid = $ExistingModels | Where-Object { $ -eq $ModelName } | Select-Object -last 1
        $ConfigName = ($configtypes | Where-Object { $_.t -eq $device.type }).n
        $Configurationtypeid = ($ITGConfigTypes | Where-Object { $ -eq $Configname }).id
        $ConfigurationBody = @{
            type       = "configurations"
            attributes = @{
                "organization-id"         = $ITGlueOrgID
                "name"                    = $DeviceName
                "configuration-type-id"   = $Configurationtypeid
                "configuration-status-id" = $ConfigurationStatusId
                "manufacturer-id"         = $
                "model-id"                = $
                "primary-ip"              = $device.ip
                "serial-number"           = $device.serial
                "mac-address"             = $device.mac
        if (!$ExistingConfiguration) { 
            write-host "Creating new device" -ForegroundColor Green
            New-ITGlueConfigurations -organization_id $ITGlueOrgID -data $ConfigurationBody
        else {
            write-host "Editing previous existing device" -ForegroundColor Green
            Set-ITGlueConfigurations -id ($ | Select-Object -last 1) -data $ConfigurationBody



And that’s it! this blog will be followed up by another documentation blog pretty quick, so its shorter than normal. As always, Happy PowerShelling.


  1. Gabriel June 17, 2020 at 4:47 pm

    Hi Kelvin,

    Love your blog posts, they’ve been very informative.

    Having a bit of an issue with this one though, I’m getting this error for sites that are linked back to IT Glue from your previous post.

    Editing previous existing device
    Set-ITGlueConfigurations : {“errors”:[{“status”:404,”title”:”Not found”,”detail”:”Record not found”,”source”:{“pointer”:”id”}}]}
    At C:\Users\%user%\Work\Scripts\unificonfigsync.ps1:152 char:13
    + Set-ITGlueConfigurations -id ($ …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set-ITGlueConfigurations

    I’ve confirmed the manufacturer and model entries have been added properly.

    Thanks for any help you can provide!

    1. Kelvin Tegelaar June 18, 2020 at 3:40 pm

      You might have duplicate devices, or the same name of the device in multiple locations. I’ve edited the script to accomdate this 🙂

  2. Garrett July 21, 2020 at 6:48 pm

    Hello, I’ve found great use in a lot of your scripts and you run a great blog! I’m running into the below error.. Any suggestions on what may be happening?

    Creating UniFi AP
    New-ITGlueModels : {“errors”:[{“status”:422,”title”:”Valid manufacturer_id is required”,”source”:{“pointer”:”data/attributes/manufacturer_id”}}]}
    At line:82 char:9
    + New-ITGlueModels -data @{
    + ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,New-ITGlueModels

    1. Kelvin Tegelaar July 21, 2020 at 8:06 pm

      Create a manufacture called “Unifi” in your IT-Glue system. I think its failing to create it via the API 🙂

  3. Chris Fonte August 2, 2020 at 12:35 am

    Though the Models are getting created properly, I am still getting this error:

    Set-ITGlueConfigurations : {“errors”:[{“status”:404,”title”:”Not
    found”,”detail”:”Record not found”,”source”:{“pointer”:”id”}}]}
    At line:156 char:13
    + Set-ITGlueConfigurations -id ($ …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set

    Any thoughts?

    Thanks again for your scripts!

    1. Kelvin Tegelaar August 3, 2020 at 9:11 am

      Seems like you also have some duplicate devices, the oneliner I added should take care of that though. If they are getting created correctly it might just be a bug.

    2. Brian Ventura February 2, 2021 at 10:16 am


      Were you able to get this resolved? I am running into the same issue where it thinks that ALL devices, even new ones, are existing so it fails when it tries to update the non-existent device. Any help would be appreciated!

  4. Brian Ventura September 27, 2020 at 12:37 am

    I am running into a strange issue where existing devices that were originally created by Eliot Munro’s scripts are being updated by your script just fine, but all devices added since we last ran his script are not being created in ITG, regardless if it is a new UniFi site or an existing one with new devices added. These are all brand new devices so they do not already existing elsewhere in our ITG. What’s stranger is the PS output is showing as if it’s trying to update an existing configuration and erroring when it does not exist:

    Documenting , using ITGlue ID:
    Editing previous existing device
    Set-ITGlueConfigurations : {“errors”:[{“status”:404,”title”:”Not found”,”detail”:”Record not found”,”source”:{“pointer”:”id”}}]}
    At line:155 char:13
    + Set-ITGlueConfigurations -id ($ …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set-ITGlueConfigurations

    I am assuming it’s an issue at line 129 where it determines if it is an existing config or not, but I don’t know how to fix it from there on my own.

    1. Kelvin Tegelaar September 28, 2020 at 9:18 am

      I’m thinking there are some duplicate devices which are causing this. Can you confirm that? if so, I can check how to resolve 🙂

      1. Brian Ventura September 29, 2020 at 1:46 am

        I checked and confirmed there are no duplicate devices at all, and anything that is existing it is updating just fine. As a test I deleted one of the existing devices and the script would not re-add it and that device also started throwing an error now where it wasn’t before I deleted it.

        Based on the PS window scrollback I think the test logic to see if a device is new or existing is not processing it right and thinks everything is existing, then when it tries to update an ‘existing’ device that isn’t really in ITG it throws that error. I just have no idea how to troubleshoot or fix the logic since at the surface checking for the existing serial should be good. I even looked at the ITG device IDs the script says are existing but they do no exist in our ITG instance.

        And these are all brand new UBNT devices that were purchased through Ingram so they should be truly new. It really does not make any sense but this is what it is.

      2. Brian Ventura October 5, 2020 at 8:23 pm

        Any chance you have had some time to look at the logic for new vs existing and find a solution? Just checking in.

  5. Pingback: Cyberdrain Automatic Documentation Scripts to Hudu – MSPP

  6. Jonathan August 2, 2021 at 3:17 pm

    Awesome script! I’m also wondering if there’s a way we can populate the Wireless settings into glue too, I know you can pull the wireless password from the UniFi API as well.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.