Rate limits
Every response tells you where you stand against the rate limit. Read the headers and back off on 429 and you'll never get surprised.
Rate-limit headers
Every response carries these headers:
Header | Meaning |
|---|---|
X-RateLimit-Limit | Your ceiling for the current window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | When the window resets. |
The standardized draft equivalents (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset) are emitted too, so a client built against either spelling works.
The current limit is 10,000 requests per minute. (This is the operating ceiling today, not a contractual floor — don't hard-code it; read X-RateLimit-Limit if you need the live value.)
When you're limited
Exceeding the limit returns 429 with a rate_limit_error:
{
"error": {
"code": "rate_limited",
"message": "Too many requests.",
"type": "rate_limit_error",
"request_id": "req_a1b2c3"
}
}The response includes a Retry-After header — the number of seconds to wait before retrying. Honor it.
Handling it well
Retry on 429 (and on 5xx) with exponential backoff, preferring the Retry-After value when present:
import time, requests
def call_with_retry(session, url, max_retries=5):
for attempt in range(max_retries):
resp = session.get(url)
if resp.status_code != 429:
return resp
wait = int(resp.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
return resp # give up after max_retriesFor large workloads, prefer the batch endpoints over a tight loop of single-email calls — submit a job and poll, rather than hammering /v1/verify. See the Quickstart and the API reference.