Skip to content
Moosewave
Demo
Transactional email & API reliability

A retry is not permission to send twice.

Reliability requires retries. Trust requires one product event to remain one email, even when the network refuses to say what happened.

By Moosewave

Published · 10 min read

Several retry paths converge into one safely delivered transactional email.
Several attempts may arrive. One durable intent should produce one message record and one send.

Share this article

The short version

Retry one identity, not one side effect.

  • 01Give each logical email, one receipt, reset, or alert, one stable idempotency key before the first API request.
  • 02Reuse that key and the same payload across network retries and queue redeliveries; reject the key if the content changes.
  • 03Treat a timeout as uncertainty, not failure, and expose prepared, submitted, rejected, and unknown as different outcomes.
  • 04Keep an inspectable ledger so support and software can reconcile the original intent without manufacturing another send.

See the contract in context on the Moosewave transactional email API.

The dangerous blank between request and response

A customer asks for a password reset. Your application sends an API request. The request disappears into the network, and five seconds later your application gives up waiting. This looks like a failure because the screen has no success response. It may not be one.

The API could have rejected the request before doing any work. It could still be processing it. It could have created the message, handed it to a provider, and lost only the response on the way back. The client sees the same blank in all three cases. A second fresh request turns that blank into a second possible email.

A timeout says, “I do not know.” It does not say, “Nothing happened.”

SMTP contains a version of the same ambiguity. RFC 5321 warns that timing out while awaiting the final acceptance reply can produce multiple copies because the receiving server may already have taken responsibility for the message. The uncertainty begins before inbox placement and human attention. Our earlier field note explains why API acceptance is not inbox delivery. Idempotency solves a narrower, earlier problem: whether one application intent creates more than one send.

Give the intent an identity

The request attempt is temporary. The intent is durable. An order receipt belongs to the captured payment. A security alert belongs to the observed account event. A reset email belongs to one reset request. The idempotency key should identify that fact, not the worker, connection, or timestamp that happened to carry it.

How one transactional event keeps a stable identity
LayerStable identityWhat changes
Eventorder_8421.payment_capturedNothing across retries
API operationreceipt:order_8421:capture_1Attempt count and timing
PayloadRecipient, template, and variables fingerprintNothing for the same key
A genuinely new intentA corrected receipt explicitly requested laterA new key and an explainable relation

The client sends that value as an Idempotency-Key. The service claims it atomically, records a fingerprint of the meaningful payload, and starts the operation. A replay with the same key and content receives the original message record. Reusing the key with a different recipient, template, subject, or variables returns a conflict instead of quietly changing history.

Stripe’s API documentation provides a familiar public example of this contract: it stores the first result for a key, returns that result on later requests, and compares parameters to prevent accidental reuse. That is an example, not an email standard. RFC 9110 defines the underlying property: repeating an idempotent request has the same intended effect as making it once, while POST is not idempotent automatically.

A retry table, not a retry reflex

Retry policies often begin as one generous catch block. Any error waits briefly and tries again. This feels robust until errors with different meanings are treated as if they were interchangeable.

Transactional email API retry decisions by outcome
ResultWhat it meansNext action
Validation or authentication errorThe request is not eligible to runFix it; do not retry unchanged
Rate limit or eligible transient errorThe service asks for another attemptBack off with jitter; keep the same key
Timeout or connection lossThe outcome is unknown to the clientReconcile or replay with the same key
Recorded successThe logical send already has a recordReturn that record; never send again
Same key, changed payloadTwo intents are being confusedReturn a conflict and require a decision

Backoff controls pressure; idempotency controls side effects. You usually need both. Limit attempts, add jitter, honor explicit retry guidance, and stop when the operation’s useful time window closes. A password-reset message can become stale. An order receipt can be reconciled without hammering the API. “Retry forever” is not reliability.

Queues deliver work, not certainty

A queue creates distance between the event and the sender, which is useful. It also creates another place where work can repeat. A worker may finish the API call and crash before acknowledging its job. A visibility timeout may expire. Two workers may briefly believe they own the same message.

AWS documents standard SQS delivery as at least once and tells consumers to be idempotent because a message copy can appear again. The correct response is not to demand that every queue become magical. Carry the product event ID and idempotency key all the way to the side-effect boundary. Dedupe where the email is actually created.

  1. 01

    Create the identity with the event

    The order, account, or security service decides which logical notification now exists.

  2. 02

    Carry it through integrations and queues

    Serialisation, redelivery, and worker changes must not invent a fresh send identity.

  3. 03

    Claim it at the sending boundary

    The API stores the key and payload fingerprint before creating the external side effect.

  4. 04

    Return one record on every replay

    Every caller sees the same message identity, outcome, and trace instead of a new send.

This matters when order, payment, CRM, and account events arrive through many connected systems. The shared identity is what lets the wider Moosewave ecosystem show one coherent story instead of several plausible ones.

Unknown is a real outcome

Dashboards dislike unknown. A green status feels decisive; red feels actionable. Unknown seems unfinished, so systems often collapse it into failed and automatically send again. That cosmetic certainty is expensive when the first attempt actually crossed the provider boundary.

Keep the states separate. Prepared means the request is valid and recorded. Submittedmeans the provider acknowledged responsibility. Rejected means the attempt did not proceed. Unknown means the evidence cannot establish whether submission completed. Unknown should open a reconciliation path, not a blind resend path.

This is not timid software. It is software that preserves the difference between evidence and wishful thinking. The same discipline shapes good email deliverability measurement: request acceptance, provider submission, mailbox delivery, inbox placement, and human action are distinct facts.

Operationally, an unknown record can be checked against a provider receipt, delivery event, or later status query. A support teammate can see the history. An automated process can decide whether a new, explicitly related message is warranted. The key point is that ambiguity remains visible until new evidence resolves it.

The ledger is the reliability feature

Idempotency is often presented as one request header. The header is only the handle. The product is the record behind it.

Intent
Workspace, product event ID, message type, and idempotency key.
Payload
Recipient, template, variables, attachments, and a stable fingerprint.
Attempts
Request times, attempt count, transport errors, and backoff decisions.
Outcome
Message ID, provider receipt, suppression result, and current state.
Evidence
Webhook events, delivery updates, and the source of every transition.
Relationship
Any later correction or resend linked as a new, explicit intent.

Do not place email addresses, reset tokens, or other personal data inside the idempotency key itself. Scope keys by tenant on the server, protect access to the ledger, and decide how long records live based on realistic retry and audit needs. The controls belong alongside the tenant-isolation and access model described on the Moosewave security page.

During an email platform migration, preserve the source event IDs and retry relationships that still matter. Replaying an old queue with newly generated keys is how a clean cutover becomes a morning of duplicate receipts.

The product consequence

In Moosewave, one logical transactional message keeps one stable Idempotency-Key. A retry with the same key and content returns the original send record. Reusing that key for different content returns a conflict. Omitting it is treated as a deliberate new send because the API cannot infer which business event the caller meant.

Suppression is checked before dispatch. Batches keep one result per item, so one invalid or replayed message does not erase the identities of the others. If the provider outcome cannot be known, the attempt is recorded as unknown and is not blindly submitted again. Those choices are visible in the interactive lab on the idempotent transactional email API page.

Transactional and marketing messages have different jobs. A retry contract protects the account event; it does not turn a promotional automation into a receipt. The lifecycle automation guide explains the triggers, exits, and re-enrolment rules around longer customer journeys. Compatible tools can request work through the scoped approval model on the Moosewave MCP page, but they do not receive a shortcut around message identity.

Open the interactive product walkthrough to see how events, approvals, sending, and evidence remain connected. Reliable email is not the absence of retries. It is the ability to retry without changing what the customer experiences.

Frequently asked questions

Direct answers about email API idempotency keys, timeouts, payload changes, queue redelivery, and duplicate sends.

What is an idempotency key in an email API?

An idempotency key is a stable identifier for one logical send, such as one order receipt or one password-reset request. When the same request is retried with the same key and content, the API can return the existing send record instead of creating another email.

Can an API timeout mean the email was already sent?

Yes. A timeout proves that the client did not receive a timely answer; it does not prove that the server did nothing. The API may have accepted or submitted the message before the response was lost, which is why a retry should keep the same idempotency key.

Should changed email content reuse the same idempotency key?

No. The same key should describe the same logical operation and payload. If the recipient, template, subject, or meaningful variables change, the API should reject the mismatch. Use a new key only when the product has created a genuinely new intent to send.

How long should an email idempotency key live?

Long enough to cover every realistic client retry, queue redelivery, delayed worker, and reconciliation process for that message. The exact period is an API contract. Critical account events may need a longer deduplication horizon than a short network retry window.

Does generating a UUID make an email request idempotent?

Not by itself. A UUID can be a useful identifier, but the service must atomically associate it with the operation, compare repeated payloads, preserve the resulting state, and return the existing record on a replay. A fresh UUID on every attempt defeats the purpose.

Can a queue guarantee that a transactional email runs once?

A standard queue may deliver the same job more than once. The worker and email API still need a stable event identity and idempotent processing. The practical goal is not to pretend duplicates cannot arrive; it is to ensure repeated delivery does not create repeated side effects.

Sources & method

Protocol and reliability references

Standards and official platform documentation support the protocol and distributed-systems claims. The email API model and product recommendations are Moosewave’s synthesis.

Last reviewed 8 August 2026. API contracts and provider behavior change; verify the linked documentation for the system you operate.

Continue reading

Reliability begins with an honest state

The previous field note explains why a clear exit must become durable audience state across every sending path.

From field note to next move

Turn the question into a reviewable plan.

Give Moosewave the outcome you want. The goal carries into a guided workspace with its scope, approval points, and evidence still attached.

Journal handoffGuided workspace · no live actions
Enter to preview · Shift + Enter for a new line

Opens a guided workspace. Nothing is sent or changed.

  1. 01UnderstandQuestion and evidence
  2. 02PlanScope and exclusions
  3. 03ApproveExact proposed action
  4. 04VerifyResult and receipt
Keep one intent intact

Make every transactional send explainable.

Explore the connected product, then request Moosewave access and updates.