Skip to main content
Required permission: Sending → Write (messages:send) Sending is a separate permission from everything else. messages:write lets a key file and star mail that already exists; it does not let it send. Mail sent here leaves under your domain’s reputation and spends your plan’s daily allowance, so granting it is a deliberate choice.

Request

Address fields accept either an array or a comma-separated string. Both are common in the wild and neither is wrong.
from must be a mailbox, not an alias. Aliases are sendable in the web app but are not accepted here yet — an alias is refused rather than quietly sent as its owner. Use an address from GET /v1/mailboxes.Private mailboxes cannot send through the API at all: the message would have to be encrypted with a key only the owner’s browser holds.

Attachments

Each entry is filename, base64 content, and an optional content_type (defaults to application/octet-stream).
At most 10 attachments totalling 8 MB decoded. The ceiling leaves headroom under SES’s ~10 MB message limit once MIME encoding is added — base64 inflates content by roughly a third, and that inflation happens after this check.

Response

202 Accepted. The message has been handed to the mail server, which is not the same as delivered — remote servers accept and bounce on their own schedule.
A recipient in rejected was refused by the mail server outright — usually a malformed address. Recipients in accepted were taken for delivery. A copy is filed in the Sent folder automatically. If that filing fails the send still reports success: the message has already gone, and reporting failure would invite you to send it twice.

Limits

Sending passes several ceilings, and they fail differently: The per-mailbox limits are the ones that decide whether a leaked key can burn your domain’s reputation before you notice, so an API key does not get a more generous version of them than the web app has. The daily allowance is the entitlement your plan sells, and it is shared: messages sent from the dashboard and through the API draw on the same counter. rate_limited carries a Retry-After header. quota_exceeded does not — the allowance resets at midnight UTC.

Errors

See Errors for the full response shape.