Rate limits & quotas
How many requests you can send per minute on each plan, what happens over the limit, the size limits of each call, and how to pace a large job.
Requests per minute
The Emelia API counts the requests of your account over a 60 second window. All the API keys of an account share the same counter.
| Plan | Requests per minute |
|---|---|
| No active plan | 30 |
| Start | 100 |
| Grow | 300 |
| Scale | 1,000 |
The window is fixed, not sliding: it starts with your first request and lasts 60 seconds, then a new window starts with the next request.
What does not count:
- The enrichment routes under
/tools/...(Email Finder, Phone Finder, Email Verifier, and the polling of their results). - The lists and contacts routes under
/lists/....
The MCP server relays your key to this API: its tools count like direct calls, under the same rules.
Over the limit: HTTP 500, not 429
Today, a request over the limit gets an HTTP 500 with this body, and no Retry-After header:
{ "error": "Internal server error" }That is the current behaviour, not the usual 429. Here is how to handle it:
- Recognise it. A
500with exactly{"error": "Internal server error"}during a burst of requests is almost always the quota. - Wait for the next window. Pause for 60 seconds, then resume at a slower pace. Retrying at once only fails again.
- Retry safely. Retry
GETrequests freely. Before retrying aPOST, check that the first call did not go through (for example, look for the contact you were adding): the quota is checked before the request runs, but a real server error looks the same.
/advanced/campaigns
# Retry once after the window when the quota is hit
status=$(curl -s -o response.json -w "%{http_code}" https://api.emelia.io/advanced/campaigns \
-H "Authorization: $EMELIA_API_KEY")
if [ "$status" = "500" ]; then
sleep 60
curl -s https://api.emelia.io/advanced/campaigns -H "Authorization: $EMELIA_API_KEY"
else
cat response.json
fiSize limits
| What | Limit |
|---|---|
| Request body, main API | 30 MB |
Request body, lists and contacts (/lists/...) | 5 MB, then 413 with "code": "PAYLOAD_TOO_LARGE" |
| Contacts per batch call (Add contacts in bulk) | 1 to 100, 422 otherwise |
Lists per page (GET /lists/list) | 25 by default, 100 at most |
Contacts per page (GET /lists/list/{listId}/rows) | 50 by default, 100 at most |
| Exact lookup of a contact by email or LinkedIn URL | 50 results, no pagination |
| Campaign attachments | 3 files of 20 MB |
| LinkedIn voice note | 10 MB and 5 minutes |
| Duration of a request | 120 seconds |
Campaign quotas
These limits belong to each campaign, in its settings (Update campaign settings):
| Setting | Range |
|---|---|
dailyEmailAdded, new contacts entering the email sequence per day | 1 to 500 |
dailyEmailLimit, emails sent per day, follow-ups included | 1 to 500, and at least dailyEmailAdded |
dailyLinkedinAdded, new contacts entering the LinkedIn sequence per day | 1 to 80, and 40 at most when the sequence sends invitations |
dailyWhatsappAdded, new contacts entering the WhatsApp sequence per day | 1 to 30 |
A campaign starts with 30,000 recipients at most. Above it, the start fails with the error code TOO_MANY_RECIPIENTS.
Pacing a large job
- Batch first. Loading 1,000 contacts is 10 batch calls of 100, not 1,000 single calls.
- Spread the calls. On Start, keep a steady rhythm under 100 requests per minute rather than bursts.
- Never retry an enrichment blindly. A retried
POST /tools/find/emailstarts a second search and is billed twice. Poll thejobIdyou already have. See Enrichment. - On an error in the middle of a batch, resume from the failed row instead of restarting: the rows already loaded come back as duplicates.