VeilBrowserDocs

API reference

Cloud and worker REST endpoints: profiles, sessions, organizations, plans, licensing and launching.

VeilBrowser exposes two REST surfaces with different jobs and different credentials:

SurfaceBase URLJob
Cloud APIhttps://api.veilbrowser.netProvision profiles, read session activity, manage organizations and billing
Local APIEach worker, http://<worker>:38923Launch and stop browsers

The worker port is 38923 in the published container image. 3000 is the from-source default and appears only in a development checkout.

Nothing on the cloud API starts a browser, and nothing on a worker manages your organization. See Authentication for which credential goes where, and Errors for the response envelope.

Interactive schemas

Both services publish OpenAPI at GET /docshttps://api.veilbrowser.net/docs for the cloud, http://localhost:38923/docs on a worker. That is the machine-readable source of truth; this page is the narrative one.

Conventions

Successful responses are { "success": true, "data": … }. List endpoints wrap results in pagination metadata:

Prop

Type

All paginated endpoints accept page, limit, sortBy and sortOrder (asc or desc, default desc).

Profiles

Requires a dashboard session. All operations are scoped to the caller's active organization.

Sessions

The cloud session list is a read-only activity feed. Workers populate it through the profile-session endpoints below; there is no cloud endpoint that launches or stops a browser.

Organizations

Requires a dashboard session. Role requirements are noted per endpoint; roles are owner, admin and member.

Billing

Every route acts on the caller's active organization, taken from the dashboard session rather than from the request, and every one is restricted to owner and admin. A member gets 403 and AUTHORIZATION_ERROR; a session with no active organization gets 400 and VALIDATION_ERROR.

Contact

Plans

Launch and stop (Local API)

Browsers run on your workers, so launching goes to the Local API or the cluster load balancer — never to api.veilbrowser.net. Authenticate with the worker's API_KEY.

Launch
curl -X POST http://localhost:38923/sessions/profile \
  -H "X-API-Key: $WORKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "profileId": "<profile-uuid>" }'

Supply either profileId for an existing profile or spec to create one from criteria, never both. Optional browser and proxyOverride objects adjust that single launch.

The 201 response includes id, status, startedAt, launchId, debugPort, webSocketDebuggerUrl, devtoolsFrontendUrl and viewUrl. debugPort is the one Selenium needs, because debuggerAddress takes a host and port rather than a URL.

Stop
curl -X DELETE http://localhost:38923/sessions/<session-id> \
  -H "X-API-Key: $WORKER_API_KEY"

The launch URL is addressed to the worker

webSocketDebuggerUrl is wss://<host>/browsers/<launchId>/devtools/browser/<guid>?ct=<token> — the worker's own public address, with the per-launch capability the /browsers/* routes require. Connect to it from anywhere that can reach the worker. Behind the cluster load balancer it is prefixed with /w/<workerId>.

Worker endpoints

MethodPathPurpose
GET/healthStatus, version and contract version — no auth
GET/profilesAvailable browser bundles, filterable and paginated
GET/profiles/versionsBrowser majors installed on this host
GET/profiles/android-modelsDevice models for a given browserVersion
POST/sessions/profileLaunch a profile
GET/sessionsList sessions — status of running, exited or killed
GET/sessions/{id}Session detail, including the CDP URL
DELETE/sessions/{id}Kill a session
GET/fleet/statusFull host snapshot for the cluster manager
GET/fleet/liveLightweight CPU, memory and active-session metrics

GET /profiles accepts filename, browserVersion, os, osVersion, windowsVersion (7, 10, 11), osArch (x86, arm), renderer, model and gpuName, plus the standard pagination parameters.

Worker integration (organization API key)

Self-hosted workers use the organization key against the cloud for licensing and session tracking. You rarely call these directly, but they explain what a worker is doing.

MethodPathPurpose
POST/v1/license/authorizeConcurrency check before launch — fail-closed. Reserves a slot
GET/v1/license/sessionsWhat the organization is being charged concurrency for, and whether each row is stale
POST/v1/license/sessions/heartbeatWorker-authoritative liveness for one machine; anything it omits is released
POST/v1/license/sessions/reclaimEnd running sessions whose worker is gone, releasing their concurrency
GET/v1/profiles/{id}/configFetch a profile's launch configuration
POST/v1/profiles/{id}/sessionsReport session start; consumes the reservation
DELETE/v1/profiles/{id}/sessions/{sessionId}Report session end
GET/v1/chromium/releasesBrowser build catalog
GET/v1/chromium/releases/{version}/downloadDownload a build

POST /v1/license/authorize wraps its answer in the usual { success, data } envelope. data carries allowed, current, limit (null = unlimited), an optional slotId, and profileConfig when a profileId was supplied. A refusal is 402 with a reason of concurrency_limit or profile_limit in the same envelope, so read data.allowed rather than the status alone.

GET /v1/license/sessions is the one to reach for when a launch is refused and you do not know why. It answers to the organization key — unlike the dashboard's GET /v1/sessions, which needs a browser session — and returns current, limit, the split into runningSessions and reservedSlots, both liveness TTLs, and up to 500 running sessions:

FieldMeaning
machineIdWhich worker reported the session
startedAtWhen it launched
heartbeatAtLast liveness report, or null if the worker has never sent one
stalePast its deadline — five minutes since heartbeatAt, or six hours since startedAt when it has never reported

stale is computed exactly as the reaper decides, so a row flagged here is a row POST /v1/license/sessions/reclaim would close. See Licensing & concurrency and Errors.

Next steps

  • Errors — codes and retry guidance.
  • Limits — the ceilings these endpoints enforce.
Was this page helpful?

On this page