Documentation / REST API reference
CLOUDBROWSER DOCUMENTATION

REST API reference

REST endpoints for persistent cloud browsers, connection grants, sharing, usage and billing.

OpenAPI 3.1 for the local backend. Public origins and Go CLI commands are planned; the service is not deployed. Fork requires a paused source; this path has passed local persistence and isolation tests against Sandbox0. Download the source contract →

Base URL & authentication

HTTP
https://cloudbrowser.tv/api/v1
Authorization: Bearer <workspace_api_key>
Content-Type: application/json

Workspace keys authenticate management requests. Browser connection tokens do not authorize REST lifecycle or grant management. Viewer exchange, refresh and logout below use the isolated viewer origin and their own ticket/cookie authorization; never send a workspace key there. Browser access is checked on every request.

Operations

POST/browsers

Create a browser

Reserves a concurrent slot atomically. Returns an operation; connection grants require running status.

GO CLI · PROPOSED
cloudbrowser create --name research --wait

Body schema: CreateBrowser. See schema definitions below.

Success: 202. Complete parameters and response schema ↗

GET/browsers

List browsers

Authenticated, workspace-scoped operation.

GO CLI · PROPOSED
cloudbrowser list --output json

Success: 200. Complete parameters and response schema ↗

GET/browsers/{browserId}

Get a browser

Authenticated, workspace-scoped operation.

GO CLI · PROPOSED
cloudbrowser get br_123

Success: 200. Complete parameters and response schema ↗

DELETE/browsers/{browserId}

Delete a browser

Revoke all grants and stop connections. Deletion is terminal.

GO CLI · PROPOSED
cloudbrowser delete br_123 --yes

Success: 202. Complete parameters and response schema ↗

POST/browsers/{browserId}/pause

Pause a browser

Disconnect transports on pause. Resume checks quota and requires fresh CDP grants or new viewer sessions obtained through existing share URLs. Profile persists; live page memory is not guaranteed. Pause/runtime replacement ends viewer sessions and outstanding tickets and invalidates CDP grants; reusable Live View shares remain configured. After resume, reopen the same share URL for a new runtime-bound session. No implicit resume for viewers. Application pause first asks Chrome to exit gracefully and waits for its supervisor restart to confirm profile flush. If shutdown cannot be confirmed, the operation fails before submitting provider pause. This is distinct from provider TTL expiry.

GO CLI · PROPOSED
cloudbrowser pause br_123 --wait

Success: 202. Complete parameters and response schema ↗

POST/browsers/{browserId}/resume

Resume a browser

Disconnect transports on pause. Resume checks quota and requires fresh CDP grants or new viewer sessions obtained through existing share URLs. Profile persists; live page memory is not guaranteed. Pause/runtime replacement ends viewer sessions and outstanding tickets and invalidates CDP grants; reusable Live View shares remain configured. After resume, reopen the same share URL for a new runtime-bound session. No implicit resume for viewers.

GO CLI · PROPOSED
cloudbrowser resume br_123 --wait

Success: 202. Complete parameters and response schema ↗

POST/browsers/{browserId}/fork

Fork a browser

Create independent browser ID and profile from a consistent snapshot. No access grants are inherited. Snapshot consistency must be qualified before implementation ships. The source must be paused; a running source returns 409 pause_required. Paused-source inheritance and independent writes passed the live test. Never treat a failed operation as a successful child snapshot.

GO CLI · PROPOSED
cloudbrowser fork br_123 --name research-copy --wait

Body schema: ForkBrowser. See schema definitions below.

Success: 202. Complete parameters and response schema ↗

POST/browsers/{browserId}/grants

Create connection access

Create CDP access or a Live View link. Live View defaults to a reusable share URL, read-only permission and no expiration. A short-lived one-time ticket is a separate session-entry credential. Share visits may create multiple independent viewer sessions; CLI exits after returning/opening the URL. Browser must be running when creating/using entry tickets. Draft only.

GO CLI · PROPOSED
cloudbrowser connect br_123 --audience cdp --ttl 1h --output json

Body schema: CreateGrant. See schema definitions below.

Success: 201. Complete parameters and response schema ↗

GET/browsers/{browserId}/grants

List access grants

List metadata only, never bearer URLs, share secrets, refresh cookies or entry tickets. Live View metadata includes permission, expiresAt (null for never), lastOpenedAt, activeSessions and revision. Filter by audience/status; paginate with cursor/limit. Local implementation returns all matching entries with nextCursor=null; pagination is pending.

GO CLI · PROPOSED
cloudbrowser tokens list br_123

Success: 200. Complete parameters and response schema ↗

POST/browsers/{browserId}/grants/{grantId}/renew

Renew a grant lease

CDP ONLY; reject live-view audience with 400 audience_not_supported. Requires workspace authorization, active renewable CDP grant and unchanged runtime. Extend expiresAt to min(now + original TTL, renewUntil), keeping opaque token stable. No hard-stop or privilege expansion. Expired/revoked CDP grants cannot renew. Viewer sessions instead use the viewer refresh endpoint and their own refresh cookie.

GO CLI · PROPOSED
cloudbrowser tokens renew br_123 grant_123

Success: 200. Complete parameters and response schema ↗

DELETE/browsers/{browserId}/grants/{grantId}

Revoke access

Permanently revoke this grant, close its streams, and invalidate all tickets and refresh families. Reusable URL can no longer create sessions. Idempotent; revoked grants cannot be revived. Does not delete the browser.

GO CLI · PROPOSED
cloudbrowser tokens revoke br_123 grant_123 --yes

Success: 200. Complete parameters and response schema ↗

GET/operations/{operationId}

Inspect an operation

Authenticated, workspace-scoped operation.

GO CLI · PROPOSED
cloudbrowser operations get op_123

Success: 200. Complete parameters and response schema ↗

GET/usage

Get current usage

Authenticated, workspace-scoped operation.

GO CLI · PROPOSED
cloudbrowser usage --output json

Success: 200. Complete parameters and response schema ↗

POST/b/{browserId}/session/exchange

Exchange a Live View link

Exchange a short-lived viewer ticket minted through account/library authorization. Atomically consume once, checking recipient account binding, browser, current grant revision, permission and runtime. The viewer never receives the main account cookie or a workspace API key. Reusable sharing acceptance happens on cloudbrowser.tv, not by anonymous viewer redemption. Atomically consume the ticket once before ticketExpiresAt. Check browser, current grant revision and runtime. Link expiresAt is a separate authorization deadline (null means no absolute deadline). Issue a 5-minute access cookie and, for autoRenew=true, a rotating refresh cookie with a 30-minute inactivity deadline, both capped by expiresAt when finite. For autoRenew=false, no refresh cookie and idle/access expiration is 5 minutes capped by expiresAt. Ticket expiry after exchange does not end the session. A reusable share may create multiple recipient sessions; each ticket is single-use. Cookie secrets never appear in JSON. A paused browser cannot exchange tickets and must not be implicitly resumed. Use isolated viewer origin, no-store/no-referrer, strict CSP, same-origin credentials, exact Origin/CSRF checks and redacted logs. Check current link authorization, permission, revision, runtime and issuer access on every request and stream. Never accept a workspace API key here. Local cookies are independently named per viewer session (cb_access_{sessionId}, cb_refresh_{sessionId}) and omit Secure on localhost HTTP. No anonymous account authorization.

VIEWER WEBPAGE · PROPOSED
fetch("/b/br_123/session/exchange", {
  method: "POST",
  credentials: "same-origin",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ ticket }), // received from the account shell via a validated handshake
});
// Runs on https://view.cloudbrowser.tv; cookies are set by the server.
// No CLI process or workspace API key required.

Body schema: ExchangeViewerTicket. See schema definitions below.

Success: 200. Complete parameters and response schema ↗

POST/b/{browserId}/session/refresh

Refresh the viewer session

Use the rotating refresh cookie even if access has expired. No CLI or workspace credential required. Reject ended/revoked sessions, inactive links, changed revisions/runtimes or expired idle deadline. Refresh is allowed indefinitely for actively used links with expiresAt=null. For finite expiresAt, stop all access when the next authorization check observes the deadline, including existing streams. Rotate atomically with reuse detection; serialize refresh across same-browser tabs. Access expiry=min(now+5 minutes, link expiresAt when finite); idle expiry=min(now+30 minutes, finite link deadline). Successful refresh reauthorizes existing same-session streams without page reload. Do not extend the link deadline or widen permissions. After inactivity, reopen the saved browser through account/library authorization to establish a new session. Use isolated viewer origin, no-store/no-referrer, strict CSP, same-origin credentials, exact Origin/CSRF checks and redacted logs. Check current link authorization, permission, revision, runtime and issuer access on every request and stream. Never accept a workspace API key here. Validate the recipient’s active account/membership as well as the owner’s source grant. Removal from the recipient library invalidates that recipient’s sessions only. Local cookies are independently named per viewer session (cb_access_{sessionId}, cb_refresh_{sessionId}) and omit Secure on localhost HTTP. No anonymous account authorization.

VIEWER WEBPAGE · PROPOSED
fetch("/b/br_123/session/refresh", {
  method: "POST",
  credentials: "same-origin",
});
// Runs on https://view.cloudbrowser.tv; cookies are set by the server.
// No CLI process or workspace API key required.

Success: 200. Complete parameters and response schema ↗

POST/b/{browserId}/session/logout

End the viewer session

End only the current viewer session, revoke its refresh family and close streams; clear cookies using the exact browser-specific path. Does not revoke the share URL: the accepted account can reopen its saved browser for a new session. Direct one-time tickets remain consumed. Missing/expired cookies are cleared and return 200. Closing a page alone is not reliable logout. Use isolated viewer origin, no-store/no-referrer, strict CSP, same-origin credentials, exact Origin/CSRF checks and redacted logs. Check current link authorization, permission, revision, runtime and issuer access on every request and stream. Never accept a workspace API key here. Validate the recipient’s active account/membership as well as the owner’s source grant. Removal from the recipient library invalidates that recipient’s sessions only. Local cookies are independently named per viewer session (cb_access_{sessionId}, cb_refresh_{sessionId}) and omit Secure on localhost HTTP. No anonymous account authorization.

VIEWER WEBPAGE · PROPOSED
fetch("/b/br_123/session/logout", {
  method: "POST",
  credentials: "same-origin",
});
// Runs on https://view.cloudbrowser.tv; cookies are set by the server.
// No CLI process or workspace API key required.

Success: 200. Complete parameters and response schema ↗

GET/browsers/{browserId}/grants/{grantId}/sessions

List a link’s authorized viewer sessions

Workspace authorization required. Return metadata only; no cookies, tokens or private page content. Expired/ended sessions are excluded. Local implementation returns all matching entries with nextCursor=null; pagination is pending.

GO CLI · PROPOSED
cloudbrowser links sessions br_123 grant_123

Success: 200. Complete parameters and response schema ↗

DELETE/browsers/{browserId}/grants/{grantId}/sessions

End all sessions for a Live View link

Workspace authorization required. Invalidate all current sessions, refresh families and outstanding entry tickets; close streams. The reusable share URL stays valid for future visits. Use revokeGrant to prevent future visits too. Does not operate on CDP.

GO CLI · PROPOSED
cloudbrowser links end-sessions br_123 grant_123 --yes

Success: 200. Complete parameters and response schema ↗

GET/library/browsers

List my owned and shared browsers

Signed-in account only. Owned and shared entries appear in one grid. A shared entry does not transfer ownership, create a browser, consume the recipient’s browser concurrency, or grant lifecycle/reshare/CDP rights. Every preview subscription rechecks current authorization. Unavailable entries may remain visible without streaming private contents. Compute remains on the owning workspace. Local implementation returns all matching entries with nextCursor=null; pagination is pending.

GO CLI · PROPOSED
cloudbrowser library list --source all --output json

Success: 200. Complete parameters and response schema ↗

POST/library/shares/accept

Accept a shared browser into my account

Requires signed-in account and a valid invitation. Reusable share links can be accepted by multiple accounts. Direct one-time invitations atomically bind to the first accepting account; subsequent redemption receives 409, including by the same account; use the saved library entry instead. Validate link expiration, revocation, revision and owner authority before accepting. Save an account-to-browser access reference, not ownership or a raw bearer token. Deduplicate by account/browser and retain a specific authorized source grant; never silently widen rights. Existing owner entries remain owned. Accepted members can later request fresh viewer tickets without replaying the original invite. Entry ticket expiration does not expire accepted membership; parent-link expiration/revocation does. Return the canonical /browsers/{id} URL. A paused browser can be added but must not be resumed automatically.

GO CLI · PROPOSED
cloudbrowser library add --url "$LIVE_VIEW_URL"

Body schema: AcceptSharedBrowser. See schema definitions below.

Success: 200. Complete parameters and response schema ↗

DELETE/library/browsers/{browserId}

Remove a shared browser from my library

Remove only this recipient’s saved access relationship and end that recipient’s viewer sessions. Do not delete/pause the owner’s browser, revoke the public share link or affect other recipients. Reject owned entries; owner deletion uses the lifecycle API. Re-adding requires a valid reusable invite or new invite if one-time access was removed.

GO CLI · PROPOSED
cloudbrowser library remove br_shared --yes

Success: 200. Complete parameters and response schema ↗

POST/library/browsers/{browserId}/viewer-ticket

Open an owned or saved shared browser

Account authorization required. Check ownership or saved membership AND its current parent grant permission, revision, expiration and issuer access; a saved list entry is not authority by itself. Browser must be running to stream; paused view shows an explicitly labeled authorized last frame without implicitly resuming. Mint a short-lived one-use runtime-bound ticket for the isolated viewer origin. The account shell passes only this ticket through a strict origin-checked handshake to the viewer, never its account cookie or workspace API key. Shared control grants no lifecycle, deletion, fork, reshare or CDP rights. Grid and fullscreen use this same authorization path; switching presentation alone does not duplicate runtime sessions.

GO CLI · PROPOSED
cloudbrowser library view br_shared

Success: 201. Complete parameters and response schema ↗

GET/billing/status

Get plan, runtime, estimated overage and billing access

Only the workspace billing owner can modify billing.

GO CLI · PROPOSED
See CLI reference

Success: 200. Complete parameters and response schema ↗

POST/billing/checkout

Start hosted Stripe Checkout for a new subscription

Only the workspace billing owner can modify billing. Additional usage is charged separately at period close. Monthly amount and extra hourly rate appear in Checkout.

GO CLI · PROPOSED
See CLI reference

Body schema: CheckoutRequest. See schema definitions below.

Success: 200. Complete parameters and response schema ↗

POST/billing/portal

Open payment methods and invoices

Only the workspace billing owner can modify billing.

GO CLI · PROPOSED
See CLI reference

Success: 200. Complete parameters and response schema ↗

POST/billing/refresh

Reconcile Stripe payment and subscription status

Only the workspace billing owner can modify billing.

GO CLI · PROPOSED
See CLI reference

Success: 200. Complete parameters and response schema ↗

POST/billing/upgrade-preview

Preview Basic to Pro proration; valid for five minutes

Only the workspace billing owner can modify billing.

GO CLI · PROPOSED
See CLI reference

Success: 200. Complete parameters and response schema ↗

POST/billing/plan

Upgrade after payment or schedule downgrade/cancel for next period

Only the workspace billing owner can modify billing.

GO CLI · PROPOSED
See CLI reference

Body schema: PlanChangeRequest. See schema definitions below.

Success: 200. Complete parameters and response schema ↗

Request and response schemas

CreateBrowser
JSON SCHEMA
{
  "type": "object",
  "required": [
    "name"
  ],
  "additionalProperties": false,
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 50
    }
  }
}
ForkBrowser
JSON SCHEMA
{
  "type": "object",
  "required": [
    "name"
  ],
  "additionalProperties": false,
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 50
    },
    "startPaused": {
      "type": "boolean",
      "default": true,
      "description": "Paused forks do not reserve running capacity. They retain independent profile writes."
    }
  }
}
CreateGrant
JSON SCHEMA
{
  "oneOf": [
    {
      "$ref": "#/components/schemas/CreateCdpGrant"
    },
    {
      "$ref": "#/components/schemas/CreateLiveViewGrant"
    }
  ],
  "discriminator": {
    "propertyName": "audience",
    "mapping": {
      "cdp": "#/components/schemas/CreateCdpGrant",
      "live-view": "#/components/schemas/CreateLiveViewGrant"
    }
  }
}
CreateCdpGrant
JSON SCHEMA
{
  "type": "object",
  "required": [
    "audience"
  ],
  "additionalProperties": false,
  "properties": {
    "audience": {
      "const": "cdp"
    },
    "permission": {
      "const": "control"
    },
    "ttlSeconds": {
      "type": "integer",
      "minimum": 300,
      "maximum": 86400,
      "default": 3600
    },
    "autoRenew": {
      "type": "boolean",
      "default": false,
      "description": "CDP only. Authenticated CLI/console manager performs renewal; the CDP client cannot refresh itself."
    },
    "renewUntil": {
      "type": "string",
      "format": "date-time",
      "description": "Required for autoRenew; must be at least initial expiry and at most 7 days after issue. Immutable hard stop."
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "autoRenew": {
            "const": true
          }
        },
        "required": [
          "autoRenew"
        ]
      },
      "then": {
        "required": [
          "renewUntil"
        ]
      }
    }
  ]
}
CreateLiveViewGrant
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "audience": {
      "const": "live-view"
    },
    "mode": {
      "type": "string",
      "enum": [
        "share",
        "one-time"
      ],
      "default": "share",
      "description": "share returns a reusable bearer URL. one-time returns a ticket URL redeemable once."
    },
    "permission": {
      "type": "string",
      "enum": [
        "view",
        "control"
      ],
      "default": "view",
      "description": "view is read-only: stream only, no mouse, keyboard, touch, clipboard writes, uploads, navigation commands or browser control. control allows browser interaction but no workspace, lifecycle or CDP administration. Enforced by the gateway, not just UI."
    },
    "expiresAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "default": null,
      "description": "Absolute link authorization deadline, measured from issuance/update; null means no expiration. Applies to new visits AND all existing sessions. Automatic refresh never moves this deadline."
    },
    "ticketTtlSeconds": {
      "type": "integer",
      "minimum": 60,
      "maximum": 900,
      "default": 300,
      "description": "One-time ticket lifetime, independent of the link authorization deadline. Shared links mint fresh tickets on each visit. Direct one-time links mint a ticket at issuance."
    },
    "autoRenew": {
      "type": "boolean",
      "default": true,
      "description": "Viewer webpage refreshes short-lived credentials while link authorization remains valid; no fixed maximum when expiresAt is null. If false, access lasts 5 minutes or until expiresAt, whichever comes first, with no refresh cookie."
    }
  },
  "required": [
    "audience"
  ]
}
UpdateLiveViewGrant
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "permission": {
      "type": "string",
      "enum": [
        "view",
        "control"
      ],
      "default": "view",
      "description": "view is read-only: stream only, no mouse, keyboard, touch, clipboard writes, uploads, navigation commands or browser control. control allows browser interaction but no workspace, lifecycle or CDP administration. Enforced by the gateway, not just UI."
    },
    "expiresAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "default": null,
      "description": "Absolute link authorization deadline, measured from issuance/update; null means no expiration. Applies to new visits AND all existing sessions. Automatic refresh never moves this deadline."
    }
  },
  "required": [],
  "minProperties": 1,
  "description": "Share-mode Live View only. At least one property required. Every effective policy change invalidates all old sessions and tickets immediately and increments revision. The same reusable URL can then open a fresh session. Revoked grants cannot be revived. An expired share may be extended by its owner, but previous sessions stay ended."
}
AcceptSharedBrowser
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "linkId": {
      "type": "string"
    },
    "shareToken": {
      "type": "string"
    },
    "ticket": {
      "type": "string"
    }
  },
  "required": [
    "linkId"
  ],
  "oneOf": [
    {
      "required": [
        "shareToken"
      ],
      "not": {
        "required": [
          "ticket"
        ]
      }
    },
    {
      "required": [
        "ticket"
      ],
      "not": {
        "required": [
          "shareToken"
        ]
      }
    }
  ],
  "description": "Account authorization plus one invitation credential. Token read from URL fragment and removed immediately. Store a server-side pending authorization handle bound to the login transaction when redirecting to sign-in; never put the bearer secret in OAuth state, returnTo, query strings, analytics or localStorage."
}
BrowserLibraryEntry
JSON SCHEMA
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "example": "br_123"
    },
    "name": {
      "type": "string"
    },
    "status": {
      "type": "string",
      "enum": [
        "starting",
        "running",
        "pausing",
        "paused",
        "resuming",
        "failed",
        "deleting",
        "unavailable"
      ]
    },
    "parentId": {
      "type": [
        "string",
        "null"
      ]
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time"
    },
    "error": {
      "type": [
        "string",
        "null"
      ]
    },
    "runtimeGeneration": {
      "type": "integer"
    },
    "owner": {
      "type": "boolean"
    },
    "permission": {
      "type": "string",
      "enum": [
        "view",
        "control"
      ]
    },
    "ownerName": {
      "type": "string"
    },
    "shared": {
      "type": "boolean",
      "description": "Owned browser has at least one currently active sharing grant."
    }
  },
  "required": [
    "id",
    "name",
    "status",
    "owner",
    "permission",
    "runtimeGeneration"
  ]
}
ViewerTicket
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "ticket": {
      "type": "string",
      "description": "One-time secret minted after account/library authorization, bound to recipient account, browser, grant revision, permission and runtime. Return only on ticket issuance."
    },
    "ticketExpiresAt": {
      "type": "string",
      "format": "date-time"
    },
    "url": {
      "type": "string",
      "description": "Isolated viewer URL carrying a single-use ticket in its fragment. The viewer clears the fragment before exchange."
    }
  },
  "required": [
    "ticket",
    "ticketExpiresAt",
    "url"
  ]
}
ExchangeViewerTicket
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "ticket"
  ],
  "properties": {
    "ticket": {
      "type": "string",
      "description": "Single-use opaque secret from the URL fragment. Never log it."
    }
  }
}
GrantIssue
JSON SCHEMA
{
  "oneOf": [
    {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "grant",
        "cdpUrl"
      ],
      "properties": {
        "grant": {
          "$ref": "#/components/schemas/CdpGrant"
        },
        "cdpUrl": {
          "type": "string",
          "description": "Secret returned only on issuance."
        }
      }
    },
    {
      "type": "object",
      "required": [
        "grant",
        "liveViewUrl"
      ],
      "properties": {
        "grant": {
          "$ref": "#/components/schemas/LiveViewGrant"
        },
        "liveViewUrl": {
          "type": "string",
          "description": "Public account-shell entry URL, returned only at issuance: https://cloudbrowser.tv/view/{grantId}#share=... (reusable) or #ticket=... (one-time invitation). Sign in and accept into your library, then open /browsers/{browserId} fullscreen in the same workspace. Viewer transport remains isolated at view.cloudbrowser.tv. Raw secrets never appear in listings."
        }
      }
    }
  ]
}
LiveViewGrant
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    },
    "browserId": {
      "type": "string"
    },
    "audience": {
      "const": "live-view"
    },
    "mode": {
      "type": "string",
      "enum": [
        "share",
        "one-time"
      ]
    },
    "permission": {
      "type": "string",
      "enum": [
        "view",
        "control"
      ],
      "default": "view",
      "description": "view is read-only: stream only, no mouse, keyboard, touch, clipboard writes, uploads, navigation commands or browser control. control allows browser interaction but no workspace, lifecycle or CDP administration. Enforced by the gateway, not just UI."
    },
    "expiresAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "default": null,
      "description": "Absolute link authorization deadline, measured from issuance/update; null means no expiration. Applies to new visits AND all existing sessions. Automatic refresh never moves this deadline."
    },
    "ticketTtlSeconds": {
      "type": "integer"
    },
    "entryExpiresAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "Direct one-time URL only; null for reusable shares."
    },
    "autoRenew": {
      "type": "boolean"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "lastOpenedAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "activeSessions": {
      "type": "integer",
      "minimum": 0,
      "description": "Current authorized viewer sessions, not connected socket count."
    },
    "revision": {
      "type": "integer",
      "minimum": 1
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "expired",
        "revoked",
        "used"
      ]
    },
    "revoked": {
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "browserId",
    "audience",
    "mode",
    "permission",
    "expiresAt",
    "ticketTtlSeconds",
    "entryExpiresAt",
    "autoRenew",
    "createdAt",
    "lastOpenedAt",
    "activeSessions",
    "revision",
    "status",
    "revoked"
  ]
}
ViewerSession
JSON SCHEMA
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "grantId",
    "browserId",
    "permission",
    "autoRenew",
    "accessExpiresAt",
    "idleExpiresAt",
    "ended",
    "authorizationExpiresAt",
    "accountId"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "grantId": {
      "type": "string"
    },
    "browserId": {
      "type": "string"
    },
    "permission": {
      "type": "string",
      "enum": [
        "view",
        "control"
      ],
      "default": "view",
      "description": "view is read-only: stream only, no mouse, keyboard, touch, clipboard writes, uploads, navigation commands or browser control. control allows browser interaction but no workspace, lifecycle or CDP administration. Enforced by the gateway, not just UI."
    },
    "autoRenew": {
      "type": "boolean"
    },
    "accessExpiresAt": {
      "type": "string",
      "format": "date-time"
    },
    "idleExpiresAt": {
      "type": "string",
      "format": "date-time"
    },
    "ended": {
      "type": "boolean"
    },
    "authorizationExpiresAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "default": null,
      "description": "Absolute link authorization deadline, measured from issuance/update; null means no expiration. Applies to new visits AND all existing sessions. Automatic refresh never moves this deadline."
    },
    "accountId": {
      "type": "string",
      "description": "Recipient account binding; never infer identity from browserId alone."
    }
  }
}

Errors, pagination and retries

Errors return code, message and requestId. Lists accept an opaque cursor and limit (1–100), and return items and nextCursor.

StatusMeaning
400Invalid parameters or token policy.
401 / 403Missing credentials or insufficient access.
404Resource not found or not visible to this caller.
409Lifecycle conflict, expired/revoked grant, idempotency conflict.
410Viewer entry ticket is expired, invalid or already consumed.
429Concurrency or rate limit; include Retry-After when applicable.
503Runtime temporarily unavailable.

Create and fork require Idempotency-Key. Retry with the original key and identical payload after an uncertain response. Never infer that a timeout means no resource was created.

Private preview · REST API · CLI designExplore console