temperDocs
Menu

API reference

Temper Control Plane API

Version 0.5.0. Generated from the OpenAPI spec, which you can download and import into your tools.

Official client libraries are available for TypeScript, Python and Go; see the quickstart for a step-by-step walkthrough.

Authentication

Every /v1 endpoint requires Authorization: Bearer temper_sk_... (an API key, issued on the console's Team page or with POST /v1/api-keys; your first key is provided when your developer account is created; only a hash of each key is stored), or a console session token temper_cs_... (see the team tag). Member management, issuing API keys and changing the webhook accept only a session; issuing keys, changing the webhook and removing members also require that you signed in within the last 10 minutes (403 session_required / reauth_required). Each developer can see and act on only their own resources: other developers' resources are treated as nonexistent (404). Authentication happens before the request body is parsed, so a request without a key gets 401 whether or not its body is valid.

Errors

Every error response is JSON: {"error": "<machine-readable code>", "message": "<human-readable explanation>"}; see Error for the codes. Requests rejected before they reach the endpoint's own logic are returned in the same shape, with these status codes:

  • 415 unsupported_media_type: an endpoint that takes a JSON body was called without Content-Type: application/json;
  • 400 bad_request: the body is not valid JSON, or the query string could not be parsed (including unknown query parameters);
  • 422 invalid_body: the JSON is valid but does not match the schema: a required field is missing, a type or enum value is wrong, or there is an unknown field (unknown fields in a JSON body are always rejected);
  • 404 not_found: no such route (message is no such route; a missing resource gives no such resource);
  • 405 method_not_allowed: the route exists but does not support this method (the Allow header is preserved);
  • 413 payload_too_large: the request body exceeds the size limit.

Errors returned by proxies or gateways in front of the API may not be JSON; when the SDKs receive a non-JSON error response they record the code as http_<status> and use the response body as the message.

Pagination

List endpoints return {"data": [...], "next": <id or null>} in ascending order of creation time; pass next back as after to get the next page. next is non-null only when the page is exactly full (its item count equals limit), so you may fetch one extra empty page at the end. If after is an id that does not exist (or belongs to someone else), the result is an empty list, not an error.

State

An environment's desired state (desired_state) is changed through the API; its actual state (state) is reported back by the host daemon after it applies the change. While no host is online, a new environment stays pending. State transitions are idempotent: calling one again when the environment is already in the target state also succeeds.

Execution and files

/v1/environments/{id}/exec, /files and /processes reach the environment's VM over the host channel. Processes run inside the runtime unit as the agent user, with the same permissions as the Agent. If the environment is not running it is woken first (its desired state is set back to running), and the call waits up to 90 seconds for it to actually be running and placed on a host; every call counts as activity. As a result:

  • an environment whose desired state is destroyed gives 404; one whose actual state is failed gives 409 environment_failed;
  • if it cannot be placed on a host within 15 seconds (no host online, not enough capacity) you get 503 environment_not_placed; if it is placed but not running within 90 seconds, 503 environment_not_running;
  • if the host is offline or the host channel times out, 503 host_unavailable; if the VM cannot be reached (mid-suspend, or while the VM is being replaced), 503 guest_unavailable.

Request parameters (argv / command, timeout_secs, path) are validated before the environment is woken, so invalid parameters get an immediate 400.

Connections and approvals

  • Connections (per-user OAuth): your backend calls POST /v1/connections/authorize to get an authorization link; after the end user consents at the provider, they are redirected through the public /v1/oauth/{provider}/callback back to your return_url. Tokens are never included in any response.
  • Policies and approvals: a policy decides whether each kind of action is allowed, denied or needs approval; when approval is needed, an approval.requested webhook is sent, and your backend either calls the signed decision_url or calls decideApproval with an API key (this is what the console does).
  • Time-limited grants are spelled inconsistently (for compatibility with the earlier developer-backend protocol): in a decision request it is {"kind": "until", "until": <unix seconds>}, while in max_scope and in the scope of approvals and grants it is called time_limited.

Not yet available

  • Terminal (TTY) sessions, registering background services (to be preserved across VM replacement), and resumable uploads for large files;
  • Billing (usage-based charges) has no endpoints yet; only usage and limits are available.

Download openapi.yaml