Authentication

API keys, the read/write/admin ladder, and which accounts a key can reach.

Every request carries a key as a Bearer token:

curl "$BIDANDSCALE_URL/api/v1/accounts" \
  -H "Authorization: Bearer bsk_…"

Create keys in Settings → API — workspace-level for keys that reach several accounts, or inside an account's settings for one clamped to it. The key is shown once. If you lose it, revoke it and create another; there is no way to retrieve it.

Keys start with bsk_ and are for this API only. The MCP server is a separate credential surface with no keys at all — it authenticates over OAuth 2.1, so there is nothing there to send here.

Two dimensions

A key carries a permission scope and an account scope, independently.

Permission scope

Ranked, not orthogonal: a key satisfies a requirement when its own tier is at least as high.

ScopeCan do
readEvery GET. Also starting agent runs — a read key's run gets a restricted toolset with every write tool removed, so it can analyse but not propose.
writeEverything above, plus proposing changes, deciding approvals, and triggering syncs and audits.
adminEverything above, plus changing optimization targets — which change what the system does unattended.

A request above a key's tier gets 403, not 401. The credential is valid; the permission is not.

Account scope

Key shapeReaches
Account keyExactly one account. Naming any other in a URL is a 403.
Workspace key, all accountsEvery account in the workspace, current and future.
Workspace key, chosen accountsOnly the accounts picked when the key was created.

GET /api/v1/accounts always returns exactly what the key can reach, so it works as a discovery call whatever the shape.

An out-of-reach account never returns a 404 that would confirm it exists — you get a 403 for accounts, and agent runs outside your reach are reported as not found.

Rotating a key

Create the new key, deploy it, then revoke the old one. Revocation takes effect on the next request. Revoked keys keep their row so /history can still attribute past changes to them.

Handling keys

  • Server-side only. There are no CORS headers; a key in a browser bundle is a key anyone can read.
  • One key per consumer, so you can revoke one without taking down the rest.
  • Give each key the lowest scope that works. A reporting job wants read.

On this page