Skip to content

Limits

Where a limit exists for a non-obvious reason, the reason is written down. Guessing at a cap is how you discover it in production.

Message size

LimitValueWhy
Attachments per message10 MB totalIsolate memory, see below
Attachment count20Practical
Total message40 MBUpstream provider ceiling
Subject998 charactersRFC 5322 line length
Custom headers20, 2 KB eachReceiver tolerance

Why 10 MB and not 40

Attachments arrive base64-encoded inside a JSON body, which inflates them by a third. That body becomes a UTF-16 string when parsed, doubling it again, and is copied once more while the message is assembled. Ten megabytes of attachment is therefore already sixty to eighty megabytes of peak memory in a request isolate capped at 128 MB.

Raising this needs a streaming upload path, not a larger constant. For anything bigger, host the file and send a link — recipients’ mail servers frequently reject large attachments anyway.

Recipients

LimitValue
Recipients per message (to + cc + bcc)50
Messages per batch request100
Scheduled delivery horizon30 days

Transactional only

Fifty recipients is a limit, not a target. This is a transactional API: mail triggered by a user action, addressed to one person. Fan-out to a list is a campaign, it will be detected as one, and it will get your organization paused.

Send limits

There are two, and a send has to satisfy both: a daily limit that resets at 00:00 UTC, and a monthly limit that resets on the 1st. New organizations start at 100 per day and 3,000 per month.

Both are counted in recipients, not messages. One send to fifty people costs fifty, because that is what it costs in reputation and in money. A request that would cross either line is refused whole and consumes nothing — you never end up with half a batch sent.

The month exists because a daily cap alone bounds very little: an account can spend it every single day, so the real ceiling on a leaked key was thirty times the number anyone approved. Exceeding the day returns daily_quota_exceeded, the month monthly_quota_exceeded, both with a 429.

Limits are raised as you accumulate history with a bounce rate under 2% and a complaint rate under 0.1%.

Idempotency

Idempotency-Key is remembered for 24 hours, scoped to your organization, and at most 255 characters. The request body is hashed alongside it: reusing a key with different content returns 409 rather than replaying the first response, because silently discarding the second email would be worse than an error.

Webhooks

LimitValue
Delivery timeout10 seconds
Retry schedule1m, 5m, 30m, 2h, 6h, 24h
Auto-disable threshold20 consecutive failures
Signature tolerance5 minutes

A 4xx other than 429 ends the retry ladder immediately: your endpoint understood the request and refused it, so repeating it for a day helps nobody.