# Idempotency keys

> Safely retry a send without sending twice using the Idempotency-Key header.

Network failures and timeouts make it hard to know whether a `POST /emails` actually succeeded. Pass an `Idempotency-Key` header so that retrying the same request is safe: MailBlastr processes the send **once** and replays the original response for any repeat of that key.

> **Note:** Idempotency keys are supported on both the `POST /emails` and `POST /emails/batch` endpoints.

## Using a key

Generate a unique key per logical send and send it on the request. If you have to retry, send the **same** key. A key must be between **1 and 256 characters**; a UUID is a good choice. A practical pattern is to derive the key from the entity the email is about, e.g. `welcome-user/123456789` for a single send or `team-quota/123456789` for a batch.

```bash
curl -X POST 'https://api.mailblastr.com/emails' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 8f3a9c1e-2b4d-4e6f-9a1b-c2d3e4f5a6b7' \
  -d '{
    "from": "Acme <hello@yourdomain.com>",
    "to": ["delivered@example.com"],
    "subject": "Receipt",
    "html": "<p>Thanks!</p>"
  }'
```

## Replay behavior

- **First request** — the send is processed and the response (the email `id`) is stored against the key.
- **Retry with the same key** — the stored response is replayed with its original status code. No second email is sent.
- **Concurrent retry** — if a second request with the same key arrives while the first is *still in flight*, it is rejected with `409 concurrent_idempotent_requests` rather than risking a double send.

> **Note:** Idempotency keys are scoped per account and remembered for **24 hours**. After that window the key is forgotten and reusing it processes a fresh send.

## Possible responses

A successful response returns the email `id` (replayed unchanged on a retry). Otherwise you may get one of these errors:

| Status | Error | Meaning |
| --- | --- | --- |
| `400` | `invalid_idempotency_key` | The key is outside the 1–256 character range. Retry with a valid key, or without an idempotency key. |
| `409` | `invalid_idempotent_request` | This key was already used for a request with a **different** payload. Retrying is futile until you change the key or the payload. |
| `409` | `concurrent_idempotent_requests` | Another request with the same key is still in flight. Its original response isn’t available yet — it is safe to retry later. |

> **Warning:** A key only protects against duplicate *delivery* of the same intended email. Reusing a key for a genuinely different payload returns `invalid_idempotent_request` rather than replaying — always use a fresh key for a new send.
