Theme

Resend API notes

What the Resend adapter does under the hood — the endpoints, the limits, the quirks worth knowing, and the capabilities it declares.

Capabilities

CapabilityValueConsequence
custom_headerstrueOur headers are passed through.
injects_unsubscribe_headersfalseNothing is auto-injected, so the RFC 8058 headers are entirely ours.
send_time_suppressiontrueSilent, region-wide drops for bounces and complaints.
suppression_read:noneNo API at all. The nightly suppression sync doesn't run.
suppression_webhookstrueThe only route for Resend-side suppression.
engagement_webhooksfalsePer-domain tracking stays off — tracking is ours.
push_unsubscribefalseNo write API. The standing guard covers it.
remote_deletefalseGDPR erase can't remove the address Resend-side.

Sending

CaseEndpoint
One messagePOST /emails
More than onePOST /emails/batch, chunked at 100

Rate limit: 10 requests/second, team-wide. The adapter declares emails_per_minute: 600, and the sender's pacer counts every send against that budget — one message per request through the queue, so 600 a minute is the honest ceiling. The account-wide maximum (sending.max_emails_per_minute, 300 by default) applies on top: the effective pace is whichever of the two is lower.

Headers

"headers": {
  "List-Unsubscribe": "<https://your-mimeo.com/u/SIGNED_TOKEN>",
  "List-Unsubscribe-Post": "List-Unsubscribe=One-Click"
}

Resend injects nothing, so these are ours. The token is the same signed token the subscription page takes, which is what attributes a header unsubscribe to the exact email it came from. Both halves matter: without List-Unsubscribe-Post, a mail client shows a link rather than its own unsubscribe button.

Transactional mail carries no unsubscribe header. You can't opt out of your own password reset.

Webhooks

Resend eventNormalizes to
email.delivereddelivered
email.bouncedbounced
email.complainedcomplained
email.suppressedsuppressed
anything elseacknowledged and ignored

A bounce's type maps to our bounce kind: Permanent → hard (suppresses the person), Transient → soft (doesn't — a full mailbox is a try-again, not a dead address).

Signed with Svix: HMAC-SHA256 over svix-id.svix-timestamp.body, base64, compared in constant time, with a five-minute freshness window so a captured request can't be replayed tomorrow. Multiple v1,… signatures are accepted so a secret can be rotated without dropping anything mid-flight. See Webhooks for the shared contract.

Quirks

Credentials

SettingWhat
provider.resend.api_keyThe API key.
provider.resend.webhook_secretThe Svix signing secret, whsec_….

Both are entered on the Settings page and encrypted in your Mimeo's database, and neither ever appears in a manager repo.

verify_config calls GET /domains and fails when no domain is verified, naming the ones still pending — reporting a good connection that would refuse every send isn't a verification.

See also: Resend setup · Webhooks · Write your own adapter