Skip to content

Throttling and rate-limit headers

Which routes have a limit of their own, which rate limit is attached to a key, what the four headers mean, and how a client reacts to 429.

4 minute readAPIUpdated: 10/25/2026

On this page

Before you start

For
Anyone who builds a sign-in flow or has to interpret a 429.
Prerequisite
none

Two things are throttled, for two reasons: The abuse-prone routes (sign-in, sign-in link, registration, password reset, and the round trips of provider sign-in) each carry a limit of their own, and every call with an API key also counts against a rate limit that belongs to the key. This page lists the headers, both limits, and the right reaction to 429.

The headers

Every response to which a limit applies carries the state of the window:

Header Meaning
X-RateLimit-Limit requests allowed in the window in total
X-RateLimit-Remaining of those, how many are still open
X-RateLimit-Reset the point in time at which the window starts anew, in Unix seconds
Retry-After seconds until the next permitted attempt, only when the limit is exceeded (429)

All four are readable for browser clients on other origins, as are X-Trace-Id, X-Correlation-Id, and Server-Timing.

The response when a limit is exceeded

{ "code": "RateLimit.Exceeded", "message": "Too many requests", "traceId": "trc_…" }

The status is 429, with Retry-After. A second code of the same area, RateLimit.GlobalCircuitBreaker (also 429), indicates a platform-wide overload safeguard. The reaction is the same.

The limits of the sign-in and registration routes

The limits apply per window and per counting key: “IP” counts per sender address, and “IP+email” counts per sender address and email address in the body.

Route Limit
POST /v1/auth/identify 10 per minute (IP+email) and 40 per 10 minutes (IP)
POST /v1/auth/login 5 per minute (IP+email)
POST /v1/auth/login/choose-organization 10 per minute (IP)
POST /v1/auth/mfa/verify, POST /v1/auth/mfa/recovery-code 5 per minute (IP)
POST /v1/auth/login/magic-link 5 per minute (IP+email)
POST /v1/auth/login/magic-link/consume 5 per minute (IP)
POST /v1/auth/password-reset/request 5 per minute (IP+email)
POST /v1/auth/password-reset/consume 5 per minute (IP)
POST /v1/auth/onboarding/consume 5 per minute (IP)
GET /v1/auth/login/sso/{providerId} 20 per minute (IP)
GET|POST /v1/auth/login/sso/callback 30 per minute (IP)
GET /v1/auth/login/social 60 per minute (IP)
GET /v1/auth/login/social/{provider} 20 per minute (IP)
GET|POST /v1/auth/login/social/callback 30 per minute (IP)
POST /v1/auth/login/exchange 10 per minute (IP)
POST /v1/auth/sso-recovery/consume 5 per minute (IP)
GET /v1/auth/signup 60 per minute (IP)
POST /v1/auth/signup/start 3 per 10 minutes (IP+email) and 10 per 24 hours (IP)
POST /v1/auth/signup/verify, POST /v1/auth/signup/social 10 per minute (IP)
POST /v1/auth/signup/complete, POST /v1/auth/signup/join 5 per minute (IP)
POST /v1/tenants/me/sso/{providerId}/domains/{domain}/verify 10 per minute (IP)

Further public and session-bound routes have windows of their own, for example invitation acceptance (GET|POST /v1/invitations/public/{token} and …/accept, each per IP), the analytics export (POST /v1/analytics/metrics/{metric}/export, per organization), and the VAT ID check (POST /v1/me/billing-profile/vat-id/verify, per organization). The description of the operation in the reference names the value where it names one, and otherwise the response headers show it.

The rate limit per key

A call with an ak_… key counts against a rate limit that belongs to the key, on every route, including the read routes without a limit of their own. The reason is the nature of an automated client: A person clicks, a script queries in a loop, and the cheap read routes are what knock a stack over fastest.

What Value
Default a value of the environment in the form <count>/<window>, such as 600/1m. The window is given in s, m, or h
Per key can be overridden at creation (field rateLimit in POST /v1/me/api-keys, where null means “the default of the environment”), and a rotation carries the value over
Counted per key, not per sender address and not per organization
Headers the same four as above, on every response
When exceeded 429 RateLimit.Exceeded with Retry-After

Calls from a signed-in session, devices, renderers, and operator keys are not affected: They have limits of their own. If several rules apply to a call, for example the limit of the sign-in route and the rate limit of the key, the headers show the tightest one, and the rule that was exceeded first determines the error code.

What a client does with this: Track X-RateLimit-Remaining and slow your own loop before zero is reached. An import that creates ten thousand media items finishes faster with a small pause per call than one that runs into the wall and waits.

The right reaction

Rule Why
Wait for Retry-After, then retry exactly once Every attempt before that counts toward the window and extends the lockout.
Watch X-RateLimit-Remaining and slow down before zero A client that knows the window never sees a 429.
Do not hammer Retries every second fill the window instead of emptying it.

When a call gets 429, the command line exits with code 8 (rate-limited), see JSON output and exit codes.