Rate limits

.md

Limits are per key, not per IP, and every response tells you where you stand.

Every response carries your current standing:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1754231400

Limits are counted per API key. Requests that never resolved a key are limited per IP address at a much tighter rate, which is what a key-guessing loop runs into.

TierRequests per minute
Standard300
Elevated1200
Unauthenticated60

Contact us if your integration needs the elevated tier.

Signing in as a person

The app endpoints count separately, because the thing being protected is different: a sign-in attempt is worth guessing at, and an open inbox polls.

WhatLimit
A signed-in device600 requests a minute, per device
Resolving an environment30 a minute, per address
Signing in10 attempts per 10 minutes per address, and 5 per email
Answering a two-factor challenge20 per 10 minutes per address, and 10 per challenge

The per-device limit means one person hammering their inbox never slows down a colleague on the same office connection. A two-factor challenge is also spent after five wrong codes regardless of the limit above.

When you go over

You get 429 with rate_limit_exceeded and a Retry-After header in seconds:

{
    "error": {
        "type": "rate_limit_error",
        "code": "rate_limit_exceeded",
        "message": "Too many requests. Slow down and retry after the window resets.",
        "request_id": "req_01kz4bkr1aj1gv63d8fv3133ey"
    }
}

Back off, do not hammer

Wait at least Retry-After seconds, then retry with exponential backoff. Retrying immediately in a loop only keeps you rate limited for longer.

Because limits are per key rather than per IP, one noisy integration cannot throttle a different firm that happens to share an outbound address.