Idempotency & Retries
Every realtime call must carry an Idempotency-Key. It is not a rate-limit courtesy — it is what makes a retry safe. Networks fail after the supplier has already been asked; without a key, the only way to find out whether a check ran is to run it again and pay for it twice.
The rule
Section titled “The rule”Send a value you can regenerate: a UUID, an order ID, or a hash of the work you are doing. The server scopes it to your account, so two users cannot collide.
| Same key | Payload | Result |
|---|---|---|
| New key | any | Runs normally, charged |
| Same key | identical | The stored response is returned; replayed=true. No new charge. |
| Same key | different | 409 idempotency_conflict — a key is bound to the payload it first carried |
| Same key | identical, first call still running | 409 request_in_progress with Retry-After |
Idempotency-Key is limited to 191 bytes and replay records are retained for 30 days by default.
replayed is not cached
Section titled “replayed is not cached”They look similar in a response and mean different things:
| Field | Where | Means |
|---|---|---|
replayed | top level | This call never reached a supplier — you replayed a key. |
cached | inside each result | This product’s verdict was served from the result cache. |
A replayed call reproduces the original response, including each entry’s cached value. Neither flag changes what you were charged: a replay never moves money, and a cache hit is still charged at the product’s per-check price.
Only settled outcomes are stored as facts. Failed and unknown results are not cached — a later check of the same identifier against the same product will ask the supplier again rather than replaying an inconclusive answer.
Retrying after a failure
Section titled “Retrying after a failure”| What you saw | What to do |
|---|---|
| Timeout, or HTTP 500 | Resend the original body with the original key. The outcome is uncertain; this is the case the key exists for. |
409 request_in_progress | Wait Retry-After, then resend the same body with the same key. |
409 idempotency_conflict | The key already carries a different payload. Generate a new key — do not edit the body and reuse the old one. |
429 realtime_rate_limited | Wait Retry-After. Nothing was submitted, so the same key is still unused and safe to send. |
503 realtime_route_unavailable | Nothing was submitted. Retry later, same key. |
The one thing never to do after a timeout is to submit a new key with the same work: if the first call did land, you have just paid for the check twice.
Errors raised here
Section titled “Errors raised here”| HTTP | code |
|---|---|
| 400 | idempotency_key_required — header missing |
| 409 | request_in_progress — the original call is still running |
| 409 | idempotency_conflict — the key was first used with a different payload |