Errors and rate limits
The Brix API response envelope, error codes, the 600 requests per minute workspace limit, RateLimit headers, retries and idempotency keys.
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" }
erroris a stable, machine-readable code. Branch on it.messageis 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
| HTTP | error | Meaning |
|---|---|---|
| 401 | missing_credentials | No Authorization: Bearer header. |
| 401 | invalid_credentials | Key unknown, revoked or expired. |
| 403 | forbidden | The key lacks the permission: Missing permission: <perm>. |
| 403 | not_shared | The content is not shared to that screen’s location. Share it there first. |
| 404 | not_found | Does not exist, is outside the key’s location, or belongs to another workspace. |
| 409 | revoked | The key is revoked. Create a new key. |
| 409 | already_inactive | The cast or takeover already ended. |
| 409 | idempotency_in_progress | A request with the same Idempotency-Key is still running. |
| 413 | too_large | The body or file is over the limit. |
| 415 / 422 | unsupported_type | The file type is not accepted. |
| 422 | validation_error | A field is missing or invalid. message names it. |
| 422 | invalid_node | nodeId is not a node in this account. |
| 422 | invalid_folder | The folder does not exist in this workspace. |
| 422 | content_unplayable | The content cannot play, for example a file still processing. |
| 422 | no_screens | The target matched no screens the key can reach. |
| 429 | rate_limited | Over the rate limit. Wait Retry-After seconds. |
| 500 | internal_error | Something went wrong on our side. Retry with backoff. Quote requestId. |
| 503 | database_busy | Retry 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/limitsreturns the workspace’s limits. - Some routes also have their own limit.
POST /v1/media/uploadallows 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,503and network errors. WaitRetry-Afterwhen it is present, otherwise back off exponentially. - Do not retry other
4xxresponses. Fix the request. - Send an
Idempotency-Keyheader 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.