Find shared TestCloud environments with the API

Use the shared TestCloud catalog to find desktop-browser and mobile-device
environments for automation or manual testing, then read artifacts from an
existing session with the v1 output endpoints. This guide does not cover
private-device discovery, requests with available=true, or starting a test session.

1. Set up authentication

Use your tenant host, https://<tenant>.katalon.io, with no trailing slash.
Authenticate with HTTP Basic: use an empty username and your Katalon API key
as the password. See
Authenticate with the v2 API
to create a key. Keep the key in your secret store and do not enable shell
tracing (set -x).

Send x-project-id on every request. For the environment catalog, the key's
user needs Execution:Read in that project. Session outputs use organization
membership instead. You can read the sessions of organizations you belong to.
You can also send x-account-id (account UUID) and
x-organization-id (organization ID) when needed to select your context.
These headers do not grant permissions by themselves.

Set KATALON_API_HOST, KATALON_API_KEY, and
KATALON_PROJECT_ID from your environment. The Bash helper below passes
credentials to curl through standard input rather than process arguments.
If the key contains " or \, escape those characters as \"
and \\ for curl's configuration format.

katalon_request() {
  : "${KATALON_API_KEY:?Missing API key}"
  printf 'user = ":%s"\n' "${KATALON_API_KEY}" |
  curl --config - --silent --show-error --fail-with-body \
    --header "x-project-id: ${KATALON_PROJECT_ID:?Missing project ID}" \
    --header 'Accept: application/json' \
    "$@"
}

2. List the shared catalog

List shared TestCloud environments:

katalon_request \
  "${KATALON_API_HOST:?Missing tenant host}/v2/tc/ees/environments?available=false&includePrivate=false"

The request has no body. This guide uses available=false and
includePrivate=false to list the shared catalog. available=false skips availability filtering and manual availability lookup.
Automation availability can still be looked up and included in the response.

Read entries from the response's items array. For each entry:

  • id identifies the environment. Treat it as an opaque value.
  • platform, platformName, and platformVersion describe the platform.
  • Desktop entries can have browser, browserName, browserVersion, and
    browserVersionType.
  • Mobile entries can have device information such as deviceName,
    deviceDisplayName, and formFactor.
  • capabilities.automation.supported and capabilities.manual.supported
    describe testing support. Treat an absent value as not supported.

The catalog is not a capacity reservation. An entry does not guarantee that
execution capacity is immediately available.

3. Narrow the catalog

Set type=automation to request automation capabilities, or type=manual
for manual-testing capabilities. Omit it to request both, in which case entries
missing either capability group are excluded; this is not the union of the
automation and manual catalogs. To find shared
desktop-browser environments for automation, use a URL-encoded q filter:

katalon_request --get \
  --data-urlencode 'available=false' \
  --data-urlencode 'includePrivate=false' \
  --data-urlencode 'type=automation' \
  --data-urlencode 'q=type==desktop_browser' \
  "${KATALON_API_HOST}/v2/tc/ees/environments"

Use q=type==mobile_device to select shared mobile-device entries instead.
The query option type selects the testing capability; the type field
inside q selects the environment category.

This endpoint does not provide a paginated response: there is no total or
continuation token. One call returns up to the first 5000 matching catalog
records, before capability filtering. Omit pageToken and size; they are not working pagination
controls. The service overrides them for this catalog read, so size does not
limit the returned items.

4. Read session artifacts and download links (v1)

Use an existing TestCloud session ID as KATALON_SESSION_ID. These output
reads use /v1/tc/ees/sessions on your tenant host; there is no /v2 path for them.
Both GET requests have no body and use the same empty-username API-key helper.

List session outputs
with exact uppercase action=DOWNLOAD to prepare download links:

katalon_request \
  "${KATALON_API_HOST}/v1/tc/ees/sessions/${KATALON_SESSION_ID:?Missing session ID}/outputs?action=DOWNLOAD"

The JSON object contains sessionId and an outputs array. An empty array
means the session has no output records and is an expected response, not an
error. Each output can contain string fields id, type, name, and value.
The set of output types can vary. Without action=DOWNLOAD, value is
returned as stored.

Set KATALON_OUTPUT_ID to an output's id to
read one output:

katalon_request \
  "${KATALON_API_HOST}/v1/tc/ees/sessions/outputs/${KATALON_OUTPUT_ID:?Missing output ID}"

The detail read always prepares value for download; it does not need an
action query. During preparation, values containing s3:// become signed
download URLs; other values remain unchanged. Neither response contains file
bytes. Fetch a returned HTTP(S) download URL separately, without the
katalon_request helper: do not send your Katalon API key to the download host.
Treat signed links as sensitive and keep them out of logs and shared examples.

5. Mobile app inputs

Use the v2 app endpoints. Upload an app file. Create its record. Get a download
URL. These calls use the authentication helper from Step 1.

Get a mobile app upload URL:

katalon_request \
  "${KATALON_API_HOST}/v2/tc/ees/apps/upload-url"

The response has signedUrl and storagePath. Save both values. Upload the
file to the signed URL without the Katalon API key:

curl --silent --show-error --fail-with-body \
  --upload-file "${KATALON_APP_FILE:?Missing app file}" \
  "${KATALON_APP_UPLOAD_URL:?Missing signed upload URL}"

Create a mobile app record
with the returned storagePath and the original file name:

katalon_request --request POST \
  --header "x-organization-id: ${KATALON_ORGANIZATION_ID:?Missing organization ID}" \
  --header 'Content-Type: application/json' \
  --data "{\"organizationId\":\"${KATALON_ORGANIZATION_ID}\",\"storagePath\":\"${KATALON_APP_STORAGE_PATH:?Missing storage key}\",\"fileName\":\"${KATALON_APP_FILE_NAME:?Missing file name}\"}" \
  "${KATALON_API_HOST}/v2/tc/ees/apps"

List mobile apps
with an organization condition in q:

katalon_request --get \
  --data-urlencode "q=organizationId==${KATALON_ORGANIZATION_ID:?Missing organization ID}" \
  "${KATALON_API_HOST}/v2/tc/ees/apps"

The required x-project-id header adds a project filter. Add an id==<UUID>
condition to the same q filter when you need one app. The list has no detail path.

Get a mobile app download URL
for a ready app:

katalon_request \
  "${KATALON_API_HOST}/v2/tc/ees/apps/${KATALON_APP_ID:?Missing app ID}/download-url"

The response contains signedUrl and fileName, not file bytes. Fetch the
signed URL separately without the Katalon API key.

6. Manage self-hosted agents

List self-hosted agents
with an organization, account, or project scope in q:

katalon_request --get \
  --data-urlencode "q=organizationId==${KATALON_ORGANIZATION_ID:?Missing organization ID}" \
  --data-urlencode 'pageToken=0' \
  "${KATALON_API_HOST}/v2/tc/ees/agents"

The agent list requires a numeric-string pageToken. Send 0 for the first
page. Use the returned pageToken value for a later page.

The x-project-id header does not add a search filter. Agent IDs are numeric.
Use the ID from a list result to
get an agent:

katalon_request \
  "${KATALON_API_HOST}/v2/tc/ees/agents/${KATALON_AGENT_ID:?Missing numeric agent ID}"

Update an agent
to set its maximum concurrent session count:

katalon_request --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"maxConcurrentSessions":4}' \
  "${KATALON_API_HOST}/v2/tc/ees/agents/${KATALON_AGENT_ID:?Missing numeric agent ID}"

Delete an agent
when it is no longer needed:

katalon_request --request DELETE \
  "${KATALON_API_HOST}/v2/tc/ees/agents/${KATALON_AGENT_ID:?Missing numeric agent ID}"

7. Private-network tunnels

List private-network tunnels
in the current account, organization, and user context:

katalon_request "${KATALON_API_HOST}/v2/tc/ees/tunnels"

Get a tunnel
by its ID. A request for an active tunnel can provision its forward proxy:

katalon_request \
  "${KATALON_API_HOST}/v2/tc/ees/tunnels/${KATALON_TUNNEL_ID:?Missing tunnel ID}"

WARNING: Delete the tunnel only when no run needs it. The service stops the
tunnel and can interrupt private-network runs.

Delete a tunnel
by its UUID:

katalon_request --request DELETE \
  "${KATALON_API_HOST}/v2/tc/ees/tunnels/${KATALON_TUNNEL_ID:?Missing tunnel ID}"

8. Read feature and execution data

List TestCloud execution features:

katalon_request "${KATALON_API_HOST}/v2/tc/ees/features"

Feature keys can vary by configuration. An enabled feature does not reserve
execution capacity.

List TestCloud executions
for an organization:

katalon_request \
  --header "x-organization-id: ${KATALON_ORGANIZATION_ID:?Missing organization ID}" \
  "${KATALON_API_HOST}/v2/tc/ees/executions"

The API checks that you belong to the organization in x-organization-id.

9. Create a desktop live-session record

Create a desktop live-session record
with an environment:

katalon_request --request POST \
  --header 'Content-Type: application/json' \
  --data '{"testSessionType":"LIVE_DESKTOP","platform":{"accountUuid":"93f0b66b-2463-4c93-a0e6-aaf94e06870f","organizationId":1234,"projectId":5678},"environment":{"platform":"windows","browser":"chrome","browserVersion":"120.0","framework":"PLAYWRIGHT"}}' \
  "${KATALON_API_HOST}/v2/tc/ees/live-sessions"

When you send environment, the response has a session record in CREATED
state. This call does not start an interactive browser session.

Next steps


Did this page help you?