Authentication

How Cocobox API keys work, where to put them, and how scoping is enforced.

Last updated

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:

  1. In the app — Settings → API keys → Create new key. The full secret is displayed once and never shown again.
  2. 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 returns 429 until you raise the budget.
  • tools_enabled — whether the key may invoke MCP tools. Set false for read-only LLM access.
  • is_active — kill switch. Disabled keys return 401 immediately.

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:

  1. Create a new key with the same scopes.
  2. Roll the new key out to your config / secret store.
  3. 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

StatuserrorMeaning
401unauthorizedNo key, malformed key, or key not found.
401key_inactiveKey exists but is_active = false.
403scope_violationModel not in allowed_models, or tools_enabled = false.
403tools_disabledMCP request with a key that has tools_enabled = false.
429rate_limitedPer-minute or per-budget cap hit.
402insufficient_creditsYour subscription’s credit pool is empty for paid models.

See Errors for the full envelope.