Troubleshooting
Why are my emails sent twice?
Find out where duplicate emails come from and stop them with the Idempotency-Key header, which makes retried API requests safe.
This article helps when recipients get the same email two or more times. Emailit sends each accepted request once, so duplicates almost always mean the request reached Emailit more than once.
Symptoms
- A recipient reports two identical emails.
- Email APIEmails shows two or more emails with the same recipient and subject, each with its own
em_…ID, created seconds or minutes apart. - Email APILogs shows more than one
POST /v2/emailsrequest for the same message.
Cause
Common sources of repeated requests:
- Retries after a timeout. Your HTTP client or job queue timed out and retried, but the first request had already been accepted.
- At-least-once job queues. A worker crashed after sending but before marking the job done, so the job ran again.
- Webhook-driven sends. Your endpoint sends an email when it receives an event. If it answered slowly, Emailit retried the webhook and your code sent again.
- Two integrations. For example, a WordPress SMTP plugin and your app both send the same notification, or an automation and your code both send a welcome email.
- Double submits from a form or button.
Emailit already removes duplicate addresses inside one request, case-insensitively, across to, cc and bcc. A single request never sends twice to the same person.
Fix
-
Find the source. In Email APIEmails, filter by the recipient and compare the duplicates. Check the API key and timestamps, then match them to requests in Email APILogs. Requests from different keys usually point to two integrations. Requests from the same key point to retries.
-
Add an
Idempotency-Keyheader. Generate a key once per logical email, for example from your order or event ID, and reuse it on every retry:curl https://api.emailit.com/v2/emails \ -H "Authorization: Bearer $EMAILIT_API_KEY" \ -H "Idempotency-Key: order-1042-receipt" \ -H "Content-Type: application/json" \ -d '{"from":"Acme <hello@acme.com>","to":"ada@example.com","subject":"Your receipt","html":"<p>Thanks!</p>"}'Keys are 1 to 256 characters of letters, digits,
-and_, and are scoped to your workspace. -
Handle the replies. For 24 hours, a repeat with the same key returns the original response without sending or charging again. A repeat that arrives while the first is still running gets
409 Idempotency key in progress: wait and retry with the same key. Failed requests aren’t stored, so you can retry them with the same key. -
Deduplicate webhook handlers. Store each
event_idyou process and skip events you’ve already handled. -
Remove the second integration. Make sure only one system sends each type of message.
Idempotency keys work on Send an email and Forward an email. SMTP has no equivalent, so deduplicate in your app before handing mail to the relay. Read Idempotency for details.
Still stuck?
Contact support or ask in Discord with the IDs of two duplicate emails.