api reference.

Three endpoints. JSON in, JSON out, and a CDP websocket where the browser lives. Everything below works with curl.

# basics
base url   https://api.guise.sh
auth       x-api-key: <key>          (get one at guise.sh/keys)
content    application/json
────────────────────────────────────────────────────────────────

POST/v1/sessions

Create a browser. One session is one browser — warm, wired to its egress, handed over as a CDP websocket. ~150ms end to end.

# request
curl -s -X POST https://api.guise.sh/v1/sessions \
  -H "x-api-key: $GUISE_KEY" \
  -d '{"ttlSec":1800}'
# response — 201
{
  "id": "s_01J9K7Q8ZV3M",
  "connectUrl": "wss://api.guise.sh/v1/sessions/s_01J9K7Q8ZV3M/cdp?token=…",
  "proxy": "residential",
  "ttlSec": 1800,
  "createdAt": "2026-08-16T20:31:04Z"
}

GET/v1/sessions

List your live sessions.

# response — 200
{ "sessions": [ { "id": "s_01J9K7Q8ZV3M", "proxy": "residential",
                   "secondsLeft": 1341, "createdAt": "…" } ] }

GET/v1/sessions/:id

Status of one session: connectUrl, tier, and time left before the TTL reaper takes it.

DELETE/v1/sessions/:id

Kill it now. The browser is destroyed — disk and all — never recycled. Returns 204.

────────────────────────────────────────────────────────────────

## connect

connectUrl is a plain CDP websocket. Anything that speaks CDP works — no SDK, no wrapper.

# playwright (node)
const b = await chromium.connectOverCDP(session.connectUrl);
const page = await b.contexts()[0].newPage();
await page.goto("https://example.com");
# puppeteer
const b = await puppeteer.connect({ browserWSEndpoint: session.connectUrl });
const page = await b.newPage();
# playwright (python)
b = playwright.chromium.connect_over_cdp(session["connectUrl"])
page = b.contexts[0].new_page()
────────────────────────────────────────────────────────────────

## proxy tiers

────────────────────────────────────────────────────────────────

## errors