Errors and rate limits

The Brix API response envelope, error codes, the 600 requests per minute workspace limit, RateLimit headers, retries and idempotency keys.

View as Markdown

Response envelope

Success:

{ "data": { "id": "scr_...", "name": "Lobby" } }

List endpoints return an array in data. Paginated lists add nextCursor (see Pagination). Endpoints that serve bytes, such as a media file or an invoice PDF, return the bytes.

Error:

{ "error": "validation_error", "message": "name is required" }
  • error is a stable, machine-readable code. Branch on it.
  • message is for people. It can change. It is sometimes absent, for example {"error":"not_found"}.
  • 5xx errors add requestId. Quote it to support.

Status codes and error codes

HTTPerrorMeaning
401missing_credentialsNo Authorization: Bearer header.
401invalid_credentialsKey unknown, revoked or expired.
403forbiddenThe key lacks the permission: Missing permission: <perm>.
403not_sharedThe content is not shared to that screen’s location. Share it there first.
404not_foundDoes not exist, is outside the key’s location, or belongs to another workspace.
409revokedThe key is revoked. Create a new key.
409already_inactiveThe cast or takeover already ended.
409idempotency_in_progressA request with the same Idempotency-Key is still running.
413too_largeThe body or file is over the limit.
415 / 422unsupported_typeThe file type is not accepted.
422validation_errorA field is missing or invalid. message names it.
422invalid_nodenodeId is not a node in this account.
422invalid_folderThe folder does not exist in this workspace.
422content_unplayableThe content cannot play, for example a file still processing.
422no_screensThe target matched no screens the key can reach.
429rate_limitedOver the rate limit. Wait Retry-After seconds.
500internal_errorSomething went wrong on our side. Retry with backoff. Quote requestId.
503database_busyRetry after Retry-After (2 seconds).

An unknown path returns 404 {"error":"not_found","message":"No route here."}.

Rate limits

  • 600 requests per minute per workspace, shared by all its API keys, in fixed 60-second windows.
  • The limit applies to API-key traffic. People using the CMS do not count against it.
  • Brix support can raise the limit for a workspace. GET /v1/account/limits returns the workspace’s limits.
  • Some routes also have their own limit. POST /v1/media/upload allows 300 per minute per key. The MCP endpoint allows 30 per minute per caller. The OAuth token endpoint allows 30 per 5 minutes per IP address.

Every API-key response carries the IETF RateLimit headers:

RateLimit-Limit: 600
RateLimit-Remaining: 587
RateLimit-Reset: 41
RateLimit-Policy: 600;w=60

RateLimit-Reset is seconds until the window resets. Over the limit, the API returns 429 with Retry-After:

{
  "error": "rate_limited",
  "message": "This workspace has used its 600 requests per minute. Wait 12 seconds and try again.",
  "limit": 600,
  "windowSeconds": 60,
  "retryAfterSeconds": 12
}

Retries

  • Retry 429, 500, 503 and network errors. Wait Retry-After when it is present, otherwise back off exponentially.
  • Do not retry other 4xx responses. Fix the request.
  • Send an Idempotency-Key header on creates you might retry (screens, playlists, schedules, media upload). A repeat with the same key returns the first success instead of creating a second item.
curl -X POST https://api.brixsignage.com/v1/playlists \
  -H "Authorization: Bearer $BRIX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1d0f5e-nightly-2026" \
  -d '{"name": "Nightly specials"}'

Request ids

Send x-brix-request-id (letters, digits, ., _, -, up to 120 characters) to tag a request with your own trace id. Quote it to support with the time of the call.

Versioning and deprecation

The version is in the path: /v1. Brix announces a retiring route at least 90 days ahead. Calls to it carry Deprecation and Sunset headers, and GET /v1/status/deprecations (no auth) lists every retiring route, its end date and its replacement.