Errors & rate limits

The standard response envelope, error codes to branch on, and how rate limiting works.

Every API response uses one envelope, and every error carries a stable code. Branch on the code, never the message.

The envelope

{
  "data": { "...": "your result, or null on error" },
  "error": { "code": "ERROR_CODE", "message": "Human-readable explanation" },
  "meta": { "requestId": "req_..." }
}

On success error is null; on failure data is null. Always log meta.requestId — it’s what support needs to trace a request. Validation failures add an error.fields map keyed by field name.

Error codes

Status Code Meaning
401 UNAUTHORIZED Missing or invalid credentials
403 FORBIDDEN Authenticated, but not allowed (wrong role / org)
403 INSUFFICIENT_SCOPE The API key lacks a required scope
403 FEATURE_DISABLED The feature isn’t enabled for your plan
402 INSUFFICIENT_CREDITS Not enough AI credits for this action
404 NOT_FOUND The resource doesn’t exist or isn’t yours
409 ALREADY_EXISTS A conflicting resource already exists
422 VALIDATION_ERROR Input failed validation (see error.fields)
429 RATE_LIMITED Too many requests — back off

Rate limits

Rate-limited endpoints return these headers on every response so you can self-throttle:

Header Meaning
X-RateLimit-Limit Requests allowed in the current window
X-RateLimit-Remaining Requests left in the window
X-RateLimit-Reset Seconds until the window resets
Retry-After Seconds to wait before retrying (sent on 429)

Exceeding a limit yields a 429 with code RATE_LIMITED; honor Retry-After and retry with exponential backoff. Per-plan limits are listed under API keys & scopes.

Pagination

List endpoints return a bounded, most-recent-first set — there’s no cursor pagination today. Narrow with per-endpoint filters (e.g. days on analytics), or use CSV/PDF export for full history. Full reference: errors & limits.

Was this helpful?

Last updated July 26, 2026 · Edit this page ↗