temperDocs
Menu

API reference

Team

Team: per-person console sign-in (sessions), members, API keys and webhook settings.

Console sign-in: start (public, used by the console)

GET/v1/console/auth/{provider}/start

Used by the console server / browser, not by the SDKs. The console generates a PKCE verifier and passes challenge = base64url(SHA-256(verifier)); the control plane records the state (10 minutes, single use) and redirects with 302 to the Google / GitHub consent page. return_to must be under the configured console URL, otherwise 400. If sign-in with this provider is not configured, 503 login_unavailable. Rate-limited per IP (30 per minute); beyond that, 429 rate_limited.

Parameters

ParameterInTypeDescription
challengerequiredquerystring

The base64url S256 PKCE challenge (43–128 characters).

return_torequiredquerystring (uri)

Where in the console to return after sign-in (usually the console's /api/auth/finish).

Responses

  • 302Redirect to the provider's consent page
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
  • 429A count limit was reached (this is not rate limiting; retrying will not help until something is released)
  • 503Temporarily unable to complete the request; `error` tells the cases apart: `environment_not_placed` (not placed on a host within 15 seconds), `environment_not_running` (not up within 90 seconds), `host_unavailable` (host offline), `guest_unavailable` (the VM cannot be reached or disconnected midway), `exec_failed` (the process could not be started inside the VM), `exec_timeout` (a synchronous exec still had not finished after its timeout), `file_operation_failed` (a file operation hit an unexpected error).

Console sign-in: provider callback (public)

GET/v1/console/auth/{provider}/callback

Not for developers to call: the callback URL registered with Google / GitHub. If the state is valid, the code is exchanged for the provider's token and the account and verified email are fetched (Google: email_verified; GitHub: the primary email or any verified email from /user/emails). On first sign-in the account is linked to the member by email (a member already linked to a different account is not relinked), then a 302 redirects to return_to: on success with code (60 seconds, single use, usable only together with the PKCE verifier from start); on failure with error: provider_denied (the user cancelled at the provider), provider_error (token exchange failed), email_not_verified, not_a_member, identity_in_use (the member matching the email is already linked to a different account), rate_limited (more than 10 attempts for the same email within 10 minutes). If the state is missing, expired or already used, there is nowhere to redirect, so 400 is returned.

Parameters

ParameterInTypeDescription
statequerystring
codequerystring
errorquerystring

Responses

  • 302Redirect to `return_to` with `code` or `error`
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
  • 429A count limit was reached (this is not rate limiting; retrying will not help until something is released)
  • 503Temporarily unable to complete the request; `error` tells the cases apart: `environment_not_placed` (not placed on a host within 15 seconds), `environment_not_running` (not up within 90 seconds), `host_unavailable` (host offline), `guest_unavailable` (the VM cannot be reached or disconnected midway), `exec_failed` (the process could not be started inside the VM), `exec_timeout` (a synchronous exec still had not finished after its timeout), `file_operation_failed` (a file operation hit an unexpected error).

Console sign-in: exchange the code for a session token (used by the console server)

POST/v1/console/sessions

Called by the console server with the code from the callback and the PKCE verifier from start (no API key). Returns a session token temper_cs_... (this one time only; the console stores it in an HttpOnly cookie). After that, Authorization: Bearer temper_cs_... works on every /v1 endpoint just like an API key, but identifies the member; it expires after 12 hours idle or 7 days after sign-in.

If the member belongs to several developers (teams) and no developer_id is given, no team is chosen for them: 409 choose_developer with a developers list. The code is not consumed; choose a team and resend with developer_id. Code expired, used, or verifier mismatch: 400 invalid_code. Not a member of that team: 403. Rate-limited per IP.

Request body application/json · CreateConsoleSessionRequest

FieldTypeDescription
coderequiredstring
verifierrequiredstring

The PKCE verifier for the challenge sent at start.

developer_idstring | null

Which team to choose when the member belongs to several.

Responses

  • 201Session ConsoleSession
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 409`choose_developer`: choose a team and try again
  • 415Missing `Content-Type: application/json` (`unsupported_media_type`)
  • 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
  • 429A count limit was reached (this is not rate limiting; retrying will not help until something is released)
  • 500Internal error (details are recorded only in server logs)

Switch team (get a session bound to a different team)

POST/v1/console/sessions/switch

Sessions only (an API key gets 403 session_required). The old session is invalidated and a new one is returned (the "recent sign-in" time carries over). Not a member of that team: 403.

Request body application/json

FieldTypeDescription
developer_idrequiredstring

Responses

  • 201New session ConsoleSession
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 415Missing `Content-Type: application/json` (`unsupported_media_type`)
  • 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
  • 500Internal error (details are recorded only in server logs)

Sign out (invalidate the current session)

DELETE/v1/console/session

Sessions only (an API key gets 403 session_required).

Responses

  • 204Signed out
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 500Internal error (details are recorded only in server logs)

Who am I

GET/v1/me

The current developer (team), member (null when using an API key) and authentication method; with a session, also every team this account can access (for switching).

Responses

  • 200Current identity Me
  • 401Missing, invalid or revoked key
  • 500Internal error (details are recorded only in server logs)

Team members

GET/v1/members

Both sessions and API keys can list members. Sorted by join time; removed members are not listed.

Responses

  • 200Members MemberList
  • 401Missing, invalid or revoked key
  • 500Internal error (details are recorded only in server logs)

Add a member

POST/v1/members

Only an owner session can add members (an API key gets 403 session_required, a member gets 403 forbidden). The new member signs in with the Google / GitHub account for this email. Emails are stored in lowercase; an existing member gives 409 member_exists; a role other than owner / member, or a malformed email, gives 400.

Request body application/json · AddMemberRequest

FieldTypeDescription
emailrequiredstring
rolerequiredMemberRole

owner: manages members, API keys and the webhook, plus everything a member can do; member: day-to-day operations.

namestring | null

Responses

  • 201Added Member
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 409State conflict; `error` holds the specific code
  • 415Missing `Content-Type: application/json` (`unsupported_media_type`)
  • 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
  • 500Internal error (details are recorded only in server logs)

Change a member's role

PATCH/v1/members/{id}

Only an owner session can change roles. The last owner cannot be demoted to member (409 last_owner).

Request body application/json

FieldTypeDescription
rolerequiredMemberRole

owner: manages members, API keys and the webhook, plus everything a member can do; member: day-to-day operations.

Responses

  • 200Changed Member
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
  • 409State conflict; `error` holds the specific code
  • 415Missing `Content-Type: application/json` (`unsupported_media_type`)
  • 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
  • 500Internal error (details are recorded only in server logs)

Remove a member

DELETE/v1/members/{id}

Only an owner session that signed in within the last 10 minutes can remove members (otherwise 403 reauth_required). The removed person's console sessions stop working immediately. The last owner cannot be removed (409 last_owner).

Responses

  • 204Removed
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
  • 409State conflict; `error` holds the specific code
  • 500Internal error (details are recorded only in server logs)

List API keys

GET/v1/api-keys

Both sessions and API keys can list keys (including revoked ones); the keys themselves are never returned.

Responses

  • 200API key ApiKeyList
  • 401Missing, invalid or revoked key
  • 500Internal error (details are recorded only in server logs)

Issue an API key

POST/v1/api-keys

Only an owner session that signed in within the last 10 minutes can issue keys (an API key cannot issue new keys: 403 session_required; otherwise 403 reauth_required). key appears only in this response; only its hash is stored. Names are 1–100 characters.

Request body application/json

FieldTypeDescription
namerequiredstring

Responses

  • 201New key (`key` is shown only this once) CreatedApiKey
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 415Missing `Content-Type: application/json` (`unsupported_media_type`)
  • 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
  • 500Internal error (details are recorded only in server logs)

Revoke an API key

DELETE/v1/api-keys/{id}

Takes effect immediately and is idempotent (an already revoked key is returned unchanged). A key can revoke itself (to disable it at once if it leaks); revoking another key requires an owner session that signed in within the last 10 minutes. Returns the revoked record (200).

Responses

  • 200The revoked record ApiKey
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 404Does not exist, or does not belong to this developer (`no such resource`); for a nonexistent route `message` is `no such route`
  • 500Internal error (details are recorded only in server logs)

Get the webhook URL

GET/v1/webhook

Both sessions and API keys can read it. The signing secret is not returned. previous_secret_expires_at is non-null after a secret rotation while the old secret has not yet expired.

Responses

  • 200Webhook settings Webhook
  • 401Missing, invalid or revoked key
  • 500Internal error (details are recorded only in server logs)

Set the webhook URL / rotate the signing secret

PUT/v1/webhook

Only an owner session that signed in within the last 10 minutes can change it. Setting it for the first time, changing the URL, or rotate_secret: true issues a new whsec_ secret (shown only in this response); re-saving the same URL returns secret as null. After a rotation the old secret stays valid for 24 hours, during which every webhook carries two signatures, new and old (Temper-Signature: t=…,v1=<new>,v1=<old>; signature verification in all three SDKs accepts multiple v1 values). The URL must be https:// (http:// is only for local testing), otherwise 400.

Request body application/json · SetWebhookRequest

FieldTypeDescription
urlrequiredstring (uri)
rotate_secretboolean

Responses

  • 200Set SetWebhookResponse
  • 400Invalid parameters: validation failed, the body is not valid JSON, or the query string could not be parsed (all returned in the same JSON shape).
  • 401Missing, invalid or revoked key
  • 403The agent user inside the runtime unit lacks permission (cannot read, write, or create the parent directories)
  • 415Missing `Content-Type: application/json` (`unsupported_media_type`)
  • 422The JSON does not match the schema: a missing field, a wrong type or enum value, or an unknown field (`invalid_body`)
  • 500Internal error (details are recorded only in server logs)