This guide covers EmailKit's API rate limits, error codes, and best practices for building a resilient integration.
Limit | Value |
|---|---|
Requests per second | 50 per API key |
Concurrent requests | 30 per API key |
Bulk jobs | 1 concurrent job per account |
Batch size | 100 emails per batch request |
Bulk job size | 10,000 emails per job |
Request body size | 25 MB maximum |
Rate limits are applied per API key. If you have multiple API keys, each has its own independent limits.
Every API response includes rate limit headers:
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312200Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per second |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
{
"error": "Rate limit exceeded",
"retryAfter": 1
}Recommended approach: Exponential backoff
async function verifyWithRetry(email, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch('https://api.emailkit.dev/api/v1/verify', {
method: 'POST',
headers: {
'Authorization': 'Bearer ek_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
});
if (response.status !== 429) {
return await response.json();
}
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
throw new Error('Max retries exceeded');
}Code | Meaning | Action |
|---|---|---|
400 | Bad Request | Check your request body and parameters |
401 | Unauthorized | Your API key is invalid, expired, or missing |
402 | Insufficient Credits | Buy more credits before retrying |
404 | Not Found | The requested resource doesn't exist |
413 | Payload Too Large | Reduce the size of your request (max 25 MB) |
422 | Validation Error | Check the error message for specific field issues |
429 | Rate Limited | Wait and retry with exponential backoff |
Code | Meaning | Action |
|---|---|---|
500 | Internal Server Error | Retry with exponential backoff |
502 | Bad Gateway | Retry after a few seconds |
503 | Service Unavailable | The service is temporarily down; retry later |
504 | Gateway Timeout | Retry the request |
All errors follow this structure:
{
"error": "Human-readable error message",
"code": "MACHINE_READABLE_CODE"
}To safely retry requests without duplicate charges, include an Idempotency-Key header:
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000Must be a valid UUID
Cached for 24 hours
Same key + same request = same response (no additional credit charge)
Use a unique key for each distinct verification request
Always handle errors — Don't assume every request will succeed. Check status codes and handle each error type appropriately.
Use exponential backoff — For 429 and 5xx errors, wait progressively longer between retries (1s, 2s, 4s, 8s...).
Set timeouts — Don't wait forever for a response. Set a reasonable timeout (10-15 seconds for single verification).
Use idempotency keys — Especially important for verification requests to avoid duplicate charges during retries.
Monitor your usage — Use the /credits endpoint or webhooks to track your credit balance and avoid unexpected failures.
Batch when possible — If you have multiple emails to verify, use the batch endpoint (up to 100) or bulk endpoint (up to 10,000) instead of making individual requests.
Respect rate limits proactively — Track the X-RateLimit-Remaining header and throttle your requests before hitting the limit.