Rate limits & errors.
Per-tier rate limits, retry behavior, and the complete error code catalog. Designed so you can build a robust client without trial-and-error.
TL;DR
Rate limits: Pro = 60 req/min, Company = 600 req/min, burst allowance 2× sustained. Limits per workspace, not per key. Errors: standard HTTP codes + error envelope with type, code, message, request_id. 429 responses include Retry-After header. Retry with exponential backoff for 5xx; don't retry 4xx (except 429).
01Rate limits per tier
| Tier | Sustained req/min | Burst (10s window) | Notes |
|---|---|---|---|
| Free | — (no API access) | — | API requires Pro+ |
| Pro | 60 | 120 | Per workspace, all keys combined |
| Company | 600 | 1,200 | Per workspace, all keys combined |
| Enterprise | Custom | Custom | Negotiated per contract |
Limits are per workspace. If you have 3 API keys for the same workspace, they share the budget.
02Rate-limit headers
Every response includes:
X-RateLimit-Reset is a Unix timestamp for when the rate window resets. Use it to back off cleanly when you see X-RateLimit-Remaining: 0.
03Retry guidance
| Status | Should you retry? | How |
|---|---|---|
| 2xx | — | Success |
| 400 Bad Request | No | Fix the request |
| 401 Unauthorized | No | Bad API key — check Settings → API |
| 403 Forbidden | No | Plan tier doesn't include this endpoint |
| 404 Not Found | No | Resource doesn't exist |
| 409 Conflict | No | Resource state prevents the operation |
| 429 Too Many Requests | Yes, respect Retry-After | Honor the header |
| 500 Internal Server Error | Yes, exponential backoff | 1s, 2s, 4s, 8s, 16s, then give up |
| 503 Service Unavailable | Yes, exponential backoff | Same as 500 |
04Error code catalog
The error.code field in the response envelope. Stable strings — safe to programmatically branch on.
| Code | HTTP | Meaning |
|---|---|---|
missing_field | 400 | Required field absent. field in envelope tells you which. |
invalid_field | 400 | Field value doesn't match expected type/format. |
invalid_api_key | 401 | API key is missing, malformed, or revoked. |
plan_required | 403 | Endpoint requires higher plan tier. |
not_found | 404 | Resource doesn't exist or you don't have access. |
conflict_state | 409 | Resource exists in a state that prevents the operation. |
rate_limited | 429 | Too many requests. Respect Retry-After. |
quota_exceeded | 429 | Monthly quota exceeded (e.g., brief generation cap). |
internal_error | 500 | Our problem. Retry. |
service_unavailable | 503 | Brief outage. Retry. |
upstream_timeout | 504 | Underlying data source timed out (e.g., during enrichment). Retry. |
05Debugging with request_id
Every API response includes X-Request-Id. When something goes wrong, include this in your support ticket — it lets us trace the request through our systems in seconds.
Format: req_ + 12 alphanumeric characters. Example: req_4f2a9c3b1d8e.
The request_id is also in the error envelope (error.request_id), so you can log it from the error body even if you don't capture headers.
06Common mistakes
Retry-After on 429Retry-After, you'll just get another 429 and waste a request. Honor the header.