VeilBrowserDocs

Authentication

The three VeilBrowser credentials, where each one belongs, and how to manage organization API keys.

VeilBrowser uses three distinct credentials. Mixing them up is the most common integration mistake, so start here before writing any client code.

The three credentials

CredentialHeader / transportIssued byAuthorizes
Dashboard sessionCookie or Authorization: BearerSigning in at veilbrowser.netProfile CRUD, session history, organizations, billing
Organization API keyX-API-KeyDashboard → Settings → API keysWorker-to-cloud calls: license authorize, profile config, session tracking, release catalog
Worker API keyX-API-KeyYou, as the worker's API_KEY env varInbound requests to a Local API worker

The first two go to api.veilbrowser.net. The third goes to a worker on your own network. They are never interchangeable.

Dashboard session

Profile management is a dashboard operation. GET/POST/PATCH/DELETE /v1/profiles, GET /v1/sessions, the organization endpoints and everything under /v1/billing require a signed-in session, established by Better Auth at sign-in.

Scripts that manage profiles carry the same session cookie a browser would:

terminal
curl https://api.veilbrowser.net/v1/profiles \
  -H "Cookie: better-auth.session_token=..."

Organization keys are not a substitute here

An organization API key will not authenticate profile CRUD. It is scoped to the worker integration endpoints listed below. If you need unattended profile provisioning, drive it from a service account session.

Organization API key

This is the key every self-hosted deployment depends on. It identifies the organization, authorizes the private image pull, and gates each browser launch at runtime.

Creating one

Open the dashboard

Sign in and go to Settings → API keys.

Create the key

Give it a name that identifies where it will run, such as prod-cluster-eu. Keys are scoped to the organization that is active when you create them, so confirm the right organization is selected first.

Copy it immediately

The full key is shown once. VeilBrowser stores only a SHA-256 hash, so a lost key cannot be recovered — it can only be revoked and replaced.

The Connect page shows the same key alongside its lowercased form, which is the path segment used when pulling images from the license-gated registry.

Where it is used

PurposeHow it travels
Image pullLowercased, as a path segment: registry.veilbrowser.net/<org-key-lower>/local-api
Worker runtimeThe VEIL_KEY environment variable on each worker
Cluster-mode launchInside the env payload of the wss://<host>/launch query string

Endpoints that accept it:

  • POST /v1/license/authorize — concurrency check before a launch
  • GET /v1/profiles/:id/config — fetch a profile's launch configuration
  • POST /v1/profiles/:id/sessions and DELETE /v1/profiles/:id/sessions/:sessionId — session lifecycle
  • GET /v1/chromium/releases and GET /v1/chromium/releases/:version/download — browser build catalog

Rotating

Because the key is both a pull credential and a runtime credential, rotate in this order to avoid an outage:

Create the replacement

Add a second key before disabling anything. Both keys are valid at once.

Roll the fleet

Update VEIL_KEY in each worker's environment and restart. Workers fail closed, so a worker still holding a revoked key stops launching rather than launching unlicensed.

Verify, then revoke

Confirm every worker is healthy and launching, then delete the old key from Settings → API keys.

Treat it like a password

An organization key grants image pulls and browser launches against your plan. Store it in your secret manager, never in a repository, and rotate it immediately if it leaks.

Worker API key

Each Local API worker is protected by its own shared secret, set as API_KEY in the worker's environment and sent by clients as X-API-Key. It has nothing to do with your VeilBrowser account — it exists so that only your automation can reach the worker.

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

Cluster mode bypasses this header

When a worker runs with VEIL_SERVER_MODE=cluster, the /launch WebSocket and the /browsers/* routes do not check X-API-Key — authorization happens per launch using the organization key in the connection payload. Never expose a cluster-mode worker directly to the internet; put it behind the cluster-manager edge. See Edge security & TLS.

Next steps

Was this page helpful?

On this page