temperDocs
Menu

API reference

Browser

Browser pool: signed-in browser profiles and browser leases.

List profiles

GET/v1/browser/profiles

Deleted profiles are not included.

Parameters

ParameterInTypeDescription
end_user_idquerystring
limitqueryinteger

Items per page, default 50; values outside 1–200 are clamped into that range (no error).

afterquerystring

The previous page's next.

Responses

  • 200A page of profiles BrowserProfileList
  • 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
  • 500Internal error (details are recorded only in server logs)

Create a browser profile

POST/v1/browser/profiles

name must be unique per end user; otherwise 409 profile_exists.

Request body application/json · CreateBrowserProfileRequest

FieldTypeDescription
end_user_idrequiredstring
namerequiredstring

Responses

  • 201Created BrowserProfile
  • 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
  • 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)

Get a profile

GET/v1/browser/profiles/{id}

Responses

  • 200profile BrowserProfile
  • 401Missing, invalid or revoked key
  • 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)

Delete a profile (its signed-in state is deleted too)

DELETE/v1/browser/profiles/{id}

Returns 409 profile_in_use while a pending / active / releasing lease is using it. Deleting an already deleted profile returns 404.

Responses

  • 204Deleted
  • 401Missing, invalid or revoked key
  • 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 leases

GET/v1/browser/leases

Expired leases of this developer are reclaimed before listing.

Parameters

ParameterInTypeDescription
environment_idquerystring
statequeryBrowserLeaseState

The value is not validated.

limitqueryinteger

Items per page, default 50; values outside 1–200 are clamped into that range (no error).

afterquerystring

The previous page's next.

Responses

  • 200A page of leases BrowserLeaseList
  • 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
  • 500Internal error (details are recorded only in server logs)

Request a browser lease

POST/v1/browser/leases

A lease is valid for 15 minutes; renew it before it expires. With profile_id, mode defaults to write (a profile can have only one write lease at a time, otherwise 409 profile_locked) and can also be read; without a profile it can only be clean. The profile must belong to the same end user as the environment, otherwise 400. Exceeding the concurrency limit (GET /v1/browser/limits) returns 429 lease_limit_reached; a destroyed environment returns 409 environment_destroyed; a nonexistent environment or profile returns 404.

Request body application/json · AcquireBrowserLeaseRequest

FieldTypeDescription
environment_idrequiredstring
profile_idstring | null

Omit for a clean browser

modeBrowserLeaseMode | null

With a profile, defaults to write and cannot be clean; without a profile, it can only be clean (or omitted).

Responses

  • 201Lease BrowserLease
  • 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
  • 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`)
  • 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)

Get a lease

GET/v1/browser/leases/{id}

Responses

  • 200Lease BrowserLease
  • 401Missing, invalid or revoked key
  • 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)

Renew a lease (another 15 minutes from now)

POST/v1/browser/leases/{id}/renew

Only an active lease that has not expired can be renewed; anything else (including a releasing lease waiting for its signed-in state to be saved) returns 409 lease_not_active (expired leases have already been reclaimed; request a new one).

Responses

  • 200Lease BrowserLease
  • 401Missing, invalid or revoked key
  • 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)

Release a lease

POST/v1/browser/leases/{id}/release

The request body is optional (if you omit it, do not send Content-Type: application/json, or the empty body gets 400).

Write lease, saving (save omitted or true): the signed-in state is still inside the browser VM and the control plane cannot read it, so the lease first enters releasing and is returned. Through the host session, the control plane asks the browser broker to end the Agent's browser session and to export, encrypt and send back the signed-in state; the lease then settles as released with save_outcome = saved (the profile version increases by 1). If nothing is sent back within 60 seconds (for example, no host is online), the reclaim job settles it as discarded (released, save_outcome = discarded, version unchanged). While releasing, expires_at is the deadline for the save; the lease cannot be renewed and cannot be switched to not saving (save: false returns 409 lease_not_active). To learn the outcome, poll GET /leases/{id}.

save: false, read leases and clean leases go straight to released (for a write lease, save_outcome = discarded). Calling this again on a released lease returns it unchanged, as does calling it again with saving on a releasing lease; a lease reclaimed on expiry returns 409 lease_not_active.

Request body application/json · ReleaseBrowserLeaseRequest

FieldTypeDescription
saveboolean | null

Whether a write lease saves the signed-in state; omitted or null means true. Only meaningful for write leases.

Responses

  • 200Lease BrowserLease
  • 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
  • 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)

Hand the browser over to the user

POST/v1/browser/leases/{id}/takeover

The end user signs in and solves CAPTCHAs on the real page themselves; during this time all of the Agent's browser commands are rejected. The broker is told through the host to lock the Agent's session, and a one-time viewer page URL view_url is returned (valid for 10 minutes, consumed when the viewer connection is established) for the end user to open. Calling this again issues a new URL. The Agent can also request a takeover itself: you receive a browser.takeover_requested webhook (browserTakeoverRequested) and then call this endpoint.

If the lease is not active, 409 lease_not_active; if the environment has not been placed on a host or the host is offline, 503 host_unavailable.

Responses

  • 200Taken over BrowserTakeover
  • 401Missing, invalid or revoked key
  • 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)
  • 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).

Hand the browser back to the Agent

POST/v1/browser/leases/{id}/handback

Ends the takeover and lets the Agent continue; any unused viewer URL is invalidated. The end user clicking "Hand back" on the viewer page has the same effect, so you do not need to call this as well. If not taken over, 409 not_taken_over; if the lease is not active, 409 lease_not_active; if the host is offline, 503 host_unavailable.

Responses

  • 200Lease BrowserLease
  • 401Missing, invalid or revoked key
  • 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)
  • 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).

Viewer page (public, for end users)

GET/v1/browser/view/{token}

Not for developers to call: this is the view_url returned by takeoverBrowserLease. The end user opens it in a browser to see the live screen, click and type, and clicks "Hand back" to finish. No API key is needed; the token in the URL is the credential. Opening the page does not consume the token (refreshing still works); it is consumed when the page establishes the viewer connection (/ws). Responses carry Cache-Control: no-store, Referrer-Policy: no-referrer and a strict CSP. If the token is invalid, expired, already used, or the browser has already been handed back, a 404 HTML page is returned.

Responses

  • 200Viewer page string
  • 404URL expired or already used (HTML)
  • 500Internal error (HTML)

Viewer connection (WebSocket, used by the viewer page itself)

GET/v1/browser/view/{token}/ws

The WebSocket used by the viewer page. Once the token is consumed, it connects through the host to this lease's browser broker and relays JSON text messages in both directions (screen frames, clicks, keystrokes; the format is an internal protocol of the viewer page). The client sending {"done": true} hands the browser back. Invalid, expired or already used token: 404; host offline: 503 host_unavailable.

Responses

  • 101Upgraded to WebSocket
  • 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)
  • 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).

Browser lease concurrency limits and lease duration

GET/v1/browser/limits

The limits are configured by the platform operator; the defaults are 50 per developer and 5 per end user.

Responses

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