Troupeby AliveDocsSign in

Troupe Cloud

API keys

An API key is a scoped credential that belongs to an organization, for CI and other callers with nobody at the keyboard. This page covers creating one, choosing its scopes, restricting it to a project, using it, and rotating and revoking it.

Create a key

Owners and admins create keys on the organization's API keys page in the web app.

FieldMeaning
NameWhat the key list shows, up to 100 characters
PurposeOptional. A short slug that groups keys for rotation; the name's slug when left out
Expires in (days)90 by default
ProjectEvery project of the organization, or one
ScopesWhat the key may do, at most what your own role allows

Creating a key needs a password confirmation. The secret, tr_key_ followed by 43 characters, is shown once. Troupe keeps only a hash of it, so store it in your CI system's secret store before you close the dialog. Every owner of the organization is mailed when a key is created or revoked.

A key belongs to the organization, not to the person who made it: it keeps working when that person leaves.

Over the API, keys.create takes a signed-in person only. A key cannot create another key.

Scopes

A key carries the scopes you tick and nothing else. The form starts with the seven device and test scopes ticked.

ScopeLets the key
devices:readSee sessions, the accessibility tree and screenshots; get a ticket to watch a stream
devices:acquireStart, keep alive and release device sessions
devices:driveTap, type, launch apps, open URLs, change device settings; get a ticket to drive a stream
apps:installInstall, uninstall and reset apps, and set their permissions
logs:readRead device logs and crash reports
runs:readRead and follow test runs
runs:reportPublish a test run's results
builds:readRead builds and follow their logs
builds:writeStart and cancel builds, and upload their sources
artifacts:readRead artifacts and get their download URLs
artifacts:writeReserved: no procedure needs it yet
signing:useRead signing credentials' metadata and name one in a signed build
projects:readRead the organization's projects
projects:writeCreate, rename and archive projects
org:readRead the organization, its members and its invitations
org:manageRename the organization, revoke invitations, set project limits, suspend and remove trusted issuers
keys:readList the organization's keys
keys:writeRevoke keys
usage:readRead usage and limits

Whatever its scopes, a key never makes a change that grants access: it cannot create keys, invite or change members, register issuers or change signing credentials. A call without a needed scope is refused with FORBIDDEN, which names every scope the call needs.

Typical sets:

ForScopes
Driving devices from a script or an agentdevices:read, devices:acquire, devices:drive, apps:install, logs:read
Building in CI and installing the resultThe five above, and builds:read, builds:write, artifacts:read
A dashboardusage:read, projects:read, builds:read

Restrict a key to one project

A key for one project sees that project only. Device sessions it starts are in that project, a build or a session of another project is NOT_FOUND, and organization-level calls are NOT_FOUND too, except the project list, project lookups by externalRef, usage and limits, which answer for its project alone.

A key for every project must say which project a device call works in, because sessions.create, sessions.list and runs.list name none. Send the Troupe-Project header:

Shell
curl https://api.troupe.ali.ve/v1/sessions/list \
  --header "Authorization: Bearer $TROUPE_API_KEY" \
  --header "Troupe-Contract: 1.0" \
  --header "Troupe-Project: prj_…"

Without it the answer is PROJECT_REQUIRED. The header only selects a project the key already reaches. Calls that name a session, a run or a file need no header: the cloud finds the project from the id. The cloud procedures for builds and artifacts take projectId in their input instead.

Prefer a key for one project: it limits what a leaked key reaches.

Expiry

A key lasts 90 days unless you ask for fewer, and 90 at most. The one exception is a key whose purpose is exactly ci, which may last up to 365 days. Asking for more is refused with VALIDATION. An expired or revoked key is refused with UNAUTHENTICATED.

Use a key

Send the key as a bearer token to https://api.troupe.ali.ve. To see what a key is:

Shell
curl https://api.troupe.ali.ve/v1/account/get \
  --header "Authorization: Bearer $TROUPE_API_KEY" \
  --header "Troupe-Contract: 1.0"
JSON
{
  "principal": "apiKey",
  "apiKey": {
    "id": "key_…",
    "orgId": "org_…",
    "projectId": "prj_…",
    "scopes": ["devices:read", "devices:acquire", "devices:drive", "apps:install", "logs:read"]
  }
}

The client takes the key as its token and calls the device procedures exactly as it does against a local runtime:

TypeScript
import { createClient } from '@alivelabs/troupe-client'

const troupe = createClient({
  baseUrl: 'https://api.troupe.ali.ve',
  token: () => process.env.TROUPE_API_KEY,
})
const { platforms } = await troupe.call('runtime.capabilities', {})

An MCP client sends the same key: see MCP in the cloud.

Keep a key on a server or in CI. A browser page gets a stream ticket from your server instead, as device sessions shows. Twenty failed credentials a minute from one address are answered with RATE_LIMITED.

Rotate a key

Two keys with the same purpose can be active at once, which is what rotation needs:

  1. Create a second key with the same purpose and scopes.
  2. Put the new secret where the old one was.
  3. Revoke the old key once nothing uses it. The key list's Last used column tells you.

A third active key with that purpose is refused with CONFLICT (too-many-active-keys).

Revoke a key

Revoke on the key list, or keys.revoke, stops a key from its next request and ends its live device streams. It cannot be undone. A key with keys:write may revoke keys too. keys.list returns each key's name, purpose, scopes, project, status, expiry, when it was last used, and the first characters of its secret, never the secret.

Next

esc

    Type to search every page, the protocol reference and the cloud API.