Skip to content

Error Reference

All API errors return a consistent JSON envelope:

{
"error": {
"code": "error_code",
"message": "Human-readable description",
"retryable": true
}
}
  • code — Machine-readable error identifier (use this for programmatic handling)
  • message — Human-readable description (may change, don’t parse this)
  • retryable — Whether the request can be retried as-is
CodeHTTP StatusRetryableDescriptionHow to Fix
unauthorized401NoMissing, invalid, or expired bearer tokenCheck your API key is correct and active. Keys use the brk_ prefix.

The API returns WWW-Authenticate: Bearer realm="brightly" on all 401 responses.

CodeHTTP StatusRetryableDescriptionHow to Fix
insufficient_scope403NoAPI key doesn’t have the required scopeCreate a new key with the needed scope, or update the existing key’s scopes.
session_mismatch403NoMCP session belongs to a different API keyStart a new MCP session with the correct API key.
CodeHTTP StatusRetryableDescriptionHow to Fix
validation_error400NoRequest body or query params failed Zod validationCheck the error message for the specific field that failed. Review the endpoint’s request body documentation.
CodeHTTP StatusRetryableDescriptionHow to Fix
not_found404NoResource doesn’t exist or isn’t in your orgVerify the UUID is correct and belongs to your organization.
lead_not_found404NoLead referenced in appointment creation doesn’t exist in your orgCheck the lead_id exists via GET /api/v1/leads/:id first.
duplicate409NoRecord violates a unique constraintA lead with this phone/email may already exist. Check before creating.
compliance_blocked422NoMessage blocked by compliance checksThe lead has sms_opted_out: true or on_dnc_list: true. Check these fields before sending.
CodeHTTP StatusRetryableDescriptionHow to Fix
rate_limit_exceeded429YesToo many requests in the current windowWait and retry. Reads: 60/min. Writes: 30/min. Use exponential backoff with jitter.

Every response includes rate limit information:

RateLimit-Limit: 60
RateLimit-Remaining: 45
RateLimit-Reset: 1715385600
CodeHTTP StatusRetryableDescriptionHow to Fix
query_failed500YesDatabase read failedTransient error — retry the request. If persistent, contact support.
create_failed500YesDatabase write failedTransient error — retry with the same request body.
internal_error500YesUnhandled server errorRetry the request. If persistent, contact support.
CodeHTTP StatusRetryableDescriptionHow to Fix
no_session400NoGET request without an active MCP sessionSend a POST to initialize a session first, then include the mcp-session-id header.
too_many_sessions503YesServer at 1,000 concurrent session capacityWait for existing sessions to expire (30-min TTL) or close unused sessions with DELETE /mcp.

For errors with retryable: true, use exponential backoff with jitter:

async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const res = await fetch(url, options);
if (res.status !== 429 && res.status < 500) return res;
const delay = Math.min(1000 * Math.pow(2, i), 30000);
const jitter = delay * (0.5 + Math.random() * 0.5);
await new Promise(r => setTimeout(r, jitter));
}
throw new Error('Max retries exceeded');
}