> ## Documentation Index
> Fetch the complete documentation index at: https://jetemail.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Idempotency Keys

> Make transactional send retries safe

# Idempotency Keys

Network errors, timeouts, and worker restarts can leave your code unsure whether a `POST /email` request actually went through. Sending an `Idempotency-Key` header lets you retry safely: a repeat with the same key and body replays the original response instead of sending a duplicate email.

<Warning>
  Idempotency keys are currently scoped **per region**. A retry that lands in a different region than the original request will not see the prior key and may produce a duplicate send. We are working on a global key store that will apply idempotency across all regions at once.
</Warning>

## How it works

1. Generate a unique key on your side (e.g. a UUID v4) for each logical send.
2. Pass it in the `Idempotency-Key` HTTP header on [`POST /email`](/api-reference/email/send-an-email).
3. If the request is retried with the **same key and same body**, JetEmail returns the original response and does not send a second email.
4. If the same key is reused with a **different body**, the request is rejected with `409 Conflict`.

## Header reference

| Header            | Required | Notes                                   |
| ----------------- | -------- | --------------------------------------- |
| `Idempotency-Key` | No       | Opaque string, **1 to 256 characters**. |

Keys are scoped to your account. Pick something globally unique per send (UUID v4 is a safe default).

## Example request

```bash theme={null}
curl -X POST https://api.jetemail.com/email \
  -H "Authorization: Bearer transactional_xxxxxxxxxxxxx" \
  -H "Idempotency-Key: 7c3a9e2a-1f3b-4d6e-9c2a-9e2a1f3b4d6e" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Your App <hello@yourdomain.com>",
    "to": "user@example.com",
    "subject": "Welcome!",
    "html": "<h1>Welcome!</h1>"
  }'
```

Retrying the exact same call with the same `Idempotency-Key` and body will return the original `201 Created` (or `202 Accepted` for scheduled sends) without triggering another delivery.

## Conflict responses

A `409 Conflict` indicates one of two situations:

| Error code                  | Meaning                                                                 |
| --------------------------- | ----------------------------------------------------------------------- |
| `IDEMPOTENCY_IN_FLIGHT`     | A request with this key is still being processed. Retry shortly.        |
| `IDEMPOTENCY_BODY_MISMATCH` | This key was already used with a different request body. Use a new key. |

If you legitimately need to send a different message, generate a new `Idempotency-Key`.

## Best practices

* **Generate the key before the first attempt**, not on retry, so retries can reuse it.
* **Persist the key** alongside the work item that triggered the send (e.g. order ID, job row) so the same retry path always reaches for the same key.
* **One key per logical send.** Do not reuse the same key for unrelated emails.
* **Pair with [scheduled sends](/transactional-email/scheduled-email)** when the call that schedules an email may itself be retried.
