Docs
Dashboard
API reference / BasicsBeta

Overview

The base URL, authentication, the WebSocket URLs and every endpoint of the API.

Everything Boxline does is an HTTP call. The SDKs and the MCP server use the same API. Every endpoint has its own page below, with its parameters, responses, errors, and examples in curl, Node and Python (and the CLI, where it has a command).

New here? Start here has the eight calls most things begin with, each as the smallest request that works.

These pages are generated from the API’s OpenAPI description (version 1.0.0), so they always match it. You can fetch it yourself at GET /v1/openapi.json, for example to generate a client.

Basics

Base URLhttps://api.boxline.dev
Authenticationx-api-key: <key> or Authorization: Bearer <key> on every request. See below.
Request bodiesJSON with content-type: application/json, except file uploads, which send the raw bytes.
ErrorsA matching HTTP status and {"error": {"code", "message", "requestId"}}. See Errors and request ids.
Request idsEvery response has X-Request-Id. Quote it when you ask for help.
Rate limitsPer route, and per project, user or organization, with RateLimit-* headers. See Rate limits.
Safe retriesIdempotency-Key on the calls that create something. See Idempotency keys.
Lists?limit=&after= in, { data, next } out. See Pagination.
Shell
curl https://api.boxline.dev/v1/project/usage \  -H "x-api-key: $BOXLINE_API_KEY"

Authentication

Every call needs an API key, except a few public ones (GET /v1/pricing, GET /v1/openapi.json and GET /healthz). Create keys in the console, or with POST /v1/project/api-keys. A key belongs to one project, and everything it does happens in that project, so no call takes a project id. The project belongs to an organization, which holds the people and the billing. You manage organizations in the console, where an API key gets 403 console_login_required: see Organizations, projects and team members. Your own model keys belong to the project too.

GET /v1/project/api-keys shows who made each key in createdBy: via (console, api_key or support), the user’s userId and email, and the apiKeyId when a key made it. It is null for keys made before this was recorded. A new sign-up cannot create a key until it has entered its confirmation code (403 email_unconfirmed).

The console signs in with a cookie instead (bx_session). Scripts and servers should always use a key.

Password resets and account recovery

Forgot your console password? Ask for a reset link on the console’s sign-in page. The link goes to your account’s email, works once, and expires after 30 minutes. A new request replaces the earlier link. After a reset, every console login of the account ends, and you get an email saying the password was changed.

A reset also confirms your email. If the email was not confirmed yet, the reset is treated as recovering the account, in case someone else set it up with your address. Besides the new password, it does this in every organization you own and in your personal organization, for all their projects:

  • revokes every API key (make new ones afterwards);
  • switches off its webhook endpoints, with disabledReason: "account_recovered";
  • switches off its task schedules and cancels queued scheduled runs (errorCode: "account_recovered");
  • removes the organization’s other members (their console logins end) and withdraws its pending invitations, so you are its only owner again;
  • stops the running sessions of its projects without saving them (stopReason: "account_recovered"), and clears what its stopped sessions had saved: a resume then answers 409 nothing_saved.

The reset email of such an account says so before you use the link. A reset of a confirmed account, and a password change while signed in, keep your API keys and members.

Confirm your email

Signing up needs a 6-digit code. We email it to your address, and the console asks for it before you can use the new account. Signing in never asks for a code. If you leave before entering it, the account takes you back to the same page the next time you sign in.

The code6 digits, random, and it works once.
Valid for15 minutes.
Wrong tries5 on one code, then that code is locked (410 confirmation_code_locked): ask for a new one. Over all of the account’s codes the limit is 15 wrong tries. After that no code is accepted (403 confirmation_locked), and only a password reset confirms the email.
A new codeAsk for one in the console. It replaces the old code and gives that code 5 tries, but it does not reset the 15 in total. At most 5 codes an hour and 10 a day (see Rate limits).

Until a new sign-up has entered its code:

  • The account can sign in only to confirm the email. Every other console call answers 403 email_unconfirmed. Reading GET /v1/auth/me, signing out, the two confirmation calls and accepting an invitation still work.
  • Creating an API key answers 403 email_unconfirmed. So does a key creating one, while every owner of the organization is a sign-up that has not entered its code.
  • API keys the account already has keep working.

Accounts made before the code existed are never held back, and never asked for a code when they sign in. If their email is not confirmed, everything works except inviting people and transferring an organization, which need a confirmed email (and nobody can demote or remove you from an organization you created until you confirm it: 403 email_unconfirmed). You can confirm whenever you like: the same two calls work for any signed-in user whose email is not confirmed.

GET /v1/auth/me shows the state in user:

FieldMeaning
emailVerifiedThe email is confirmed.
emailConfirmationRequiredtrue only for a new sign-up that has not entered its code yet. The console shows the code page and nothing else.
emailConfirmationAvailableThis server emails confirmation codes, so asking for one can work.

A password reset confirms your email too, and so does accepting an invitation, or signing up with an invitation link: those links were mailed to that address, so no code is needed.

The console makes the two calls, POST /v1/auth/confirm-email with { "code": "123456" } and POST /v1/auth/confirm-email/send. They need a console login: with an API key the answer is 403 console_login_required.

AnswerWhy
400 invalid_confirmation_codeThe code is wrong, or not 6 digits. The message says how many tries are left.
410 confirmation_code_expiredNo code was asked for, it was used or replaced, or it is older than 15 minutes.
410 confirmation_code_locked5 wrong tries on that code. Ask for a new code.
403 confirmation_locked15 wrong tries over all of the account’s codes. No code is accepted or sent any more: reset the password to confirm the email.
429 rate_limitedToo many codes asked for (5 an hour, 10 a day), or too many tries.
503 mail_unavailableThe email could not be sent. Try again later.

WebSockets and the live view

Three session URLs are not plain HTTP calls. Each carries a signed token, works without your API key, and is on the session object. Get a session returns fresh ones every time; one is null when the session has no browser (connectUrl, liveUrl) or no shell (terminalUrl):

Session fieldWhat it is
connectUrlChrome DevTools Protocol WebSocket (/v1/connect?sessionId=…&token=…) for Playwright or Puppeteer. See Connect with Playwright.
liveUrlLive view page (/live/:id?token=…). Open it to watch the browser or take control. Anyone with it can control the browser: treat it like a password. See Live view.
terminalUrlTerminal WebSocket (/v1/sessions/:id/terminal?token=…). Send JSON text frames {"type":"input","data":"…"} or {"type":"resize","cols":N,"rows":N}; receive raw terminal output as binary frames. See Shell.

A URL of a stopped or deleted session answers 410 session_ended; a rotated or expired one, 401 unauthorized.

All endpoints

Web

Fetch a pagePOST/v1/fetch
Screenshot a pagePOST/v1/screenshot
Print a page to PDFPOST/v1/pdf
Extract data from pagesPOST/v1/extract

Crawls

Start a crawlPOST/v1/crawls
List crawlsGET/v1/crawls
Get a crawlGET/v1/crawls/{id}
Cancel a crawlPOST/v1/crawls/{id}/cancel

Sessions

Create a sessionPOST/v1/sessions
List sessionsGET/v1/sessions
Get a sessionGET/v1/sessions/{id}
Update a sessionPATCH/v1/sessions/{id}
Delete a sessionDELETE/v1/sessions/{id}
Stop a sessionPOST/v1/sessions/{id}/stop
Resume a sessionPOST/v1/sessions/{id}/resume
Stop, resume or delete many sessionsPOST/v1/sessions/bulk

Browser

Run browser actionsPOST/v1/sessions/{id}/browser/actions
Run a computer-use actionPOST/v1/sessions/{id}/browser/computer
Run a Playwright scriptPOST/v1/sessions/{id}/browser/script
Export cookies to a filePOST/v1/sessions/{id}/browser/export-cookies
Open the live viewGET/live/{id}

Shell

Run a commandPOST/v1/sessions/{id}/shell/exec
Restart the shellPOST/v1/sessions/{id}/shell/restart

Files

Read a file or list a folderGET/v1/sessions/{id}/files
Upload a filePUT/v1/sessions/{id}/files
Delete a file or folderDELETE/v1/sessions/{id}/files
Download a folderGET/v1/sessions/{id}/files/archive
Wait for a fileGET/v1/sessions/{id}/files/wait

Logs and recording

List session eventsGET/v1/sessions/{id}/events
Stream session eventsGET/v1/sessions/{id}/events/stream
List visited pagesGET/v1/sessions/{id}/pages
Get the recordingGET/v1/sessions/{id}/recording
Get a recording frameGET/v1/sessions/{id}/recording/frames/{index}

Agent

Start a runPOST/v1/agent/runs
List runsGET/v1/agent/runs
Get a runGET/v1/agent/runs/{id}
Stream a runGET/v1/agent/runs/{id}/events/stream
Send a message to a runPOST/v1/agent/runs/{id}/messages
Pause a runPOST/v1/agent/runs/{id}/pause
Resume a runPOST/v1/agent/runs/{id}/resume
Cancel a runPOST/v1/agent/runs/{id}/cancel
List modelsGET/v1/agent/models

Tasks

Create a taskPOST/v1/tasks
List tasksGET/v1/tasks
Get a taskGET/v1/tasks/{id}
Update a taskPATCH/v1/tasks/{id}
Delete a taskDELETE/v1/tasks/{id}
Run a taskPOST/v1/tasks/{id}/runs
List a task's runsGET/v1/tasks/{id}/runs

Profiles

Create a profilePOST/v1/profiles
List profilesGET/v1/profiles
Get a profileGET/v1/profiles/{id}
Update a profilePATCH/v1/profiles/{id}
Delete a profileDELETE/v1/profiles/{id}

Credentials

Create a credentialPOST/v1/credentials
List credentialsGET/v1/credentials
Get a credentialGET/v1/credentials/{name}
Update a credentialPATCH/v1/credentials/{name}
Delete a credentialDELETE/v1/credentials/{name}
Push a 2FA code or sign-in linkPOST/v1/credentials/{name}/codes
List the audit logGET/v1/credentials/audit

Extensions

Upload an extensionPOST/v1/extensions
List extensionsGET/v1/extensions
Get an extensionGET/v1/extensions/{id}
Delete an extensionDELETE/v1/extensions/{id}

Webhooks

Create a webhook endpointPOST/v1/webhooks
List webhook endpointsGET/v1/webhooks
Get a webhook endpointGET/v1/webhooks/{id}
Update a webhook endpointPATCH/v1/webhooks/{id}
Delete a webhook endpointDELETE/v1/webhooks/{id}
Send a test eventPOST/v1/webhooks/{id}/test
List deliveriesGET/v1/webhooks/{id}/deliveries
Retry a deliveryPOST/v1/webhooks/{id}/deliveries/{deliveryId}/retry
List event typesGET/v1/webhooks/event-types

Project

Get project settingsGET/v1/project/settings
Update project settingsPUT/v1/project/settings
List model keysGET/v1/project/model-keys
Set a model keyPUT/v1/project/model-keys/{provider}
Delete a model keyDELETE/v1/project/model-keys/{provider}
Create an API keyPOST/v1/project/api-keys
List API keysGET/v1/project/api-keys
Revoke an API keyDELETE/v1/project/api-keys/{id}
Get usage and costGET/v1/project/usage

Account

Sign upPOST/v1/auth/signup
Log inPOST/v1/auth/login
Log outPOST/v1/auth/logout
Get who is callingGET/v1/auth/me

Platform

Get prices and plansGET/v1/pricing
Get the OpenAPI descriptionGET/v1/openapi.json
Check healthGET/healthz

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.