Code samples and SDKs

Last published : Oct 31, 2026
The following Powershell script allows you to paginate and throttle seamlessly.
<#
.SYNOPSIS
  Reporting script
.DESCRIPTION
  Allows to query for device, application, enrollment profiles, software inventories, users, certificates and keystore from the customer
.NOTES
   Author: Citrix Systems Inc.
   Params:
       -Server: the server uri with port included
       -Username: username of the customer admin credentials
       -SecurePassword: password of the customer admin credentials
       -ClientId: generated by CC in the portal developer
       -ClientSecret: generated by CC in the portal developer
       -QueryTemplateFile: file with the query template body
#>

param (
   [Parameter(Mandatory=$true)][string]$Server,
   [Parameter(Mandatory=$true)][string]$QueryTemplateFile,
   [Parameter(Mandatory=$false)][string]$Username,
   [Parameter(Mandatory=$false)][Security.SecureString]$SecurePassword,
   [Parameter(Mandatory=$false)][Security.SecureString]$ClientId,
   [Parameter(Mandatory=$false)][Security.SecureString]$ClientSecret
)

[string]$CONTINUATION_TOKEN_HEADER = 'Citrix-Continuation-Token'
[string]$AUTH_TOKEN_HEADER = 'auth_token'
[string]$CITRIX_CUSTOMER_ID_HEADER = 'Citrix-CustomerId'

function Get-CemAuthenticationToken {
   Param ([string]$Username, [Security.SecureString]$SecurePassword, [string]$Server)

   $LoginUriSuffix = '/api/endpoint-management/console/$login'
   $LoginUri = $server + $LoginUriSuffix

   $Payload = @{
       login = $Username
       password = ConvertFrom-SecureString $SecurePassword -AsPlainText
   }

   $Body = (ConvertTo-Json $Payload)

   Try {
       Write-Information -Message "Authenticating ..."

       $Response = Invoke-RestMethod -Uri $LoginUri -ContentType 'application/json' -Body $Body -Method Post -Verbose
       $AuthToken = $Response.authToken

       Write-Information -Message "Authentication sucessfull"

       return $AuthToken
   }
   Catch {
       Write-Error -Message "An error ocurred while authenticating. Try again ..."
       return $null
   }
}

function Get-CemAuthenticationTokenWithSecretCredentials {
   Param ([Security.SecureString]$ClientId, [Security.SecureString]$ClientSecret, [string]$Server)

   $LoginUriSuffix = '/api/endpoint-management/console/$secretCloudLogin'
   $LoginUri = $server + $LoginUriSuffix

   $Payload = @{
       clientId = ConvertFrom-SecureString $ClientId -AsPlainText
       clientSecret = ConvertFrom-SecureString $ClientSecret -AsPlainText
   }

   $Body = (ConvertTo-Json $Payload)

   Try {
       Write-Information -Message "Authenticating with CC client secret ..."

       $Response = Invoke-RestMethod -Uri $LoginUri -ContentType 'application/json' -Headers $Headers -Body $Body -Method Post -Verbose
       $NewAuthToken = $Response.authToken

       Write-Information -Message "Authentication successful"

       return $NewAuthToken
   }
   Catch {
       Write-Error -Message "An error ocurred while authenticating with CC client secret. Check CEM version, make sure LOGIN_USING_SECRET_CLOUD_CREDENTIALS feature flag is enabled and try again ..."
       return $null
   }
}

function Get-CemAuthentication {

   If ($null -ne $ClientId -and $null -ne $ClientSecret) {
       return Get-CemAuthenticationTokenWithSecretCredentials -ClientId $ClientId -ClientSecret $ClientSecret -Server $Server
   }
   ElseIf ($null -ne $Username -and $null -ne $SecurePassword) {
       return Get-CemAuthenticationToken -Username $Username -SecurePassword $SecurePassword -Server $Server
   }

   Write-Error -Message "An error ocurred. Check script input parameters."
   return $null
}

function Debug-CemException {
   Param ([Microsoft.PowerShell.Commands.HttpResponseException]$CemException, [string]$Server)

   If ($CemException.Response.StatusCode.value__ -eq '401') {
       Write-Output 'Reauthenticating ...'

       # if authentication expire while fetching segments re-authenticate
       $AuthToken = Get-CemAuthentication
       $RequestHeaders.Set_Item($AUTH_TOKEN_HEADER, $AuthToken)
   }
   ElseIf ($CemException.Response.StatusCode.value__ -eq '429') {
       $retryAfter = $CemException.Response.Headers.RetryAfter.Delta.Seconds

       Write-Output "Retrying in ($retryAfter) seconds ..."
       Start-Sleep -s $retryAfter
   }
}

function Get-CemSegmentsInformation {
   Param ([String]$Server, [String]$Username, [Security.SecureString]$SecurePassword, [Security.SecureString]$ClientId, [Security.SecureString]$ClientSecret, $RequestHeaders, [string]$QueryPayloadFilePath)

   $ReportingUriSuffix = '/api/endpoint-management/report/$search'
   $ReportingUri = $Server + $ReportingUriSuffix

   $BodyPayload = Get-Content -Path $QueryPayloadFilePath | ConvertFrom-Json

   # replace ':' for '-' since windows path does not support ':' character
   $CurrentDate = Get-Date -Format 'dddd-MM-dd-yyyy-HH:mm:ssK'
   [string]$ResultFileName = "./result-$($CurrentDate).csv" -Replace ':','-'

   Do {

       Try {
           $Response = Invoke-WebRequest -Uri $ReportingUri -Method Post -Headers $RequestHeaders -ContentType 'application/json' -Body (ConvertTo-Json $BodyPayload)
           $Response.Content | Out-File -Append -Force -NoNewline -FilePath $ResultFileName

           Write-Output $Response.Content

           [String]$ContinuationToken = ''

           if ($Response.Headers.ContainsKey($CONTINUATION_TOKEN_HEADER)) {
               [String]$ContinuationToken = $Response.Headers[$CONTINUATION_TOKEN_HEADER]
               $RequestHeaders.Set_Item($CONTINUATION_TOKEN_HEADER, $ContinuationToken)
           }
       }
       Catch [Microsoft.PowerShell.Commands.HttpResponseException] {

           Write-Output $_.Exception.Response.ReasonPhrase
           # pretty print the json body response
           Write-Output $_.ErrorDetails.Message | ConvertFrom-Json | ConvertTo-Json

           Debug-CemException -CemException $_.Exception -Server $Server
       }
       Catch {
           Write-Error $_
           Exit
       }

   }
   Until ([string]::IsNullOrEmpty($ContinuationToken))
}

$Headers = @{}
$Headers.Add($CITRIX_CUSTOMER_ID_HEADER, $Username)

$AuthToken = Get-CemAuthentication

If ($null -eq $AuthToken) {
   Exit
}

$Headers.Add($AUTH_TOKEN_HEADER, $AuthToken)

Write-Output "Getting information ..."

Measure-Command {
   Get-CemSegmentsInformation -Server $Server -Username $Username -SecurePassword $SecurePassword -ClientId $ClientId -ClientSecret $ClientSecret -RequestHeaders $Headers -QueryPayloadFilePath $QueryTemplateFile | Out-Default
}

Write-Output "Finished."

How to use the Powershell script

Install PowerShell version 7.1 or later. To invoke the script, provide the following:
  1. Username and password of the customer admin or the Client Id and secret credentials to authenticate.
  2. The template query as a file.
  3. A server URL.