API keys
Create API keys with only the scopes an agent needs, a spend cap and an expiry; rotate them, revoke them, and check what a key can do.
Give each agent, service or CI job its own key, with only the scopes it needs. Creating keys needs platform:write, which the default key does not have: create the first such key in the dashboard.
Create a key
bashcurl -s https://beta-api.b3os.org/v1/keys \ -H "Authorization: Bearer $B3OS_ADMIN_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "research agent", "scopes": ["vision:run", "sandboxes:write", "sandboxes:run", "infer:run"], "spend_cap_usd": 20, "expires_at": "2026-12-31T00:00:00Z"}'
tsimport { B3OS } from "@b3os/sdk";const admin = new B3OS({ apiKey: process.env.B3OS_ADMIN_KEY });const key = await admin.keys.createKey({ name: "research agent", scopes: ["vision:run", "sandboxes:write", "sandboxes:run", "infer:run"], spend_cap_usd: 20, expires_at: "2026-12-31T00:00:00Z",});console.log(key.secret); // shown once
pythonimport osfrom b3os import B3OSadmin = B3OS(api_key=os.environ["B3OS_ADMIN_KEY"])key = admin.keys.create_key({ "name": "research agent", "scopes": ["vision:run", "sandboxes:write", "sandboxes:run", "infer:run"], "spend_cap_usd": 20, "expires_at": "2026-12-31T00:00:00Z",})print(key["secret"]) # shown once
Create keys from your own code, the dashboard or the CLI's b3os keys, not through an agent. Keep platform:write out of the keys your agents hold, so an agent can never mint itself a wider key.
The response includes secret, the only time it is returned, and redacted, the start and end of the secret for recognizing it later. Store the secret in your secret manager.
| Field | Meaning |
|---|---|
scopes | Required. Scopes from the catalog, <product>:* or *; never more than the creating key holds |
spend_cap_usd | Requests fail with spend_cap_exceeded once the key has spent this much in the billing period; never above the creating key's cap |
expires_at | When the key stops working |
project_id | Another project in the same organization; your key's project by default |
Asking for scopes or a cap beyond your own fails with forbidden, reason scope_escalation.
Check a key
GET /v1/keys/current works with any valid credential and returns its kind, organization, project, scopes, spend cap and expiry. GET /v1/keys lists the organization's keys (filter by project_id or status), and GET /v1/keys/{key_id} shows one with its spend this period and its last use. Secrets are never returned after creation.
Change, rotate and revoke
PATCH /v1/keys/{key_id}changes the name, spend cap, expiry or metadata. Scopes never change; create a new key instead.- To rotate, create a new key with the same scopes, deploy it, then revoke the old one.
DELETE /v1/keys/{key_id}revokes the key at once. Open streams authenticated by it close within a minute, and routines published with it pause their triggers until a new version is published with a valid key. A revoked key stays listed for audit.
Keys and sandboxes
Code in a sandbox never needs a key: it calls http://127.0.0.1:7700 and runs with the scopes of the sandbox's grant, a subset of the key that created it. Do not put API keys in sandbox environment variables. See agents in sandboxes.