reference

Errors & status codes

Every /v1 endpoint returns errors in one envelope, so you write the error-handling path once and it works for the whole API:

{
  "error": {
    "code": "insufficient_scope",
    "message": "the API key is missing the required scope: stream:golive",
    "requestId": "req_9f2c1a7b4e5d6f80",
    "requiredScope": "stream:golive"
  }
}
  • code — a stable, machine-readable string. Branch on this, not on the HTTP status or the human message. Codes are part of the compatibility promise (see Versioning); new codes may be added, existing ones will not change meaning within /v1.
  • message — a human-readable explanation. For logs and developers, not for branching. The wording may change at any time.
  • requestId — the same value returned in the X-Request-Id response header. Quote it when you ask us to look into a request.
  • requiredScope — present only on insufficient_scope. It names the exact scope your key is missing, so you can request a key that has it.

The X-Request-Id header

Every response — success or error — carries an X-Request-Id. If you send your own X-Request-Id on the request, we echo it back; otherwise the gateway generates one (req_ + hex). Log it on your side and you can correlate any call with our logs.

Codes and their HTTP status

HTTP code When it happens What to do
400 invalid_request Malformed input: a bad cursor, a non-numeric limit, a body that doesn't parse. Fix the request. Don't retry unchanged.
401 invalid_key No key sent, or the key is unknown, revoked, or expired. Check the Authorization: Bearer sk_live_… (or X-API-Key) header; mint a new key if needed.
403 insufficient_scope The key is valid but lacks the scope for this route. requiredScope names it. Issue a key that holds the named scope.
404 not_found The studio (or sub-resource) doesn't exist, or your account can't see it. Verify the id. A resource you don't own reads as not-found.
429 rate_limited You exceeded the per-key rate limit. Back off for the Retry-After seconds, then retry. See Rate limits.
503 write_disabled A write endpoint (go-live / go-offline) is currently gated off. Not retryable by you; the write surface is disabled in this preview.
503 unavailable A dependency needed to serve the request is temporarily down (e.g. key verification). Transient — retry with backoff.
502 bad_gateway An upstream service returned an unexpected error. Transient — retry with backoff.
500 internal An unexpected error on our side. Retry with backoff; if it persists, send us the requestId.

How to handle errors

  1. Read error.code, not the HTTP status alone. Two different 503s (write_disabled vs unavailable) mean very different things — one is a deliberate gate, the other is transient.
  2. Retry only the transient codes (unavailable, bad_gateway, internal, and rate_limited after its Retry-After). Use exponential backoff. Never hot-loop a retry.
  3. Never retry a 4xx unchangedinvalid_request, invalid_key, insufficient_scope, and not_found will fail identically until you change the request or the key.
  4. Surface requestId in your own error reports. It's the fastest way for us to trace a failing call.

Auth errors specifically

  • A 401 invalid_key means the credential itself is the problem (missing, unknown, revoked, expired). Re-check the header and the key.
  • A 403 insufficient_scope means the credential is fine but under-scoped. requiredScope tells you what to add. A key can only ever act within its owner's own account, so a 404 rather than a 403 can also mean "not yours".

See the full request/response shapes in the API reference and the credential model in Authentication.