Skip to main content

Limits

ContextRequests/minExpensive ops/min
Authenticated60030
Unauthenticated605
“Expensive ops” include POST /extract and POST /extract/sync. All other endpoints count as standard requests.

Rate limit headers

Every API response includes rate limit information:
HeaderDescription
X-RateLimit-LimitMax requests per window
X-RateLimit-RemainingRequests remaining
X-RateLimit-ResetUnix timestamp when window resets

When rate limited

You receive a 429 response:
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please try again later.",
    "doc_url": "https://okrapdf.dev/api-reference/rate-limits"
  }
}
The Retry-After header tells you how many seconds to wait.

Best practices

  1. Check headers before hitting limits — monitor X-RateLimit-Remaining
  2. Use exponential backoff on 429 responses
  3. Batch small PDFs — prefer one large job over many small ones
  4. Use async extraction — submit jobs and poll, rather than sync endpoint for every file
  5. Cache results — store extraction results locally after fetching
import time

def respect_rate_limit(response):
    remaining = int(response.headers.get("X-RateLimit-Remaining", 1))
    if remaining <= 1:
        reset = int(response.headers.get("X-RateLimit-Reset", 0))
        wait = max(0, reset - time.time())
        time.sleep(wait)