API reference / Rate limits & quotas

Rate limits & quotas

Two independent limits apply to /v1/generate: a monthly quota (how many documents you can generate per calendar month) and a per-minute rate limit (how fast you can send requests). They exist for different reasons and return different errors.

Limits by plan

PlanMonthly quotaRequests / min
Free505
Starter1,00030
Pro5,000120
Scale25,000300

(Plans also differ on active API keys and history retention. See Plans & limits.)

Monthly quota — limit_exceeded (429)

Each plan has a monthly generation quota, counted per calendar month in UTC (a period looks like 2026-06). When you reach it, further calls return limit_exceeded (429) until the next month begins. The fix is to upgrade or wait for the reset.

Only successful generations count toward the quota. A failed call never does.

Request rate — rate_limited (429)

Each document is a full browser render, so there is also a short-term cap on how many requests per minute you may send. Bursting past it returns rate_limited (429) with a Retry-After header telling you how long to wait. This is "slow down", not "you are out of quota".

Both limits use HTTP 429, but the code distinguishes them: rate_limited means wait a moment and retry; limit_exceeded means you have hit your monthly allowance. Always branch on code, not the status alone.

Capacity — service_unavailable (503)

If the render engine is momentarily saturated, a request can be shed with service_unavailable (503) rather than queued indefinitely. This is transient: retry after a short, backed-off delay.

Accounting guarantee

The successful generation and its usage increment are written in a single transaction, so your usage figure can never disagree with what actually rendered, and a failed render leaves the counter untouched.

Retrying safely

There is no idempotency key today, but you do not need one to retry safely: a request either returns the PDF bytes or fails without producing a document or consuming quota. So:

  • Retry the transient failures with exponential backoff: rate_limited (wait at least the Retry-After value), service_unavailable, and usually internal_error.
  • Do not retry request errors (invalid_json, invalid_data, template_not_found, template_not_published): fix the request first, or you will just fail again.
  • A successful retry generates a new document (and counts once). If you trigger generation from a user action, guard against double-submits on your side.

A reasonable policy: up to ~3 retries, starting around 1s and doubling, capped at a few seconds, and never retrying a 4xx that is your request's fault. See Errors for the per-code guidance.