Authentication
How Cocobox API keys work, where to put them, and how scoping is enforced.
Every request to the Cocobox API must be authenticated with an API key. The key proves which Cocobox user is calling, what models they’re allowed to invoke, and which credit pool is debited.
Key format
sk-coco-<32 hex chars>
Examples (illustrative — never real):
sk-coco-7c4f1a2e3b8d9a4c6f5e1d2b3a8c9d0e
The sk-coco- prefix is reserved by Cocobox; nothing else uses it. The 32 hex characters carry 128 bits of entropy.
Header forms
Send the key in either of these headers:
Authorization: Bearer sk-coco-…
x-api-key: sk-coco-…
If both are sent, Authorization wins. Anything else (cookies, query params, form bodies) is ignored — keys must travel in headers, over HTTPS.
Where keys come from
You can create keys two ways:
- In the app — Settings → API keys → Create new key. The full secret is displayed once and never shown again.
- Programmatically — see API keys for the meta-CRUD endpoints.
Storage
Cocobox stores only the SHA-256 hash of every key. Even if our database is compromised, an attacker can’t recover your secrets. If you ever lose a key, rotate it — there is no “show me the key again” button.
The first 16 characters of every key are stored separately as a prefix so that listing your keys can show you something useful (sk-coco-7c4f1a2e…) without revealing the secret.
Scoping
Each key carries optional restrictions, set at creation and editable later:
allowed_models— array of model aliases the key is permitted to call. Empty = all models.request_budget— hard cap on total requests for the lifetime of the key. Once reached, the key returns429until you raise the budget.tools_enabled— whether the key may invoke MCP tools. Setfalsefor read-only LLM access.is_active— kill switch. Disabled keys return401immediately.
A request that violates a key’s scope returns 403 with error: "scope_violation".
Examples
curl https://api.cocobox.io/v1/models \
-H "Authorization: Bearer $COCOBOX_API_KEY" curl https://api.cocobox.io/v1/models \
-H "x-api-key: $COCOBOX_API_KEY" # opencode reads OPENAI_API_KEY by default; point its base URL at Cocobox.
export OPENAI_API_KEY=sk-coco-…
export OPENAI_BASE_URL=https://api.cocobox.io/v1
opencode Rotation
Best practice: rotate any key that has been on a developer’s machine longer than 90 days, and rotate immediately when someone leaves the team.
To rotate:
- Create a new key with the same scopes.
- Roll the new key out to your config / secret store.
- Once traffic on the old key drops to zero (visible in Settings → API keys → Last used), revoke it.
There is no automatic key rotation today; it’s coming in a future release.
Revocation
A revoked or deleted key returns 401 unauthorized on the very next request, globally, within ~1 second. There is no grace period — revoke fearlessly.
Common errors
| Status | error | Meaning |
|---|---|---|
| 401 | unauthorized | No key, malformed key, or key not found. |
| 401 | key_inactive | Key exists but is_active = false. |
| 403 | scope_violation | Model not in allowed_models, or tools_enabled = false. |
| 403 | tools_disabled | MCP request with a key that has tools_enabled = false. |
| 429 | rate_limited | Per-minute or per-budget cap hit. |
| 402 | insufficient_credits | Your subscription’s credit pool is empty for paid models. |
See Errors for the full envelope.