Retries and duplicates
Networks fail. A request can reach weneed.email and be stored while the reply is lost on the way back. Retry the right way and you get one message; retry the wrong way and the recipient gets two.
The rule
Section titled “The rule”Retry with the same key and the same content.
- API: reuse the
Idempotency-Keyand the exact request body. Keys are remembered for seven days. Reusing a key with different content is rejected. - SMTP: set
X-Email-Idempotency-Key. Without it, every submission is new, and a lost final reply can produce a duplicate.Message-IDis not used to detect duplicates.
Choosing a key
Section titled “Choosing a key”Use an ID you already have for the event: the sign-up ID, the order number plus the message type, the password-reset request ID. Store it with the event so a retry after a crash uses the same one.
Uncertain answers
Section titled “Uncertain answers”| You see | Meaning | Do |
|---|---|---|
202 / 250 |
✓Stored and queued | Nothing. Follow delivery in the history. |
No answer, timeout, 503, SMTP 451 |
?Unknown whether it was stored | Retry with the same key and content |
Permanent error (4xx API, SMTP 5xx) |
✕Not stored | Fix the request; it’s safe to send again |
weneed.email never resends on its own when a recipient’s server gives an unclear answer. That message stays unknown in the history rather than risking a duplicate.
For one-time codes, set expires_at so a delayed message isn’t delivered after it’s useless.