Rate limits
Requests are limited per account. The default is 10 requests per second; your account's actual limit is on every response:
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1786313285
Over the limit, you get 429 and a Retry-After in seconds:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 1 seconds."
}
}
Handling it
Respect Retry-After. It is the actual number of seconds until the window
resets, so waiting exactly that long is neither too eager nor wasteful.
async function send(payload, attempt = 0) {
const res = await fetch(url, { method: "POST", headers, body: JSON.stringify(payload) });
if (res.status === 429 && attempt < 5) {
const wait = Number(res.headers.get("Retry-After") ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
return send(payload, attempt + 1);
}
return res.json();
}
Sending a lot of mail
The rate limit is on API requests, not on messages. One
POST /v1/emails/batch carries up to 100 messages and counts as one request,
so a batch is a hundredfold more throughput for the same budget.
For a list rather than a set of individual messages, use a
broadcast. One request, and the pacing is handled for you —
including batchSize, which throttles delivery so a large send does not arrive
at one mailbox provider all at once.
Raising the limit
Ask. The limit exists to keep one account from starving the others, not to sell you a bigger number, and it is raised on request when the traffic is real.