Rate limits
Mailbeam enforces two types of limits: monthly quotas (per-plan) and per-second rate limits (per API key).
Monthly quotas
Each plan includes a fixed number of verifications per calendar month:
| Plan | Verifications/month |
|---|---|
| Free | 1,000 |
| Starter | 10,000 |
| Growth | 50,000 |
| Pro | 200,000 |
| Scale | 1,000,000 |
| Enterprise | Custom |
Your quota resets at midnight UTC on your billing anniversary. You can check your current usage at /v1/account/usage.
Per-second rate limits
| Plan | Requests/second |
|---|---|
| Free | 5 |
| Starter | 20 |
| Growth | 50 |
| Pro | 100 |
| Scale | 500 |
| Enterprise | Custom |
Batch endpoint requests count as 1 request per batch submission, not per email in the batch.
Rate limit headers
Every response includes headers showing your current rate limit status:
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716825600
X-Quota-Limit: 50000
X-Quota-Remaining: 43218
X-Quota-Reset: 1719532800| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per second for your plan |
X-RateLimit-Remaining | Requests remaining in the current second |
X-RateLimit-Reset | Unix timestamp when the per-second window resets |
X-Quota-Limit | Monthly verification quota |
X-Quota-Remaining | Verifications remaining this month |
X-Quota-Reset | Unix timestamp when monthly quota resets |
Handling 429 responses
When you exceed the per-second rate limit, you receive a 429 Too Many Requests response:
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please slow down.",
"retry_after": 1
}The retry_after field indicates seconds to wait before retrying.
Recommended backoff strategy
Use exponential backoff with jitter for robust rate limit handling:
async function verifyWithRetry(email, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await mb.verify(email);
} catch (err) {
if (err.status === 429 && attempt < maxRetries - 1) {
const retryAfter = err.retryAfter ?? 1;
const jitter = Math.random() * 1000; // 0–1000ms
const delay = retryAfter * 1000 * Math.pow(2, attempt) + jitter;
await new Promise((r) => setTimeout(r, delay));
} else {
throw err;
}
}
}
}For bulk verification, use the batch endpoint instead of issuing individual requests in a loop. The batch endpoint automatically handles concurrency on our side.
Quota exhaustion
When your monthly quota is exhausted, requests return 429 with error: "quota_exceeded". On paid plans, overage billing kicks in automatically — you are not blocked. On the Free plan, requests are rejected until the next reset.
You receive email notifications when you reach 80% and 100% of your monthly quota.