Rate Limiting
The API enforces rate limits per API key to ensure fair usage and system stability.
Default Limits
| Limit | Default | Description |
|---|---|---|
| Per minute | 60 requests | Sliding window, resets continuously |
| Per month | 10,000 requests | Calendar month, resets on the 1st |
Custom limits can be configured per API key.
Rate Limit Response
When you exceed your limit, the API returns 429 Too Many Requests:
{
"detail": "Rate limit exceeded. 60 requests per minute allowed."
}
The response includes a Retry-After header indicating how many seconds to wait:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Handling Rate Limits
Exponential Backoff
import time
import requests
def api_call_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 5))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
continue
return response
raise Exception("Max retries exceeded")
Node.js
async function apiCallWithRetry(url, headers, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, { headers });
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "5");
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return response;
}
throw new Error("Max retries exceeded");
}
Best Practices
- Batch documents — Send multiple files in a single
/v1/extractcall instead of one-per-request - Use webhooks — Avoid polling loops that consume your rate limit
- Cache results — Store job results locally to avoid re-fetching
- Monitor usage — Check
GET /v1/usageto track your consumption - Respect
Retry-After— Always wait the indicated time before retrying