Idempotency

Retry requests safely: an Idempotency-Key makes sure the same email is never sent twice.

Networks fail. If your server sends a request and the connection drops before the response arrives, you cannot tell whether the email was accepted. Send an Idempotency-Key header and you can retry without risk: Cresca returns the first result instead of sending again.

Request
curl -X POST 'https://api.cresca.xyz/api/v1/emails' \
  -H 'Authorization: Bearer cr_live_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-confirmation/order-1042' \
  -d '{
  "from": "Acme <orders@acme.com>",
  "to": "user@example.com",
  "subject": "Your order #1042 is confirmed",
  "html": "<p>Thanks for your order.</p>"
}'

Rules

SituationResult
Same key, same body, within 24 hoursThe original response, with the header idempotent-replayed: true. Nothing is sent again.
Same key, different body409 invalid_idempotent_request
Same key while the first request is still running409 concurrent_idempotent_requests. Retry shortly.
The first request failed (any error)The key is released, so the retry is processed normally.
More than 24 hours laterThe key has expired and the request is treated as new.

Keys are 1 to 256 characters and are scoped to your account. A key outside that length gets 400 invalid_idempotency_key. Keys work on POST /emails and POST /emails/batch; for a batch, one key covers the whole request.

Choosing keys

Derive the key from the event that caused the email, not from the time or a fresh random value, so every retry produces the same key. A good pattern is <event>/<id>:

  • welcome/user-123
  • password-reset/reset-request-9f2c
  • invoice/inv-2026-0042

A new password-reset request is a new event: give it a new id, so a person who asks twice gets two emails.

When to retry

Retry on network errors, timeouts, 429 and 5xx responses, with exponential backoff (for example 1s, 2s, 4s, 8s) plus a little random jitter. Do not retry other 4xx responses: fix the request first. See Errors.