Idempotency is opt-in and currently applies to
POST /v1/messages. Send the header and you get the protection; omit it and the endpoint behaves normally.Using it
Pick a key that’s unique to the thing you’re doing, not to the attempt. Then send the same key on every retry of that same send.order-8842-shipped, which has the nice property that you can reconstruct it later without storing it.
What happens on a replay
When a key you’ve already completed comes back, Paige returns the original stored response, byte for byte, and adds:Two conflicts to handle
Both are409.
idempotency_in_progress
idempotency_in_progress
The first request with this key is still running. This is exactly what you want to happen when a retry fires before the original finished — the duplicate is refused rather than racing it.Wait a moment and retry with the same key. You’ll then get the completed response as a replay.
idempotency_key_mismatch
idempotency_key_mismatch
This key was already used with a different request body. Paige fingerprints each request, so reusing a key for different content is treated as a bug rather than silently returning the wrong stored answer.Either you reused a key you shouldn’t have, or your code changed the message between attempts. Use a fresh key for genuinely new content.
400 invalid_idempotency_key.
How the fingerprint works
The fingerprint covers the request method, path, and body. Object keys are sorted before hashing, so serialising your JSON with keys in a different order does not trip a mismatch. Array order does matter — reordering a list is a different request.What gets stored
That last row is the important one. A
500 is exactly the case where you want a retry to try again, so it’s deliberately not cached.
A pattern that works
1
Derive the key from the event, not the attempt
order-8842-shipped, booking-991-reminder. One real-world event, one key.2
Reuse it for every retry of that event
Same key, same body, however many attempts it takes.
3
Retry only 5xx, timeouts, and rate limits
A
400 won’t fix itself. See Errors.4
Treat 409 in-progress as retryable
Wait briefly, then retry with the same key.
