Skip to content
On this site

Idempotency

A network timeout does not tell you whether the request arrived. An idempotency key makes it safe to find out by asking again.

How to use it

Send an Idempotency-Key header on POST /emails and POST /emails/batch. Choose the value from something that identifies the work, not the attempt — an order ID, a job ID, a UUID you generate once and reuse across retries.

Idempotency-Key: order-1042
  • 1256 characters.
  • Scoped to your team, so two teams may use the same string without colliding.
  • Remembered for 24 hours, counted from the first request.

Generating a fresh key on each retry defeats the mechanism entirely — that is the one mistake worth guarding against. The key must be the same string every time you retry the same send.

What happens on a repeat

Idempotent request outcomes
SituationStatusAnswer
Same key, same payload, first request still running409concurrent_idempotent_requests
Same key, same payload, first request finished200The original response, with Idempotent-Replayed: true
Same key, different payload409invalid_idempotent_request
A key shorter than 1 or longer than 256 characters400invalid_idempotency_key

The payload is compared by fingerprint, so a reordered JSON object is still the same payload. A genuinely different body under a key you have already used is refused rather than sent: two different emails under one key is a bug, and we would rather surface it than pick one.

Batches

One Idempotency-Key covers a whole batch, not each message inside it. Retrying the batch replays the whole batch; there is no partial replay.

Everything else

Only the two send endpoints take the header. GET and DELETE are naturally idempotent — repeating them changes nothing — and the remaining writes are either keyed by a resource you name or are safe to repeat.