Rate limits

Requests are limited per API key (per IP address for unauthenticated requests). The default is 120 requests per minute; individual deployments may configure a different value. Read the rate-limit headers on every response and back off when you're throttled.

Rate-limit headers

Every response carries the current bucket state, in two families:

Response headers

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
RateLimit-Limit: 120
RateLimit-Remaining: 118

They describe one budget, not two: the IETF RateLimit-* pair mirrors the X- pair value for value. Read whichever your HTTP client already understands. The legacy X- pair stays for a deprecation window and will not be removed without an announcement in the changelog.

  • Name
    RateLimit-Limit / X-RateLimit-Limit
    Type
    integer
    Description

    The maximum number of requests allowed per minute for this key.

  • Name
    RateLimit-Remaining / X-RateLimit-Remaining
    Type
    integer
    Description

    Requests remaining in the current window. When it hits 0, further requests are rejected until the window resets.

The reset headers do not mirror

This is the one place the two families disagree, because they disagree about what a reset is. Both are sent only on a 429:

HeaderValueExample
X-RateLimit-ResetUnix timestamp of the moment the window resets1784729460
RateLimit-ResetDelta seconds until it resets, per the IETF draft17
Retry-AfterDelta seconds — the same number as RateLimit-Reset17

Do not treat the two Reset headers as interchangeable. 17 and 1784729460 are the same instant expressed two ways, and reading one as the other is the difference between waiting seventeen seconds and waiting until the heat death of your retry budget.

All of these are readable from a browser

X-Request-Id, Retry-After, both RateLimit families and Idempotent-Replayed are listed in Access-Control-Expose-Headers, so a cross-origin client can act on a rate limit and detect an idempotent replay rather than having them silently stripped by CORS.

When you exceed the limit

Over-limit requests return 429 with a Retry-After header (in seconds) and a rate_limit_error:

429 Too Many Requests

{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Slow down and retry after the interval in the Retry-After header."
  }
}

Guidance

  • Spread bulk work. Prefer one mass import over thousands of individual passport creations — it's dramatically fewer requests and far kinder to the limit.
  • Keys aren't a throughput multiplier. Each key has its own bucket, but issuing more keys to sidestep the limit isn't supported. If you consistently need more headroom, contact support.
  • Watch X-RateLimit-Remaining. Slow down proactively as it approaches 0 rather than waiting for a 429.

Was this page helpful?