Skip to content

Authentication: API keys and accounts

How Browserberg separates machine keys from human dashboard accounts, how to create a bearer key, and how to read the error envelope.

Last updated:

Two credentials by design

Browserberg keeps two credentials apart on purpose. API keys authenticate machines: org-scoped bearer tokens with the prefix bb_, sent as Authorization: Bearer bb_... on every API call. Dashboard accounts authenticate humans: an httpOnly cookie session for the web app, useless as an API credential.

The separation is not cosmetic. Revoking a leaked key never locks a person out, an SSO change never breaks a pipeline, and a key found in a log cannot open the dashboard. If something authenticates a script, it is a key; if it authenticates a person, it is an account.

Create your first key

  1. Register a dashboard account

    Open /app on your deployment and create an organisation. The account you register with becomes its owner — and only an owner can create API keys.

  2. Open the key screen

    The dashboard is German-first, so the screen is labeled "API-Schlüssel" in the navigation. Open it and choose to create a new key.

  3. Copy the plaintext once

    The key is shown exactly once, at creation. Copy it now; it cannot be displayed again, only revoked and replaced.

  4. Store it as an environment variable

    Export it as BROWSERBERG_API_KEY, which every sample in these docs and both SDKs read by default. Keep it out of source control.

The envelope, provoked

The fastest way to learn the error shape is to earn a refusal. This request carries no key at all:

# A request with no key is refused with the machine-readable envelope every
# error uses. Branch on error.retryable, not on the code: the enum is open.
curl -s -X POST "https://browserberg.com/v1/sessions" \
  -H 'Content-Type: application/json' -d '{}' \
  | python3 -m json.tool

Reading the error envelope

Every refusal, from a missing key to a full fleet, arrives in the same envelope: an error object with code, message, retryable and sometimes retryAfterMs, requestId and details. Branch on retryable, never on the code — the code enum is open, and a newer server may introduce codes your switch statement has never seen. retryable: true means back off and try again; false means fix the request.

The requestId is your bridge to support: it names the exact request in our logs, so quote it whenever something behaves in a way these docs did not predict.

Tip · Read your usage

`GET /v1/usage` returns the four metered dimensions over a window, per day, with open sessions and the included quota; the dashboard’s Verbrauch screen draws it. See the [usage guide](/docs/guides/usage-and-billing).