Rate limits
Rate limits are enforced per API key on a sliding 60-second window, bucketed by operation type: reads, writes, and outbound calls each have their own bucket.
The baseline is 60 reads, 20 writes, and 5 outbound calls per key per minute. Limits vary by plan; higher plans get more.
Discover your limits at runtime
Do not hardcode limits. Every authenticated response includes headers that tell you your current allowance:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed in the current window. |
X-RateLimit-Remaining | Requests remaining before the limit is hit. |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets. |
Retry-After | Sent on 429 only. Seconds to wait before retrying. |
Read X-RateLimit-Limit and X-RateLimit-Remaining on each response to discover your allowance at runtime.
Handling 429 responses
When the limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header. Back off for the indicated number of seconds and retry. Use exponential backoff with jitter for retries beyond the first.
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1713590460
Retry-After: 12
{
"error": "Rate limit exceeded",
"limit": 60,
"window_seconds": 60,
"retry_after_seconds": 12
}
Example backoff loop:
async function requestWithBackoff(url, options, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const res = await fetch(url, options)
if (res.status !== 429) return res
const retryAfter = Number(res.headers.get('Retry-After')) || 1
// Retry-After first, then exponential backoff with jitter, capped at 30s
const waitSeconds = Math.min(
Math.max(retryAfter, 2 ** attempt + Math.random()),
30
)
await new Promise((r) => setTimeout(r, waitSeconds * 1000))
}
throw new Error('Rate limited after max retry attempts')
}
Need higher limits?
Contact support@autorev.ai with your use case. Enterprise customers can request custom limits or dedicated throughput.