Skip to content
Reference

Idempotency

Networks fail. A request can time out after Mailmanny already queued your email. With an Idempotency-Key you can retry as often as you like and the email still goes out once.

Send a key#

await mm.emails.send(  { from: "Manny <orders@mannysbakery.com>", to: order.email, subject: "Your receipt", react: <Receipt order={order} /> },  { idempotencyKey: `receipt-${order.id}` },);

Use a value that identifies the thing you're emailing about, like receipt-1042, or a UUID you store with the job. Keys are 1–256 printable characters without spaces, and unique per workspace.

What happens on a retry#

Same key, same email200
The original response, with the original ids. Nothing is sent again.
Same key, different email409
invalid_idempotent_request: a different recipient or subject reused the key.
First request still running409
concurrent_idempotent_requests: retry after a moment.
First request failed—
Nothing was queued, so the retry runs normally.
Response409 ConflictJSON
{  "statusCode": 409,  "name": "invalid_idempotent_request",  "message": "This Idempotency-Key was already used for a different email. Use a new key for a new email."}

Where it works#

  • POST /emails: the key covers the email to all its recipients.
  • POST /emails/batch: each email in the batch gets its own derived key. If a batch fails halfway, retrying it with the same key queues only the emails that didn't make it.
  • POST /events: an event with a key Mailmanny saw in the last 24 hours doesn't start automations again.

Contact upserts, tag edits and template pushes are naturally idempotent: repeating them leaves the same result, so they don't need a key.