REFERENCE
Errors & rate limits
The API uses conventional HTTP status codes and returns a structured error body. Build for failure: retry transient errors with backoff, and surface the rest clearly.
Error shape
{
"error": {
"type": "rate_limit_error",
"code": "too_many_requests",
"message": "You have exceeded your requests-per-minute limit.",
"request_id": "req_a1b2c3"
}
}Always log request_id, it lets us trace a specific call if you contact support.
Status codes
| Status | Meaning | What to do |
|---|---|---|
400 | Invalid request | Fix the payload; do not retry unchanged. |
401 | Bad or revoked key | Check the API key. |
403 | Not permitted | Key lacks scope for this action. |
404 | Not found | Check the resource or endpoint. |
429 | Rate limited | Back off and retry (see below). |
500 / 503 | Server error / overloaded | Retry with backoff. |
Rate limits
Limits are applied per key. Every response includes headers so you can pace requests:
| Header | Meaning |
|---|---|
x-ratelimit-limit | Requests allowed in the window |
x-ratelimit-remaining | Requests left in the window |
x-ratelimit-reset | Seconds until the window resets |
Retrying with backoff
Retry 429, 500 and 503 with exponential backoff and jitter. The SDK does this for you by default; here is the shape:
async function withRetry(fn, tries = 4) {
for (let i = 0; i < tries; i++) {
try {
return await fn();
} catch (err) {
if (!err.retryable || i === tries - 1) throw err;
const wait = Math.min(1000 * 2 ** i, 8000) + Math.random() * 250;
await new Promise((r) => setTimeout(r, wait));
}
}
}Idempotency: send an
Idempotency-Key header on writes so a retried request is not executed twice.