ScenebrewDevelopers

Authentication

API keys as Bearer tokens, the read and write scopes, and what 401 and 403 responses mean.

API keys

Every request carries a first-party API key as a Bearer token:

Authorization: Bearer sbk_live_…

Keys are created in the app under Settings → API Keys. A key belongs to the workspace it was created in and acts as the user who created it; it sees that workspace's projects and nothing else. Another workspace's ids answer 404, never 403 — existence is not disclosed.

The full key is shown once, at creation. The app keeps only the display prefix (sbk_live_a1b2…) and the time the key was last used, so a lost key is replaced, not recovered. Revoking a key takes effect on its next request.

Scopes

A key's scope is chosen when it is created and cannot be widened later:

Level in the appScopesAllows
Read-onlyreadGET /v1/me, credits, models, and every read of projects, files, scenes, artifacts, operations, sessions and the library
Read & writeread, writeEverything above, plus creating and changing entities, uploading files and artifacts, running steps, posting messages, cancel

write does not imply read. The app always mints Read & write as both, which is what API clients and the MCP server need. Each operation in the reference names the scope it requires.

Responses

401 Unauthorized — no key, an unknown key, or a revoked one. The response carries WWW-Authenticate: Bearer and a problem document:

{
  "type": "about:blank",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Missing API key",
  "instance": "/v1/me"
}

403 Forbidden — the key is live but lacks the scope the operation needs. Because the caller is authenticated, the response names the missing scope, as RFC 6750 §3.1 specifies:

HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope", scope="write"
Content-Type: application/problem+json
{
  "type": "https://scenebrew.com/problems/insufficient-scope",
  "title": "Forbidden",
  "status": 403,
  "detail": "This operation requires the 'write' scope",
  "instance": "/v1/scenes/0192a7c4-3f5e-7c8a-9b1d-2e3f4a5b6c7d/steps",
  "code": "insufficient_scope"
}

The fix is a new key at the Read & write level; scopes are fixed for the life of a key.

Keeping keys safe

  • Put keys in environment variables or your CI's secret store, never in source. The prefix is sbk_live_ followed by 40 characters — add that pattern to your secret scanner.
  • Use one key per environment or integration, named after it, so the last used column in the app tells you what is alive.
  • Rotate by creating the replacement first, switching, then revoking the old key.
  • Presigned download URLs — on artifacts and files — are separate, short-lived credentials: they need no header and expire at download_expires_at (equivalently, after download_expires_in seconds). Do not store them.

Playground

Each reference page has a playground that sends requests from your browser directly to the API. Your key is kept in the browser for the session and never passes through this site.

On this page