Workspot provides a REST API for Workspot Control. This API uses standard REST concepts and provides a simple command interface for performing administrative tasks.
This guide shows you how to use the API. The examples use Microsoft PowerShell, which should be readable enough that non-PowerShell users can treat them as pseudo-code when creating equivalent routines.
The API is available for Workspot installations in both the Microsoft Azure and Google GCP Clouds. The two behave identically, except that the "redeploy," "screenshotDesktop," "moveDesktop," and "cancelMoveDesktop" commands are not currently available for GCP.
The basics of making API calls are covered below in Preparing to Use the API and Making Workspot API Calls. A PowerShell example is given below in Example: Get a Workspot Usage Report.
How it Works
Signing Into the API
Users sign into the API using Workspot Administrator credentials using OAuth 2.0 authentication. After that they can make calls to the API, which replicate most of the functionality of the Control UI and in some cases exceed it.
Status, Polling, and Retries
Success is not guaranteed. Always check HTTP return code and the body of the response.
Many commands are asynchronous, returning a “StatusURL” field with the URL to poll with the “operation” call until the command completes.
Synchronous commands do not return a response until they have completed (successfully or unsuccessfully).
Connection Throttling
The API has per-customer throttling that rejects calls if they are issued too quickly. This throttling puts API calls into three categories, with a higher limit for lightweight read-only (GET) calls than heavyweight or very heavyweight calls.
Rejected calls will return an HTTP 400 status code with details in the body of the reply that include an “X-Retry-After” code giving the recommended time to wait in seconds before retrying. For example:
{
"X-Retry-After-Secs": 12,
"description": "RateLimitExceeded",
"error": "TooManyRequests"
}
Descriptions of Individual API Calls
Most commands are self-documenting, but some of the more complex ones are described in detail later in this article.
Recent and Upcoming Releases
Current Release
Control API 2.8.
Control API 2.9
Update scheduled for:
US Control: July 26, 2025, from 0200-0300 UTC.
EU Control: July 29, 2025, from 0200-0300 UTC.
Many new API calls in several categories:
Template management: list, clone, publish, unpublish, register, and delete templates.
Gateway management: Create and manage Gateways and Gateway Clusters.
Clouds: List Clouds and the regions, zones, and networks in each Cloud.
Known Limitations
The new API "Gateway Reboot" command (/v1.0/rdgateways/clusters/{clusterName}/gateways/{gatewayName}/reboot) is currently synchronous but will become an asynchronous command soon.
Accessing the Workspot Control API
The Workspot Control API is reached via https://api.workspot.com.
The preferred URLs are:
https://api.eu.workspot.com:443 for customers with Control deployments in the EU region.
https://api.us.workspot.com:443 for customers with Control deployments in the Us region.
You can also reach the Control API from the old address of https://api.workspot.com.
Documentation for Individual API Calls
The API is largely self-documenting, as shown in the image below. Clicking the api-controller link on the homepage shows a complete list of calls and their syntax. Clicking on an API call expands it to show a detailed view.
Some calls are also explained in more detail later in this article.
List of API Calls
HTTP Type | Command | Description |
GET | /v1.0/bundles | Returns a list of all application bundles |
POST | /v1.0/bundles | Creates a new application bundle |
GET | /v1.0/bundles/{bundleId} | Returns an application bundle details |
POST | /v1.0/bundles/{bundleId} | Updates an existing application bundle |
DELETE | /v1.0/bundles/{bundleId} | Deletes an application bundle |
GET | /v1.0/cloudAppPools | Returns a list of all application server pools |
POST | /v1.0/cloudAppPools | Creates an application server pool |
GET | /v1.0/cloudAppPools/{cloudAppPoolId} | Returns the details about an application server pool |
DELETE | /v1.0/cloudAppPools/{cloudAppPoolId} | Deletes an application server pool |
GET | /v1.0/cloudAppPools/{cloudAppPoolId}/appServers | Returns a list of application servers in a pool |
GET | /v1.0/cloudAppPools/{cloudAppPoolId}/appServers/{appServerId} | Returns details for a single application server |
DELETE | /v1.0/cloudAppPools/{cloudAppPoolId}/appServers/{appServerId} | Deletes a Cloud app server |
POST | /v1.0/cloudAppPools/{poolId} | Updates an application server pool |
GET | /v1.0/cloudAppPools/applications | Returns a list of all application server applications |
POST | /v1.0/cloudAppPools/applications | Creates an application |
GET | /v1.0/cloudAppPools/applications/{appId} | Returns application details |
POST | /v1.0/cloudAppPools/applications/{appId} | Updates an application |
DELETE | /v1.0/cloudAppPools/applications/{appId} | Deletes an application |
GET | /v1.0/clouds | Returns information about public clouds |
GET | /v1.0/clouds/{subscriptionName}/customImages | Returns information about Custom Images |
POST | /v1.0/clouds/{subscriptionName}/customImages | Adds a new Custom Image |
GET | /v1.0/clouds/{subscriptionName}/networks | Returns information about Cloud networks |
GET | /v1.0/clouds/{subscriptionName}/regions | Returns list of regions |
GET | /v1.0/clouds/{subscriptionName}/regions/{region}/networks | Returns information about Cloud networks in a region |
GET | /v1.0/clouds/{subscriptionName}/regions/{region}/securityGroups | Returns information AWS security groups |
GET | /v1.0/clouds/{subscriptionName}/regions/{region}/zones | Returns list of Zones for provided region |
GET | /v1.0/clouds/{subscriptionName}/templates | Returns information about templates |
GET | /v1.0/clouds/{subscriptionName}/templates/{templateName} | Returns information about templates |
DELETE | /v1.0/clouds/{subscriptionName}/templates/{templateName} | Deletes template from cloud subscription |
POST | /v1.0/clouds/{subscriptionName}/templates/{templateName}/clone | Clones a new template from an existing template |
POST | /v1.0/clouds/{subscriptionName}/templates/{templateName}/draft | Draft the template |
POST | /v1.0/clouds/{subscriptionName}/templates/{templateName}/preview | Preview the template |
POST | /v1.0/clouds/{subscriptionName}/templates/{templateName}/publish | Publish the template |
POST | /v1.0/clouds/{subscriptionName}/templates/build | Builds a new template Image |
POST | /v1.0/clouds/{subscriptionName}/templates/register | Registers a new template Image |
GET | /v1.0/clouds/{subscriptionName}/templates/vmClasses | Returns information about VM Classes required to create Templates |
GET | /v1.0/clouds/rdgateways/images | Returns information Market place images required to create gateway cluster (managed gateways) |
GET | /v1.0/clouds/rdgateways/vmClasses | Returns information about VM Classes required to create gateway cluster (managed gateways) |
POST | /v1.0/desktops/{desktopId}/cancelUpgradeDesktop | Cancels a upgrade desktop operation |
POST | /v1.0/desktops/{desktopId}/retainDesktop | Sets the retention period for a desktop on suspension. |
POST | /v1.0/desktops/{desktopId}/upgradeDesktop | Upgrades a persistent desktop to the specified pool |
GET | /v1.0/globalDesktops | Returns information on available Global Desktop Applications |
GET | /v1.0/globalDesktops/{globalDesktopId} | Return details of Global Desktop |
POST | /v1.0/globalDesktops/{globalDesktopId}/pools | Assign pools to global desktop application |
GET | /v1.0/groups | Returns a list of all groups |
POST | /v1.0/groups/{groupId}/bundle | Assigns an application bundle to a user group |
GET | /v1.0/groups/{groupId}/globalDesktops | Returns information on global desktops assigned to a group |
POST | /v1.0/groups/{groupId}/globalDesktops | Assign a global desktop application to a group |
DELETE | /v1.0/groups/{groupId}/globalDesktops/{globalDesktopId} | Unassign a global desktop application from a group |
GET | /v1.0/licenses | Returns a list of Workspot licenses for each VM type purchased |
GET | /v1.0/operation/{operationId} | Returns status of an asynchronous operation |
GET | /v1.0/policies | Get List of Policies |
GET | /v1.0/pools | Returns a list of all desktop pools |
POST | /v1.0/pools | Creates Desktop Pool |
GET | /v1.0/pools/{poolId} | Returns the details for a single pool |
GET | /v1.0/pools/{poolId}/agentToken | Returns Agent token for the pool |
POST | /v1.0/pools/{poolId}/customdesktop | Creates a desktop in custom cloud pool |
GET | /v1.0/pools/{poolId}/desktops | Returns a list of desktops in a pool |
POST | /v1.0/pools/{poolId}/desktops | Creates a desktop |
GET | /v1.0/pools/{poolId}/desktops/{desktopId} | Returns details for a single desktop |
DELETE | /v1.0/pools/{poolId}/desktops/{desktopId} | Deletes a desktop |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/cancelMoveDesktop | Cancels a move desktop operation |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/moveDesktop | Moves a persistent desktop to the specified pool |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/pause | Pauses a desktop |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/reboot | Reboots a desktop |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/redeploy | Redeploys a desktop |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/resume | Resumes a desktop |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/screenshotDesktop | Takes a screen shot of the desktop |
POST | /v1.0/pools/{poolId}/desktops/{desktopId}/tags | Sets tags for a desktop |
POST | /v1.0/pools/{poolName} | Updates a desktop pool. |
GET | /v1.0/pools/loginOptions | Get login options for desktop pool |
GET | /v1.0/rdgateways/authenticationOptions | Returns information about authentication options required to create gateway cluster (managed gateways) |
GET | /v1.0/rdgateways/clusters | Returns information about each gateway cluster (managed gateways) |
POST | /v1.0/rdgateways/clusters | Creates Gateway Cluster |
GET | /v1.0/rdgateways/clusters/{clusterId}/regions/{clusterRegionId}/rdgateways | Returns information about each gateway in a given cluster |
GET | /v1.0/rdgateways/clusters/{clusterId}/regions/{clusterRegionId}/rdgateways/{gatewayId}/connections | Returns information about the Client connections for a gateway in the specified gateway cluster |
GET | /v1.0/rdgateways/clusters/{clusterId}/regions/{clusterRegionId}/rdgateways/{gatewayId}/performance | Returns system performance statistics such as CPU and memory usage for a gateway in the specified cluster |
POST | /v1.0/rdgateways/clusters/{clusterName} | Updates GatewayCluster |
DELETE | /v1.0/rdgateways/clusters/{clusterName} | Deletes GatewayCluster |
POST | /v1.0/rdgateways/clusters/{clusterName}/gateways | Creates Gateway Host in a cluster |
DELETE | /v1.0/rdgateways/clusters/{clusterName}/gateways/{gatewayName} | Deletes Gateway Host from a cluster |
POST | /v1.0/rdgateways/clusters/{clusterName}/gateways/{gatewayName}/enable | Enables Gateway Host from a cluster |
POST | /v1.0/rdgateways/clusters/{clusterName}/gateways/{gatewayName}/reboot | Reboots Gateway Host from a cluster |
POST | /v1.0/rdgateways/clusters/{clusterName}/publish | Publish GatewayCluster |
POST | /v1.0/reports/generateusagereport | Generates a report of active users |
GET | /v1.0/staleDevices | Returns all stale devices. |
DELETE | /v1.0/staleDevices | Deletes given list of stale devices from Control. |
POST | /v1.0/users | Creates a user |
GET | /v1.0/users/{email}/ | Returns user details |
DELETE | /v1.0/users/{email}/ | Deletes a user |
POST | /v1.0/users/{email}/assignCostCenter | Assigns a cost center to a user |
POST | /v1.0/users/{email}/desktops | Assigns a desktop to a user |
DELETE | /v1.0/users/{email}/desktops/{desktopId} | Unassigns a desktop from user |
DELETE | /v1.0/users/{email}/globalDesktops/{globalApplicationId} | Unassign Global Desktop Application from a user |
GET | /v1.0/users/{email}/globalDesktops/{globalDesktopId} | Returns Global Desktop Application details for a user |
POST | /v1.0/users/{email}/globalDesktops/{globalDesktopId}/pools | Assign pools to user’s global desktop application |
DELETE | /v1.0/users/{email}/globalDesktops/{globalDesktopId}/pools | Deallocate the pools from user’s global desktop application |
POST | /v1.0/users/{email}/logoff | Signs a user out of a desktop session |
POST | /v1.0/users/{email}/pools | Assigns a user to a given pool |
POST | /v1.0/users/{email}/refreshGroupEntitlements | Refreshes group entitlements for given user |
POST | /v1.0/users/{email}/remoteAssistanceInvitation | Invites a user to a remote assistance session |
POST | /v1.0/users/{email}/sendMessage | Sends a message to a user's desktop |
Limitations
Concurrent Provisioning of Desktops
Only a limited number of desktop provisioning requests can be outstanding at any given time. This is across all Clouds and pools. If the current limit is exceeded, any rejected requests will have a status message like this:
{
"status": "Failed",
"startTime": "2024-02-06T10:50:37.621Z",
"endTime": "2024-02-06T10:50:37.644Z",
"details": null,
"errorInfo": {
"error": "maxConcurrentProvisioningError",
"description": "You have reached the max concurrent provisionings allowed. Please wait for some time and try again."
}
}
In addition to this limit, no desktops are provisioned in parallel. Provisioning is always one desktop at a time.
Details About Selected Commands
Taking a Desktop Screen Shot
The API allows you to take screen captures of desktops. The snapshot is of the login screen only; it returns nothing if there’s an active desktop session.
When the screenshot is complete, the Status URL contains a link to the screen capture. This is typically used to debug boot issues, such as the desktop being unavailable because a Windows Update is being applied. The screenshot expires after 15 minutes.

Remote Assistance API Call

Remote assistance sessions can now be initiated from the Control API (in addition to from the Control UI). The parameters for the API call are:
Email address: The address Control associates with the end-user needing assistance.
desktopID: The desktop ID string of the end-user, as given by the API.
Password: A temporary password used only for this Remote Assistance session, set by the administrator.
poolID: The ID of the desktop pool containing the end-user’s desktop.
As with any Remote Assistance session, the end-user’s system will generate a .msrincident file. This will be transferred to Workspot Control by the Workspot Agent on the desktop, then uploaded to the Cloud. A link to this file is contained in the Status URL response.
The Expert role for the Remote Assistance session can be accepted by any user with access to the .msrincident file, the password, and who has a desktop with access to the same network as the end-user. In other words, once the expert has the .msrincident file and the password, a standard Remote Assistance session is the next step.
The .msrincident file expires one hour after creation, so the Remote Assistance session must be started before then.
The response format is given below.

Moving Desktops
The moveDesktop command lets you transfer a persistent desktop to a different pool while keeping it assigned to the same user. The desktop is transferred, the new desktop is powered up, and when this succeeds, the old desktop is deleted. However, a snapshot of the original is retained and can be restored by Workspot Support.
Note: This command is available only on Azure, and for persistent desktops only.
How it Works
Moving a desktop does the following:
The source desktop is shut down.
A snapshot is made of the source desktop.
A copy of the desktop is made in the target pool.
The new desktop is powered on.
The Workspot Agent registers the desktop.
The end-user's assignment is transferred to the new desktop. When the end-user launches the desktop, everything seems the same as before, including the desktop's DNS name.
The source desktop is deleted.
Best Practices When Moving Desktops
Moving desktops can be disruptive to users and can run into throttling limits with Cloud providers. Use these best practices when moving desktops:
Do not reboot or redeploy a desktop VM while migration is in progress. During migration, the desktop will be inaccessible and the end-user may try to reboot it. To minimize this problem, move desktops during off-hours, inform the users of the downtime, or both.
Limit the number of simultaneous moveDesktop calls. The number of outstanding API calls to create or move desktops should be capped at ten for your entire enterprise.
Add a delay of 60 seconds or more between moveDesktop calls.
Limitations
The moveDesktop and cancelMoveDesktop calls are available only for Azure persistent desktops.
Desktops that are suspended, are part of a regional disaster recovery event, or have a connected user cannot be moved.
Both the source and the target pools must be in the same Azure region.
The target desktop pool has to use a VM that's consistent with the source pool. For example, you cannot move a GPU workstation into a non-GPU pool. In general, the SKUs have to be the same.
Troubleshooting
Failures in the early stages of the move leave the source desktop in place, and it is still the copy assigned to the end-user. Very early failures (when powering down or backing up the source desktop) cause the source desktop to be powered back on, making it available to the user.
If the failure happens later in the process, the source desktop remains powered down. If the end-user's desktop assignment hasn't been transferred to to the target desktop, rebooting the source desktop is all that is required. Otherwise, use the cancelMoveDesktop API command to bring back the source desktop.
If for some reason the Workspot Agent takes more than a few hours to register the desktop with Workspot Control, auto-registration will fail and will have to be registered manually with the pool's Agent Token by running “C:\Program Files\Workspot Agent\reregister_poolvm.bat tokenvalue" on the desktop VM.
Using the API
Before you can use the API, you must do the following:
Contact Workspot and request API access, which is not enabled by default.
Once API access is enabled, a “Setup > API tab” will appear in Workspot Control. This tab contains two parameters you need to access the API:
The Client ID, which uniquely identifies your organization’s API access.
The Client Secret, which validates your identity.

You can generate new API security credentials at any time, at which point any existing ones become invalid.
To access the API, you need to copy both the Client ID and the Client Secret. The Client Secret is normally hidden except for a few digits. Press the Reveal button to make the Client Secret visible.
You now have the information you need to make API calls.
Making Workspot API Calls
A Workspot REST API call is consists of a properly formatted HTTP POST, GET, or DELETE command with a base URL of https://api.us. workspot.com/ or https://api.eu. workspot.com/, which from here on we will call https://api.REGION.workspot.com.
Each API session starts with authentication, which provides an access token that is included with each subsequent request.
Scripting
A PowerShell example is shown below, using a desktop usage report as the example.
Postman is anoter popular option. See Using Postman with the Control API for more information.
Authentication
To use the API, you need to authenticate yourself. This process normally uses an OAuth 2.0 token or an Entra ID token. Entra ID tokens are mandatory on Entra-ID-only deployments.
The rest of this article assumes you are using an OAuth 2.0 token
For Entra ID authentication, see Using Entra ID Authentication with the Control API.
The OAuth token is generated through a call to https://api.REGION.workspot.com/oauth/token. Its parameters include the string “Client_ID:Client_Secret” that you got from Workspot Control, and a few other parameters, such as the email and password of a Control administrator. See the sample code for details.
This token remains valid until it expires an hour later, at which point you use the same procedure to generate a new one.
Once you have the OAuth token, you can use the other functions of the API.
Example: Get a Workspot Usage Report
The example below creates an OAuth token and then calls the API to retrieve a usage report for the indicated date range.
In all the examples in this document, the parameters are declared at the top, but are left blank for security reasons. For this code example, there are two sets of parameters: OAuth token parameters and usage report parameters.
The OAuth parameters are:
Client ID
Client Secret
Control User (email address of a Control admin account)
Control Password
The user report parameters are:
Start Date for the report in YYYY-MM-DD format, no more than 30 days in the past
End date for the report, as above
Optional CSV path for the output file. The report is always fetched in JSON format (the only supported option). If the CSV option is specified, the output is converted into CSV format and saved to the specified file. Otherwise, it is displayed without conversion on the PowerShell console, as shown below:

Most of these values should be self-explanatory except for the following:
costCenter is the value in the AD user record field, if any, selected to represent which accounting group the user belongs to. If the cost center feature is not enabled, this will always be blank. See Using the Cost Center Feature in Workspot Control
timeSpent is the number of hours the user spent actively signed in to desktops and apps.
Sessions are the number of times the user-initiated a new desktop or application session.
Usage Report Request Flow
This example uses Windows PowerShell. The code does the following:
After declaring variables (left blank here for security), the admin user’s credentials are converted into base64 and the API is called to get the authentication token.
This is done with an HTTP POST request to https://api.REGION.workspot.com/oauth/token.
This URL is not self-documented on https://api.REGION.workspot.com. See the code for invocation details.
Then the API is called to generate the usage report.
This is done with an HTTP POST request to https://api.REGION.workspot.com/v1.0/reports/generateusagereport.

Report generation is asynchronous, so the request returns before the report is ready, providing a status/download URL for the request. This URL is tested every five seconds with an HTTP GET until the report is ready. When the report is ready, it is provided in the body of the HTTP response.
Usage Request Code
################################################################################ Sample script to run a Workspot Usage report (for up to a thirty day window ###########################################################################################################
# Variable initialization #
$ApiClientId = "" #Workspot Control API Client ID
$ApiClientSecret = "" #Workspot Control API Client Secret
$WsControlUser = "" #Workspot Control Administrator user email address
$WsControlPass = "" #Workspot Control Administrator user password
$StartDate = "" #First date of range for report, format YYYY-MM-DD
$EndDate = "" #Last date of range for report, format YYYY-MM-DD
$CsvPath = "" #Optional path to output directly to CSV
############################
$ApiClientPair = "$($ApiClientId):$($ApiClientSecret)"
$EncodedApiCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($ApiClientPair))
$HeaderAuthValue = "Basic $EncodedApiCreds"
$Headers = @{Authorization = $HeaderAuthValue}
$PostParameters = @{username=$WsControlUser;password=$WsControlPass;grant_type='password'}
$ApiReturn = Invoke-RestMethod -Uri "https://api.workspot.com/oauth/token" -Method Post -Body $PostParameters -Headers $Headers
$ApiToken = $ApiReturn.Access_Token
$Headers = @{Authorization =("Bearer "+ $ApiToken)}$RestUri =
$ReportParams = @{
end = $EndDate
format = "JSON"
start = $StartDate
}
$ReportParamsJson = $ReportParams | ConvertTo-Json
$ReportStatusUrl = (Invoke-RestMethod -Uri "https://api.workspot.com/v1.0/reports/generateusagereport" -Method Post -Headers $Headers -Body $ReportParamsJson -ContentType 'application/json').StatusUrlDo {
Start-Sleep -Seconds 5
$StatusReturn = Invoke-RestMethod -Method GET -ContentType "application/json" -Uri
$ReportStatusUrl -Headers $Headers} Until($StatusReturn.Status -ne "InProgress")If($CsvPath) { #Output to path specified for CSV file (Invoke-RestMethod $StatusReturn.details.downloadUrl).UsersUsage | Export-CSV
$CsvPath -NoTypeInformation}
$ReportArray = (Invoke-RestMethod $StatusReturn.details.downloadUrl).UsersUsage #Write report to object in JSON format
$ReportArray #Display report to PowerShell Console