Skip to main content

Rate Limiting

The API enforces rate limits per API key to ensure fair usage and system stability.

Default Limits

LimitDefaultDescription
Per minute60 requestsSliding window, resets continuously
Per month10,000 requestsCalendar 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/extract call 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/usage to track your consumption
  • Respect Retry-After — Always wait the indicated time before retrying