Virtualization, technology, and random rantings with a focus on Citrix and VMware.

Tag: api

Get That Outta Here! : Releasing Citrix Cloud User Licenses Via API In Accordance With Citrix EULA

*Update. Changes made due to API only allowing 100 licenses to be released at one time.*

Building on getting the licenses on the last post, how about a way to release them? Obviously you will need to follow the guidelines laid out by Citrix EULA on when you can release licenses: Citrix License Usage.

You do have the option to use the console in Citrix Cloud, but if you prefer to do things via script, you can do that as well!

Important note to make…. The format of the consumerList is what presented the biggest issue. With a bit of assistance from a teammate, it was possible to get the proper way to format the data.

This is the format to have the data in:

Link to developer API document

You’ll notice the consumerList = @() in there. It is expecting to have an array of consumerList be passed to it. If you do not format this way, you will get invalid character errors.

Example of format that will fail all so miserably and give you that wonderful invalid character error:

This is an example of the output that will work and prevent frustration:

Example with five of users:

Example of result of successful release of 5 users:

# Script to release licenses from Citrix Cloud. Tested with PowerShell ISE. Also requires secure-client.csv with ID, Secret, and CustomerID in CSV to pass to Citrix Cloud.
# This must be used in accordance with Citrix EULA for users not having accessed in 30+ day period. Example below is targeting where users that have not logged in over 60 days.
# This will report on what users are in that group over 60 days. You can do a quick check using $releaseUsers.count before doing the release to see how many licenses will be released.
# ALWAYS check the exported report of users before releasing to make sure you are releasing the licenses you are expecting to.

$date           = (Get-Date).AddDays(-60)
$creds          = Import-Csv "c:\scripts\secure-client.csv"
$CLIENT_ID      = $creds.ID
$CLIENT_SECRET  = $creds.Secret
$CUSTOMER_ID    = $creds.CustomerID
$tokenUrl       = ''
$reportName     = "user-license-toRelease.csv"
$getDate        = Get-Date -Format MMddyyyy
$reportLocation = "C:\scripts\logs"

$response       = Invoke-WebRequest $tokenUrl -Method POST -Body @{
  grant_type    = "client_credentials"
  client_id     = $CLIENT_ID
  client_secret = $CLIENT_SECRET

$token = $response.Content | ConvertFrom-Json

$headers              = @{
  Accept              = "application/json"
  Authorization       = "CwsAuth Bearer=$($token.access_token)"
  'Citrix-CustomerId' = $CUSTOMER_ID
$resourceLocUrl = "$CUSTOMER_ID/sites"
$response       = Invoke-WebRequest $resourceLocUrl -Headers $headers
$content        = $response.Content | ConvertFrom-Json
$siteID         = $

$headers              = @{
  Accept              = "application/json"
  Authorization       = "CwsAuth Bearer=$($token.access_token)"
  'Citrix-CustomerId' = $CUSTOMER_ID
  'Citrix-InstanceId' = $siteID

$consumerList = Invoke-RestMethod "" -Method GET -Headers $headers | Select-Object consumerList -ExpandProperty consumerList -ExcludeProperty consumerList
$releaseUsers = $consumerList | Where-Object {[DateTime]$_.latestLogonTime -lt $date} 
$releaseUsers | Export-Csv "$reportLocation\$getDate-$reportName" -Append -NoTypeInformation

if($releaseUsers.count -gt 100){

$smallerCounter = $releaseUsers.Count
$toSkip = 0


$smallerList = $releaseUsers | Select-Object -Skip $toSkip -first 100

$body = @{
    productEdition = "XAXDFull"
    licenseType    = "user"
    consumerList   = @(
} | ConvertTo-Json

Invoke-RestMethod "" -Method POST -Body $body -Headers $headers -ContentType 'application/json'

$toSkip += 100
$smallerCounter -= 100

} Until ($smallerCounter -lt 100)

$smallerList = $releaseUsers | Select-Object -Skip $toSkip -first $smallerCounter

$body = @{
    productEdition = "XAXDFull"
    licenseType    = "user"
    consumerList   = @(
} | ConvertTo-Json

Invoke-RestMethod "" -Method POST -Body $body -Headers $headers -ContentType 'application/json'


Moving Control Plane To Cloud: Setting Up Cloud SDK And Authentication Profiles

This will be first in a series of posts relating to what I found in moving to Citrix Cloud and some of the gotchas I encountered.

Update** Added change to switch profiles to: Get-XDAuthentication -ProfileName “Cloud-Test” -Verbose**

This was a good article to get started with using the Cloud SDK to replace your other SDK you installed with Citrix Studio ( Important note, if you install this with Studio installed, Studio will no worky after the installation.

One of the other things you will have to do, is create an API access account that will download a secureclient.csv that you will use to authenticate and allow you to run commands against Citrix Cloud.

Logon to the Citrix Cloud at and get authenticated.

Click on the hamburger menu in the upper left.

Click on “Identity and Access Management.”

Click on “API Access.”

Fill out the name and click “Create Client.”

Copy and save the “ID” and “Secret.”

Click to download and save the “secureclient.csv” file to store in a safe location.

I added the “CustomerId” field to my secureclient file to pass to the XDCredential setup. To get this, you can see your CCID on the upper-right hand side underneath your name while you are logged into Citrix Cloud.

Below is what I used to configure my access to do the connections. One thing I noticed, if you name the profile anything other than “default,” it prompts for authentication and caused issues for automated scheduled tasks.

# Script to setup Citrix Cloud credential profile
asnp Citrix*

$secureClientProd = “C:\scripts\logs\secureclient-1.csv"
$secureClientTest = “C:\scripts\logs\secureclient-2.csv"
$xdCredsProd = import-csv $secureClientProd
$xdCredsTest = import-csv $secureClientTest

# Set prod profile
Set-XDCredentials -CustomerId $xdCredsProd.CustomerId -SecureClientFile $secureClientProd -ProfileType CloudAPI –StoreAs "default"

# Set test profile if you have a test cloud account
Set-XDCredentials -CustomerId $xdCredsTest.CustomerId -SecureClientFile $secureClientTest -ProfileType CloudAPI –StoreAs "Cloud-Test"

# List profiles
Get-XDCredentials -ListProfile

# Load credentials
Get-XDCredentials -ProfileName "default"

# To change profile credentials
Get-XDAuthentication -ProfileName "Cloud-Test"

# Clear Cloud credentials if you wish to delete a profile
Clear-XDCredentials -ProfileName "profilename"

So what I did to modify most of the scripts I was using before, was to remove the -AdminAddress and add these lines to the top of the scripts, then proceed business as normal. This allowed me to do the same things I was doing before and pass the API securecred file information.

asnp Citrix*
Get-XDCredentials -ProfileName "default"
From Update section to show the change of the profile

Links to other articles in the series:

Part 2 Of Cloud Migration Series: Part 2

Part 3 Of Cloud Migration Series: Part 3

Part 4 Of Cloud Migration Series: Part 4

Powered by WordPress & Theme by Anders Norén