{"openapi":"3.0.3","info":{"title":"The Browser Farm","version":"0.1.0","description":"Browserbase-compatible subset this gateway implements. Routes and fields not listed here are not implemented. Human guide: https://www.thebrowserfarm.com/docs"},"servers":[{"url":"https://api.thebrowserfarm.com"}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-BB-API-Key","description":"Account API key. If both are sent, `X-BB-API-Key` wins, including when that header is empty."},"Bearer":{"type":"http","scheme":"bearer","description":"The same API key. Ignored when X-BB-API-Key is also sent."}},"schemas":{"Error":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"Session":{"type":"object","required":["id","createdAt","updatedAt","startedAt","endedAt","projectId","status","keepAlive","region","connectUrl","seleniumRemoteUrl","signingKey","userMetadata"],"properties":{"id":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"projectId":{"type":"string","description":"Echoed from the request, or \"default\". There is no project store."},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","ERROR","TIMED_OUT"]},"keepAlive":{"type":"boolean","description":"From the create body, default false. Closing CDP ends the session unless it was created with `keepAlive: true`. When the last CDP connection closes (Playwright or Puppeteer `browser.close()`, or a dropped or failed connection) the status becomes `COMPLETED` and the next connect is `404`. With `keepAlive: true` the session stays `RUNNING` after a disconnect and the same `connectUrl` accepts another client until you release it or it idles out. A CDP `Browser.close` command, which is what Puppeteer's `browser.close()` sends, ends the session either way."},"region":{"type":"string","enum":["us-west-2"],"description":"Always us-west-2. Not a placement choice; a requested region is ignored."},"connectUrl":{"type":"string","description":"`connectUrl` is `wss://<api host>/<id>/cdp?signingKey=<bfsk_… token>`. Pass it through unchanged to Playwright `connectOverCDP` or Puppeteer `connect`. The path id is not a credential. The handshake requires that `signingKey`, or the owning customer's API key in the `X-BB-API-Key` header (not as a query parameter). A presented `signingKey` that does not match does not fall through to the API key. A live session with no valid credential is `401` (plain text). To revoke a leaked connectUrl, release the session.","example":"wss://api.thebrowserfarm.com/00000000-0000-4000-8000-000000000000/cdp?signingKey=bfsk_example"},"seleniumRemoteUrl":{"type":"string","nullable":true,"description":"Always null."},"signingKey":{"type":"string","description":"`signingKey` is a per-session `bfsk_…` token, the same value as the `signingKey` query on `connectUrl`, valid for 24 hours from issue; `GET` the session for a fresh `connectUrl`. To revoke a leaked `connectUrl`, release the session: the key is stateless until it expires. It is not a Selenium secret.","example":"bfsk_example"},"userMetadata":{"type":"object","additionalProperties":true}}}}},"paths":{"/v1/sessions":{"post":{"operationId":"createSession","summary":"Create a session","security":[{"ApiKey":[]},{"Bearer":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","description":"Empty object is valid. projectId is echoed (default \"default\"). userMetadata is echoed. browserSettings.viewport {width,height} and fingerprint.devices including \"mobile\" are applied. keepAlive (default false) selects whether closing the last CDP connection ends the session. `isolation`: `\"context\"` (the default) or `\"vm\"`. Anything else is `400`. `context` is a browser context in a shared Chromium. `vm` is a Firecracker microVM of its own, on the dev tier only; that pool is small, so when it is full create returns `503` with `Retry-After`. The production API currently serves `context` only: `vm` is accepted there and runs as a `context` session. Ignored, not errors: `proxies`, `region`, `timeout`, `api_timeout`, `browserSettings.blockAds`, `solveCaptchas`, `recordSession`, `contextId`, `extensionId`.","additionalProperties":true}}}},"responses":{"201":{"description":"Session created","content":{"application/json":{"schema":{"type":"object","required":["id","createdAt","updatedAt","startedAt","endedAt","projectId","status","keepAlive","region","connectUrl","seleniumRemoteUrl","signingKey","userMetadata"],"properties":{"id":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"projectId":{"type":"string","description":"Echoed from the request, or \"default\". There is no project store."},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","ERROR","TIMED_OUT"]},"keepAlive":{"type":"boolean","description":"From the create body, default false. Closing CDP ends the session unless it was created with `keepAlive: true`. When the last CDP connection closes (Playwright or Puppeteer `browser.close()`, or a dropped or failed connection) the status becomes `COMPLETED` and the next connect is `404`. With `keepAlive: true` the session stays `RUNNING` after a disconnect and the same `connectUrl` accepts another client until you release it or it idles out. A CDP `Browser.close` command, which is what Puppeteer's `browser.close()` sends, ends the session either way."},"region":{"type":"string","enum":["us-west-2"],"description":"Always us-west-2. Not a placement choice; a requested region is ignored."},"connectUrl":{"type":"string","description":"`connectUrl` is `wss://<api host>/<id>/cdp?signingKey=<bfsk_… token>`. Pass it through unchanged to Playwright `connectOverCDP` or Puppeteer `connect`. The path id is not a credential. The handshake requires that `signingKey`, or the owning customer's API key in the `X-BB-API-Key` header (not as a query parameter). A presented `signingKey` that does not match does not fall through to the API key. A live session with no valid credential is `401` (plain text). To revoke a leaked connectUrl, release the session.","example":"wss://api.thebrowserfarm.com/00000000-0000-4000-8000-000000000000/cdp?signingKey=bfsk_example"},"seleniumRemoteUrl":{"type":"string","nullable":true,"description":"Always null."},"signingKey":{"type":"string","description":"`signingKey` is a per-session `bfsk_…` token, the same value as the `signingKey` query on `connectUrl`, valid for 24 hours from issue; `GET` the session for a fresh `connectUrl`. To revoke a leaked `connectUrl`, release the session: the key is stateless until it expires. It is not a Selenium secret.","example":"bfsk_example"},"userMetadata":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid JSON, or isolation is not context or vm","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"invalid JSON body"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"missing API key: send X-BB-API-Key or Authorization: Bearer <key>"}}}},"403":{"description":"Revoked key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"API key has been revoked"}}}},"429":{"description":"Account is at its concurrent-session cap. Header Retry-After: 5. No other rate limit.","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"concurrency limit reached: N of M sessions running. Release a session (or wait for one to idle out) and retry."}}},"headers":{"Retry-After":{"schema":{"type":"integer","example":5}}}},"502":{"description":"Browser allocation failed","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"failed to allocate a browser session"}}}},"503":{"description":"No browser capacity, including a full vm pool on the dev tier. Header Retry-After (seconds; 5 when the host does not name one)","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"no browser capacity available right now; retry shortly"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}},"get":{"operationId":"listSessions","summary":"List this account's in-memory sessions","description":"JSON array, not an envelope. Omitting status returns every status. ?q= is ignored. This list is the gateway process's memory, not a durable archive. On the public API a restart drops it, including running sessions. A terminal session may still include `connectUrl`; reconnecting returns `404` `unknown or released session` (plain text, not JSON).","security":[{"ApiKey":[]},{"Bearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","ERROR","TIMED_OUT"]}}],"responses":{"200":{"description":"Sessions","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","required":["id","createdAt","updatedAt","startedAt","endedAt","projectId","status","keepAlive","region","connectUrl","seleniumRemoteUrl","signingKey","userMetadata"],"properties":{"id":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"projectId":{"type":"string","description":"Echoed from the request, or \"default\". There is no project store."},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","ERROR","TIMED_OUT"]},"keepAlive":{"type":"boolean","description":"From the create body, default false. Closing CDP ends the session unless it was created with `keepAlive: true`. When the last CDP connection closes (Playwright or Puppeteer `browser.close()`, or a dropped or failed connection) the status becomes `COMPLETED` and the next connect is `404`. With `keepAlive: true` the session stays `RUNNING` after a disconnect and the same `connectUrl` accepts another client until you release it or it idles out. A CDP `Browser.close` command, which is what Puppeteer's `browser.close()` sends, ends the session either way."},"region":{"type":"string","enum":["us-west-2"],"description":"Always us-west-2. Not a placement choice; a requested region is ignored."},"connectUrl":{"type":"string","description":"`connectUrl` is `wss://<api host>/<id>/cdp?signingKey=<bfsk_… token>`. Pass it through unchanged to Playwright `connectOverCDP` or Puppeteer `connect`. The path id is not a credential. The handshake requires that `signingKey`, or the owning customer's API key in the `X-BB-API-Key` header (not as a query parameter). A presented `signingKey` that does not match does not fall through to the API key. A live session with no valid credential is `401` (plain text). To revoke a leaked connectUrl, release the session.","example":"wss://api.thebrowserfarm.com/00000000-0000-4000-8000-000000000000/cdp?signingKey=bfsk_example"},"seleniumRemoteUrl":{"type":"string","nullable":true,"description":"Always null."},"signingKey":{"type":"string","description":"`signingKey` is a per-session `bfsk_…` token, the same value as the `signingKey` query on `connectUrl`, valid for 24 hours from issue; `GET` the session for a fresh `connectUrl`. To revoke a leaked `connectUrl`, release the session: the key is stateless until it expires. It is not a Selenium secret.","example":"bfsk_example"},"userMetadata":{"type":"object","additionalProperties":true}}}}}}},"400":{"description":"Unknown status filter","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"invalid status \"NOPE\": expected one of PENDING, RUNNING, COMPLETED, ERROR, TIMED_OUT"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"missing API key: send X-BB-API-Key or Authorization: Bearer <key>"}}}},"403":{"description":"Revoked key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"API key has been revoked"}}}}}}},"/v1/sessions/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getSession","summary":"Get one session","security":[{"ApiKey":[]},{"Bearer":[]}],"responses":{"200":{"description":"Session. connectUrl may still be present after it ends; dialing it fails.","content":{"application/json":{"schema":{"type":"object","required":["id","createdAt","updatedAt","startedAt","endedAt","projectId","status","keepAlive","region","connectUrl","seleniumRemoteUrl","signingKey","userMetadata"],"properties":{"id":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"projectId":{"type":"string","description":"Echoed from the request, or \"default\". There is no project store."},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","ERROR","TIMED_OUT"]},"keepAlive":{"type":"boolean","description":"From the create body, default false. Closing CDP ends the session unless it was created with `keepAlive: true`. When the last CDP connection closes (Playwright or Puppeteer `browser.close()`, or a dropped or failed connection) the status becomes `COMPLETED` and the next connect is `404`. With `keepAlive: true` the session stays `RUNNING` after a disconnect and the same `connectUrl` accepts another client until you release it or it idles out. A CDP `Browser.close` command, which is what Puppeteer's `browser.close()` sends, ends the session either way."},"region":{"type":"string","enum":["us-west-2"],"description":"Always us-west-2. Not a placement choice; a requested region is ignored."},"connectUrl":{"type":"string","description":"`connectUrl` is `wss://<api host>/<id>/cdp?signingKey=<bfsk_… token>`. Pass it through unchanged to Playwright `connectOverCDP` or Puppeteer `connect`. The path id is not a credential. The handshake requires that `signingKey`, or the owning customer's API key in the `X-BB-API-Key` header (not as a query parameter). A presented `signingKey` that does not match does not fall through to the API key. A live session with no valid credential is `401` (plain text). To revoke a leaked connectUrl, release the session.","example":"wss://api.thebrowserfarm.com/00000000-0000-4000-8000-000000000000/cdp?signingKey=bfsk_example"},"seleniumRemoteUrl":{"type":"string","nullable":true,"description":"Always null."},"signingKey":{"type":"string","description":"`signingKey` is a per-session `bfsk_…` token, the same value as the `signingKey` query on `connectUrl`, valid for 24 hours from issue; `GET` the session for a fresh `connectUrl`. To revoke a leaked `connectUrl`, release the session: the key is stateless until it expires. It is not a Selenium secret.","example":"bfsk_example"},"userMetadata":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"missing API key: send X-BB-API-Key or Authorization: Bearer <key>"}}}},"403":{"description":"Revoked key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"API key has been revoked"}}}},"404":{"description":"No such session for this account, including a malformed id (someone else's session looks the same)","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"session not found"}}}}}},"post":{"operationId":"releaseSession","summary":"Release a session","description":"`POST /v1/sessions/<id>` with `{\"status\":\"REQUEST_RELEASE\"}` ends the session. The response is `200` and the session object with status `COMPLETED`. Live CDP sockets are closed. Releasing again is `200` and does not double-destroy. Any other status is `400`. Closing CDP ends the session unless it was created with `keepAlive: true`. When the last CDP connection closes (Playwright or Puppeteer `browser.close()`, or a dropped or failed connection) the status becomes `COMPLETED` and the next connect is `404`. With `keepAlive: true` the session stays `RUNNING` after a disconnect and the same `connectUrl` accepts another client until you release it or it idles out. A CDP `Browser.close` command, which is what Puppeteer's `browser.close()` sends, ends the session either way.","security":[{"ApiKey":[]},{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["REQUEST_RELEASE"]}}}}}},"responses":{"200":{"description":"Session, status COMPLETED when it was running","content":{"application/json":{"schema":{"type":"object","required":["id","createdAt","updatedAt","startedAt","endedAt","projectId","status","keepAlive","region","connectUrl","seleniumRemoteUrl","signingKey","userMetadata"],"properties":{"id":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time","nullable":true},"projectId":{"type":"string","description":"Echoed from the request, or \"default\". There is no project store."},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","ERROR","TIMED_OUT"]},"keepAlive":{"type":"boolean","description":"From the create body, default false. Closing CDP ends the session unless it was created with `keepAlive: true`. When the last CDP connection closes (Playwright or Puppeteer `browser.close()`, or a dropped or failed connection) the status becomes `COMPLETED` and the next connect is `404`. With `keepAlive: true` the session stays `RUNNING` after a disconnect and the same `connectUrl` accepts another client until you release it or it idles out. A CDP `Browser.close` command, which is what Puppeteer's `browser.close()` sends, ends the session either way."},"region":{"type":"string","enum":["us-west-2"],"description":"Always us-west-2. Not a placement choice; a requested region is ignored."},"connectUrl":{"type":"string","description":"`connectUrl` is `wss://<api host>/<id>/cdp?signingKey=<bfsk_… token>`. Pass it through unchanged to Playwright `connectOverCDP` or Puppeteer `connect`. The path id is not a credential. The handshake requires that `signingKey`, or the owning customer's API key in the `X-BB-API-Key` header (not as a query parameter). A presented `signingKey` that does not match does not fall through to the API key. A live session with no valid credential is `401` (plain text). To revoke a leaked connectUrl, release the session.","example":"wss://api.thebrowserfarm.com/00000000-0000-4000-8000-000000000000/cdp?signingKey=bfsk_example"},"seleniumRemoteUrl":{"type":"string","nullable":true,"description":"Always null."},"signingKey":{"type":"string","description":"`signingKey` is a per-session `bfsk_…` token, the same value as the `signingKey` query on `connectUrl`, valid for 24 hours from issue; `GET` the session for a fresh `connectUrl`. To revoke a leaked `connectUrl`, release the session: the key is stateless until it expires. It is not a Selenium secret.","example":"bfsk_example"},"userMetadata":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Update status is not REQUEST_RELEASE","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"unsupported update: only { \"status\": \"REQUEST_RELEASE\" } is implemented in Phase 0a"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"missing API key: send X-BB-API-Key or Authorization: Bearer <key>"}}}},"403":{"description":"Revoked key","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"API key has been revoked"}}}},"404":{"description":"No such session","content":{"application/json":{"schema":{"type":"object","required":["message"],"additionalProperties":false,"properties":{"message":{"type":"string"}}},"example":{"message":"session not found"}}}}}}},"/healthz":{"get":{"operationId":"healthz","summary":"Unauthenticated health","description":"`GET /healthz` and `GET /api/health` need no API key. Both return HTTP 200, including when the browser backend is down. The body's `status` is `\"ok\"` or `\"degraded\"`, `service` is `\"gateway\"`, and `sessions` counts live and total sessions. `environment` is the process `NODE_ENV`, not which site you called.","security":[],"responses":{"200":{"description":"Health snapshot","content":{"application/json":{"schema":{"type":"object","required":["status","service"],"properties":{"status":{"type":"string","enum":["ok","degraded"]},"service":{"type":"string","enum":["gateway"]},"environment":{"type":"string"},"sessions":{"type":"object","properties":{"live":{"type":"integer"},"total":{"type":"integer"}}}}}}}}}}},"/api/health":{"get":{"operationId":"apiHealth","summary":"Same body as GET /healthz","security":[],"responses":{"200":{"description":"Health snapshot"}}}}}}