API
Idempotency
How to retry a write safely, why a replay is not a new decision, and the one thing retrying does not buy you.
Both POST endpoints accept an Idempotency-Key header. On the decision endpoint you should always send one.
The contract
| Property | Value |
|---|---|
| Header | Idempotency-Key |
| Length | 8 to 255 characters. Use a UUID. |
| Scope | Your account. |
| Retention | 24 hours. |
| Same key, same body | The stored response is replayed, including the original decision_id, and is not billed again. |
| Same key, different body | 409, type: .../idempotency-conflict. |
A replayed response carries Idempotency-Replayed: true.
Choosing a key
Derive it from the thing the request is about, not from the attempt. For a deposit decision, a key derived from your deposit_ref means every retry of that deposit — including retries after a process restart, from a different worker — collapses onto the same stored decision.
A fresh UUID per attempt is not idempotency. It is a way to bill yourself twice and end up with two decision_id values for one deposit.
Retrying after a failure
key := stable_key_for(deposit_ref)
attempt:
response := POST /v1/decide/deposit (Idempotency-Key: key)
if response.status == 200:
act_on(response.verdict)
else:
hold(deposit) # no verdict exists
back_off_and_retry(attempt) # same key, same body
Reusing the key is what makes the retry safe: if the first attempt actually reached us and produced a decision before the connection dropped, the retry returns that same decision rather than making a second one.
What retrying does not buy you
Retrying is not a substitute for a verdict. While you are backing off, the deposit is on HOLD. Do not credit on a timer, do not credit because the retry budget ran out, and do not treat the first 2xx you happen to get as retroactive permission for the time you spent waiting.
A 409 means the key was already used with a different body. Do not resolve it by minting a new key and sending the changed body — work out why the body changed for the same deposit first.