Learning journey
Go through the learning journey section to get started with tasks that you can perform using the Citrix Virtual Apps and Desktops REST APIs.
This guide walks you through steps to generate your first bearer token, make your first API request, and perform some common administrative tasks. By the end of this learning journey, you will be comfortable parsing the documentation and get familiar with functionalities available to you.
This guide lists a few examples of what you can do with these APIs. We release new runbooks often. You can provide feedback on this guide and any of our APIs in our discussion forums.
Prerequisites
Before you make your first call to the service, let’s make sure that you have everything that is required.
Step 1: Create a bearer token
Tokens are passed into the authorization header of APIs. Create a bearer token for API authentication and authorization. To generate a token, use the admin credential to exchange a token.
POST https://[DdcServerAddress]/cvad/manage/Tokens HTTP/1.1
Accept: application/json
Authorization: Basic [AdminCredenticalEncodedByBase64]
<!--NeedCopy-->
The following parameters are required to create bearer token:
- a
DdcServerAddress
which is one of your on-premises DDC server address. - a
AdminCredenticalEncodedByBase64
which is your admin credentical encoded by base64. The username and password separated by a colon, UTF8-encoded, then base64-encoded.
The admin credentical can be encoded by the following powershell script:
$adminCredentical = ‘:’
$Bytes = [System.Text.Encoding]::UTF8.GetBytes($adminCredentical)
$EncodedAdminCredentical =[Convert]::ToBase64String($Bytes)
$EncodedText
<!--NeedCopy-->
After successfully calling the Token
API, you receive a response and a payload with a bearer token in the field token
. Save this token for later use, to pass the `` in authorization header as Authorization: CWSAuth bearer=
.
Note:
Bearer tokens are typically valid for an hour, after which they expires (refer to the response field expires_in). In that case, follow the same steps to generate a new token.
Step 2: Get the site ID
Know your siteId
to specify to the API service which Citrix Virtual Apps and Desktops site you want to call. Use the Me
API route to get the ``, which is used in other API calls. The Me
route is used to return information about the sites for a given customer. For on-premises Citrix Virtual Apps and Desktops, the customerId
is always CitrixOnPremises
.
Use the bearerToken
that was generated in Step 1 as header values in the request as per the following format:
GET https://[DdcServerAddress]/cvad/manage/Me HTTP/1.1
Citrix-CustomerId:
Authorization: CWSAuth Bearer=
<!--NeedCopy-->
The following is a sample response:
{
"UserId": "Test\\Administrator",
"DisplayName": "Administrator",
"ExpiryTime": "11:27:31 AM",
"RefreshExpirationTime": "10:27:31 AM",
"VerifiedEmail": null,
"IsCspCustomer": false,
"Customers": [
{
"Id": "CitrixOnPremises",
"Name": null,
"Sites": [
{
"Id": "41701c13-d857-449b-bed8-bc843e7ee9a9",
"Name": "samplecloudsite"
}
]
}
]
}
<!--NeedCopy-->
Under the Sites
array within the first element of the Customers
array, put the first element’s Id
as the siteId
. The siteId
can be saved, it will not change as long as the DaaS account remains active.
For more information, see the Me API Specification.
Step 3: Identify route structure for functional routes
The URI pattern for Citrix Virtual Apps and Desktops functional routes is as follows:
https://[DdcServerAddress]/cvad/manage/
You can make a note of the URI pattern for future use.
Hello notepad
When setting up a Citrix Virtual Apps and Desktops site, it is common that many admins use Notepad as a simple test application for any Delivery Group. Let’s use this application to show that routes are working in our site.
Note:
In this example, let’s assume that you have a machine that is already provisioned, and a delivery group created.
Example 1: Publishing an app via API (Notepad)
If you want to publish an application in Citrix Studio, go to your Delivery Group and then modify the delivery to include the application in the object. The same logic applies here. Use the /DeliveryGroups/
route collection to implement this functionality.
Step 1: Get the delivery group ID
Since we assume you already have a Delivery Group created, let’s first get the Delivery Group Id
so that you can store this information. Most API route collections have standard GET
methods implemented so getting all Delivery Groups is easy.
GET https://[DdcServerAddress]/cvad/manage/DeliveryGroups HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
<!--NeedCopy-->
We expect an array of Delivery Group objects: let’s take one of the Delivery Groups and inspect the object.
{
"Id": "5245ff16-515b-47ee-a0f3-7324cfe8a99e",
"Uid": 49,
"UserManagement": "Studio",
"Delivering": "DesktopsAndApps",
"DeliveryType": "DesktopsAndApps",
"Description": null,
"DesktopsAvailable": 0,
"DesktopsDisconnected": 21,
"DesktopsFaulted": 0,
"DesktopsUnregistered": 1,
"Enabled": true,
"HasBeenPromoted": false,
"HasBeenPromotedFrom": "Unknown",
"InMaintenanceMode": false,
"IsBroken": false,
"IsRemotePC": false,
"MinimumFunctionalLevel": "L7_6",
"Name": "Students",
"RequireUserHomeZone": false,
... // Rest of object too large to show for the example.
}
<!--NeedCopy-->
As you can see, many of the properties represented in the Students
Delivery Group are in this object. Now, you will need the Id
to pass it to the next route that you will call.
Step 2: Call a route on the particular delivery group
After you have an Id
, you are ready to call a route on the particular Delivery Group. In this case, you can POST a NewApplication object while using POST /Applications
.
A sample object is used below. Check the documentation to see how to call the route with a custom object.
POST https://[DdcServerAddress]/cvad/manage/DeliveryGroups//Applications HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
{
"NewApplications": [
{
"ApplicationFolder": "",
"ApplicationType": "HostedOnDesktop",
"IncludedUsers": [],
"InstalledAppProperties": {
"CommandLineExecutable": "",
"CommandLineArguments": "",
"WorkingDirectory": "C:\\"
},
"Name": "",
"PublishedName": ""
}
]
}
<!--NeedCopy-->
For more information, see the API Specification.
Admins must know the application name, the published name, and where the app is installed. Assuming one prepared an image and we are publishing an app off a Golden Image. Run where {executableName.exe}
in the Windows command prompt to get a valid path. In our case: notepad is located in Windows\System32\notepad.exe
for most images.
You should see Notepad added to the applications.
Example 2: Enumerating sessions and send message to a session console
Step 1: Pull all of the active sessions running within your site
Now, it’s common that you would want to pull all of the active sessions running within your site. That is pretty simple! We have a dedicated route that can return all of the sessions along with the requisite session information.
GET https://[DdcServerAddress]/cvad/manage/Sessions HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
<!--NeedCopy-->
For more information, see the API specification.
An array full of Session objects is returned, as follows:
{
"Items": [
{
"Id": "b108af54-cdaa-463e-b791-0b07a624e2b2",
"Uid": 1002,
"ApplicationsInUse": [
{
"Id": "00000000-0000-0000-0000-000000000000",
"Uid": null,
"Name": "Faculty Club"
}
],
"AppState": "Active",
"AppStateLastChangeTime": "5/8/2021 5:38:58 PM",
"Brokering": {
"AutonomouslyBrokered": false,
"DurationMilliseconds": null,
"Time": null,
"UserName": null,
"UserSid": null
},
"Client": {
"DeviceId": "WR_kcAvFgC7qh03R7jrt",
"HardwareId": "00000000",
"IPAddress": "127.0.0.1",
"Name": "HTML-1063-0750",
"Platform": "Unknown",
"ProductId": 0,
"ReceiverIPAddress": "66.165.176.60",
"ReceiverName": "WR_kcAvFgC7qh03R7jrt",
"Version": ""
},
"Connection": {
"ConnectedViaHostName": null,
"ConnectedViaIP": "10.0.0.5",
"ConnectionMode": "Brokered",
"LaunchedViaHostName": "hynth658.eastus.cloudapp.azure.com",
"LaunchedViaIP": "13.92.114.133",
"Protocol": "Hdx",
"SecureIcaActive": false,
"SmartAccessTags": []
},
... // More information omitted.
},
... // More sessions omitted.
],
"ContinuationToken": "T7UhcehawR8PBTpc-tszgA=="
}
<!--NeedCopy-->
Step 2: Set a limit on the maximum records
For performance consideration, you can set a limit on the maximum records that return when you query and search site objects using APIs. Use the limit
query parameter to specify the limit. An extra limit might also be applied at the API server side depending on the Cloud settings.
If the number of objects matching your query or search exceeds the limit, they cannot be returned using one call. Use paging to obtain all the objects through multiple API calls.
In the preceding sample response, we can see a ContinuationToken
string at the end of the response JSON object. We can pass this string value as the continuationToken
query parameter values to the same query to get the next batch of results. Repeat this step until the ContinuationToken
value in response is null, indicating there’re no more unreturned results.
GET https://[DdcServerAddress]/cvad/manage/Sessions?continuationtoken= HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
<!--NeedCopy-->
Another array of Session objects is returned, as follows:
{
"Items": [
{
"Id": "cf314e6e-0ec6-47ba-aa77-88b63d4827bb",
"Uid": 1252,
"ApplicationsInUse": [
{
"Id": "00000000-0000-0000-0000-000000000000",
"Uid": null,
"Name": "Published Web Browser"
}
],
"AppState": "Active",
"AppStateLastChangeTime": "5/8/2021 15:31:07 PM",
"Brokering": {
"AutonomouslyBrokered": false,
"DurationMilliseconds": null,
"Time": null,
"UserName": null,
"UserSid": null
},
"Client": {
"DeviceId": "WR_kcAvFgC7qh03R7jrt",
"HardwareId": "00000000",
"IPAddress": "127.0.0.1",
"Name": "HTML-1063-0750",
"Platform": "Unknown",
"ProductId": 0,
"ReceiverIPAddress": "66.165.176.60",
"ReceiverName": "WR_kcAvFgC7qh03R7jrt",
"Version": ""
},
"Connection": {
"ConnectedViaHostName": null,
"ConnectedViaIP": "10.0.0.5",
"ConnectionMode": "Brokered",
"LaunchedViaHostName": "hynth655.eastus.cloudapp.azure.com",
"LaunchedViaIP": "13.92.114.135",
"Protocol": "Hdx",
"SecureIcaActive": false,
"SmartAccessTags": []
},
... // More information omitted.
},
... // More sessions omitted.
],
"ContinuationToken": "3EOYomxNlavb8GhMCzr7wg=="
}
<!--NeedCopy-->
Repeat this step until a null ContinuationToken
is received.
For more information, see How to use paging.
Step 3: Explore actions with the sessions
Now, that seemed pretty simple. Let us take a step further by exploring what we can do with the sessions.
In the documentation link provided, you can see that $logoff
or $sendMessage
are some of the actions we can perform. Logging off someone is a common administration task but let’s do something that is less consequential such as sending a message.
You can POST a Message object to a Session by ID
and have the message show up to a logged-in user in real time. You can let them know that you added Notepad as an available application.
We can use this mechanism to warn our users about any other announcements to the site that might be applicable.
POST https://[DdcServerAddress]/cvad/manage/Sessions//$sendMessage HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
{
"Style": "Unknown",
"Title": "Hey There!",
"Text": "We just added Notepad to your machine. Happy Typing!"
}
<!--NeedCopy-->
Ensure you pass the payload.
Remember, this is a small subset of what you can do with the API. With your HTTP client of choice, you can iterate through the sessions object to log anyone off or get robust information about who is connected.
Neat tricks
So far, we have learned about the basics of the API and introductory routes that can be used. Now let’s a take a moment to explore the additional functionality and advanced scenarios that can be performed. We will get into searching, modifying existing objects and VMs, and image management.
In this section, we assume you have provisioned VMs and prepared Golden Images.
Example 3: Tagging VMs by criteria
Many admins wish to tag provisioned VMs on certain information for organization. In this example, we will go through performing a search via an API and then performing a tag.
In this example, two APIs are used, they are:
- search the machines
- associate a tag with those machines
Step 1: Get machine ID
First, search for a machine to get its Id
to be able to perform an action on it. You can refer to examples given in this guide earlier.
These routes concern actions related to specific VMs. The $
delimiter denotes actions within the API. In this case, you can apply $search
to perform a Search. However, since we need to post an object with filters and parameters of what we are looking for, we perform a POST not a GET.
POST https://[DdcServerAddress]/cvad/manage/Machines/$search?limit=100 HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
{
"SearchFilters": [
{
"Property": "SessionSupport",
"Value": "SingleSession",
"Operator": "Equals"
}
]
}
<!--NeedCopy-->
For more information, see the API specification.
The Payload with the SearchFilters
object is the standard model we use across all search operations in Citrix Virtual Apps and Desktops. The above object lists all Single Session machines. In your payload, you can have multiple filters and up to one search string. Note, how the standard search query string property commented out in the preceding example. We left this in place to show you that this is optional.
We expect to get the following back:
{
"Items": [
{
"Id": "string",
"Uid": 0,
"name": "string",
"AgentVersion": "string",
"ApplicationsInUse": [
{
"Id": "string",
"Uid": 0,
"Name": "string"
}
],
...
}
]
}
<!--NeedCopy-->
You might notice a pattern how arrays of objects return under Items. You can expect that Items of any Object type will return for any call where you expect a list of results.
Take the Id
and pass it to the next API call we will perform.
Step 2: Explore expected action in next API
Now, you have the Id
of the VM you wish to tag, let’s explore what is expected in the next API.
As expected, the functionality pertaining to the same type of object is within the route collection. In this case, the Id
of the object is encoded in the route, pass the machineId
in the route as well.
Assuming that the tag is ready to use in this example, if not you can check out /cvad/manage/Tags
to see how you can create one.
POST https://[DdcServerAddress]/manage/Machines//Tags/ HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
<!--NeedCopy-->
For more information, see the API specification.
Now you can use the tags
GET routes to return all Machines with a specific tags simplifying your management experience.
Example 4: Update a catalog image
Admins have image management pipelines in a variety of places. One common admin task after an image is generated in a certain file store is to update the catalog with the new Golden Image. With the $updateProvisioningScheme
under the MachineCatalogs
collections you can point the Machine Catalog to a newly generated image.
Let’s assume you already have a Machine Catalog you want to update, and let’s assume you have a link to our image in a public infrastructure provider.
With the following route you can post a new ProvisioningScheme
object to tell the service that you wish to update with a new image.
POST https://[DdcServerAddress]/cvad/manage/MachineCatalogs//$UpdateProvisioningScheme?async=true HTTP/1.1
Citrix-CustomerId:
Citrix-InstanceId:
Authorization: CWSAuth Bearer=
{
"MasterImagePath": "XDHyp:\\HostingUnits\\Azure001-Resource001\\image.folder\\MachineCatalog.resourcegroup\\MasterVDA001_OsDisk_1_6927d0254c194a01aa3078eec78bdca0.manageddisk",
"StoreOldImage": true,
"MinimumFunctionalLevel": "L7_20",
"RebootOptions": {
"RebootDuration": -1,
"SendMessage": false
}
}
<!--NeedCopy-->
For more information, see the API specification.
Admins can use this mechanism with an IaaS functions service allowing them to include an API call in their Dev Ops pipelines. Remember, the Dev Ops pipeline service must generate a valid token before executing this request.