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