Sessions
What a session is, the options you can create it with and how it is billed.
A session is one isolated cloud machine. It runs in its own gVisor sandbox and is never shared with another customer. Inside, it can have:
- a Chrome browser you control over the Chrome DevTools Protocol (see Browser);
- a bash shell with Python, Node and ffmpeg built in (see Shell);
- the shared /workspace disk, used by both (see Files).
A session needs a browser, a shell, or both. Sessions start from a warm pool of ready machines; our target is under one second from request to a running session.
Create a session
POST/v1/sessions
curl -X POST https://api.staging.boxline.dev/v1/sessions \
-H "x-api-key: $BOXLINE_API_KEY" \
-H "content-type: application/json" \
-d '{
"browser": true,
"shell": true,
"timeout": 900
}'Body parameters
| Field | Default | Description |
|---|---|---|
browser | true | Start Chrome in the session. |
shell | false | Add a bash shell. |
timeout | 300 | Maximum lifetime in seconds. At least 60; the maximum depends on your plan (see plan limits). |
keepAlive | false | Keep a browser-only session running after its last CDP client disconnects. See lifetime. |
viewport | none | { width, height } of the browser window, from 200×200 to 3840×2160. |
userMetadata | {} | Any JSON object; returned on the session. |
context | none | { id, persist }: start with a saved context; with persist: true, save the browser state back to it when the session ends. |
The session object
Every session endpoint returns this object (201 on create):
{
"id": "3f6c2a9e-8b1d-4c7a-9e2f-5d0b7a1c4e88",
"status": "RUNNING",
"projectId": "…",
"region": "…",
"browser": true,
"shell": false,
"keepAlive": false,
"timeout": 300,
"createdAt": "2026-09-28T12:00:00.000Z",
"startedAt": "2026-09-28T12:00:00.000Z",
"endedAt": null,
"expiresAt": "2026-09-28T12:05:00.000Z",
"endReason": null,
"connectUrl": "wss://…/v1/connect?sessionId=3f6c2a9e-8b1d-4c7a-9e2f-5d0b7a1c4e88&token=…",
"liveUrl": "https://…/live/3f6c2a9e-8b1d-4c7a-9e2f-5d0b7a1c4e88?token=…",
"terminalUrl": null,
"workspacePath": "/workspace",
"contextId": null,
"userMetadata": {},
"moves": 0,
"error": null,
"usage": { "seconds": 0, "costUsd": 0 }
}| Field | Description |
|---|---|
id | Session ID (a UUID), used in every other session endpoint. |
status | "RUNNING", "PAUSED", "COMPLETED" or "ERROR". |
browser, shell | What the session was created with. |
keepAlive, timeout | Lifetime settings (see below). timeout is in seconds. |
createdAt, startedAt, endedAt | ISO timestamps. endedAt is null until the session ends. |
expiresAt | When the session will end by reaching its timeout. |
endReason | Why it ended: released, timeout, disconnected, agent_finished, api_restart or paused_expired. null until it ends. |
connectUrl | Signed Chrome DevTools Protocol WebSocket URL for Playwright or Puppeteer. null without a browser. |
liveUrl | Signed URL of the live view page. Open it, or embed it in an iframe. |
terminalUrl | Signed WebSocket URL of the interactive terminal. null without a shell. |
workspacePath | The shared disk, "/workspace". |
contextId | The context the session was started with, or null. |
userMetadata | The object you passed at creation. |
moves | How many times the session has been moved. |
error | Error message when status is ERROR, otherwise null. |
usage | { seconds, costUsd }: billed running time and its cost so far. |
The signed URLs expire. For fresh liveUrl and terminalUrl values, call GET /v1/sessions/:id/live.
How long a session lives
- Every session ends when it reaches its
timeout(endReason: "timeout"), unless you release or pause it first. - A browser-only session without
keepAliveends about 5 seconds after its last CDP client disconnects ("disconnected"). The short grace period lets a client reconnect. SetkeepAlive: trueto keep it running between connections. - A session with a shell keeps running until you release it or it times out, whether or not a browser client is connected.
Get and list sessions
GET/v1/sessions/:id
curl https://api.staging.boxline.dev/v1/sessions/$SESSION_ID \
-H "x-api-key: $BOXLINE_API_KEY"GET/v1/sessions?status=&limit= returns { data: [Session] }, optionally filtered by status.
Release a session
POST/v1/sessions/:id/release or DELETE /v1/sessions/:id
Ends the session and returns it with status COMPLETED. Billing stops at that second. If the session uses a context with persist: true, its browser state is saved first.
curl -X POST https://api.staging.boxline.dev/v1/sessions/$SESSION_ID/release \
-H "x-api-key: $BOXLINE_API_KEY"Plan limits
Your plan sets how many sessions can run at once and the largest timeout you can ask for. Creating (or resuming) a session beyond your concurrency returns 429 concurrency_limit; a timeout above your plan’s maximum returns 403 plan_limit.
| Plan | Running sessions | Max timeout |
|---|---|---|
| Free | 3 | 900 seconds |
| Hobby | 25 | 7,200 seconds |
| Startup | 100 | 21,600 seconds |
| Scale | 250+ | 86,400 seconds |
Billing
Sessions are billed per second while they run, with no per-session fee. A browser session costs $0.045 per hour. Sessions with a shell are billed by sandbox resources: $0.045 per vCPU-hour plus $0.013 per GiB-hour, about $0.084 per hour for a browser and shell on 1 vCPU and 3 GiB. Each session reports its own usage; GET /v1/usage in the API reference totals your account. See pricing for plans.
Every Boxline session runs in its own sandbox. The security page describes the isolation model.
These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.