Idempotency

Retry a POST safely with an Idempotency-Key, so a send or create that may have gone through never runs twice.

When a connection drops mid-request, you cannot tell whether a send or create went through. Send the POST with an Idempotency-Key and retry with the same key: a request that already ran answers what it answered the first time instead of running again.

Send a key

Any authenticated POST to /v1 takes an Idempotency-Key header: 1 to 255 printable ASCII characters, without spaces. A UUID works well. Other methods ignore the header.

curl -X POST "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/outbox" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "Idempotency-Key: 0d0f8a52-6a7e-4b55-a1f5-0f3c2d9b7e11" \
  -H "content-type: application/json" \
  -d '{ "to": [{ "address": "ada@example.com" }], "subject": "Hi", "text": "Hello" }'

How a key is matched

  • Keys are scoped to your tenant and kept for 24 hours after the first answer.
  • The key is stored with a fingerprint of the request: its method, path, query string and body.
  • A retry with the same key and the same fingerprint gets the stored answer: the first status and body, with content-type and location, plus the header Idempotent-Replayed: true.
  • A replay's RateLimit-* headers describe the replay itself, and replays count against rate limits.

What is not stored

These answers free the key, so a retry with the same key runs the request again:

  • 5xx answers and 429s.
  • Refusals answered before the key is looked at: authentication, scopes and rate limits.
  • Answers that are not JSON (downloads), and JSON answers larger than 1 MB.

Other answers are stored, the operation's own 4xx refusals included. After fixing a refused request, retry it with a new key.

Errors

AnswerWhen
400 invalid_idempotency_keyThe key is empty, longer than 255 characters, contains a space, or is not printable ASCII.
409 idempotency_key_in_progressThe first request with this key has not been answered yet. Retry shortly.
422 idempotency_key_reusedThe key was used in the last 24 hours with another method, path, query or body.

A request whose process stops before answering holds its key for up to 10 minutes; after that the key is free again.

In the SDK

The TypeScript SDK sends a fresh Idempotency-Key with every POST and reuses it across its own automatic retries. Pass your own key, as above, to make retries across process restarts or your own timeouts answer what the first attempt did.

On this page