rate_limited
HTTP status: 429
What happened
An API key exceeded the request rate, or the tenant exceeded a hard send cap.
Organization creation caps return 422 organization_limit_reached with no Retry-After header.
| Plan | Live recipients per UTC day | Live recipients per UTC month |
|---|---|---|
| Free | 100 | 3 000 |
| Pro | No daily cap | 100 000 |
| Scale | No daily cap | 1 000 000 |
Tenant overrides replace the plan defaults. Zero disables sends for that period.
Test keys share a separate tenant cap of 1 000 recipients per UTC day and do not
consume live caps. Each recipient counts, including recipients in batch and
scheduled requests. Rejected requests create no email rows or usage debits.
UTC days reset at midnight; months reset at midnight on the first day.
GET /usage, with a full or read_only key, reports counts, effective limits
(null means uncapped), and reset timestamps. A read_only key can access only /usage.
Every API key and every dashboard user has a request rate of 10 requests per second
with burst capacity 20, shared across that caller's authenticated routes. The limiter
key is the API key id or the dashboard user id. Replays and rejected authenticated
requests count. X-RateLimit-* headers are returned on those authenticated customer
routes. Platform system mail is not a customer endpoint and does not use these headers.
How to fix
Wait for the integer Retry-After seconds (at least 1). The error hint names the
send cap and UTC reset, or the request rate. A 429 is not cached by idempotency;
retry with the same Idempotency-Key after the wait.
Every authenticated response, including errors and replays, carries:
X-RateLimit-Limit: request rate per second, 10.X-RateLimit-Remaining: remaining requests in the burst capacity.X-RateLimit-Reset: Unix seconds, rounded up, when the burst fully replenishes.
These headers describe request admission; GET /usage describes send caps.
On a Valkey error, request admission fails open and logs a WARN. The headers
then report capacity 20 and a reset two seconds ahead as an estimate. Postgres
send caps still enforce the hard stop. The worker send limiter in ADR-0016
remains fail closed; request admission does not spend worker tokens.
Source: docs/errors/rate_limited.md.