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
-
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.
-
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.
-
Copy the plaintext once
The key is shown exactly once, at creation. Copy it now; it cannot be displayed again, only revoked and replaced.
-
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
{
"error": {
"code": "unauthorized",
"message": "Provide an API key as `Authorization: Bearer <key>`.",
"retryable": false,
"requestId": "req_xxxxxxxx"
}
}
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).