Developer documentation

Avoid duplicate emails with idempotency keys

How idempotency keys prevent duplicate transactional emails when a request times out or a job retries, and how to choose a key for each business event.

A request can fail in a way you cannot see: the connection drops after the API accepted your email but before you got the response. If your code retries, the customer gets two emails. An idempotency key makes the retry safe.

How it works

You send a unique key with the request. If a timeout leaves you unsure whether the email was accepted, retry with the same key to retrieve the stored email ID instead of sending another. If the same key arrives with different content, the API returns a 409 conflict, so a key can never silently attach to the wrong email. Keys are scoped to your project.

await panda.emails.send(
  {
    from: "Your app <hello@your-verified-domain.com>",
    to: ["customer@example.com"],
    subject: "Your password reset link",
    html: "<p>Reset your password.</p>",
    text: "Reset your password.",
  },
  { idempotencyKey: `password-reset-${resetRequestId}` },
);

Choosing a key

  • One key per business event. Use the ID of the thing that caused the email: an order, an invitation or a reset request, such as receipt-order-1042.
  • Reuse it when you retry the same event. A new key on every attempt defeats the purpose.
  • Do not reuse it for a different message. A second email about the same order, such as a shipping notice, needs its own key.

What the SDK does for you

The SendPanda SDK retries a POST automatically after network failures, HTTP 429 and HTTP 5xx only when you supplied a key. It never automatically retries an unkeyed send, because it cannot know whether the first attempt was accepted. If a send times out and you have no key, check the message history before submitting again.

Next steps