Idempotency
Send an Idempotency-Key header on POST /v1/predict and a retry can never charge
you twice. This page is the whole contract — each statement below is a promise.
The seven promises
-
The header is optional, and absence is never an error. A request without an
Idempotency-Keyis processed normally and charged per call. Nothing about the request changes except that a retry of it is a new, charged request. -
Keys are scoped to your Account. One Account can never replay another Account's result, whatever key it sends. Two Accounts using the same key value never touch each other.
-
The replay window is 24 hours. Send the same request with the same key inside the window and you receive the stored response — one Spend, however many sends. After 24 hours the stored response expires, and a repeat is a new, charged request. One carve-out: if the Terms of Service have changed materially since your Account last accepted them, a send inside the window is refused with
403 terms-not-acceptedinstead of replaying, and nothing is charged for it. The consent check runs before the key is looked at at all, so accepting the current Terms restores the replay. -
Only successful responses are stored. A failed request — one that was refunded — is not stored against its key. So retrying the same key after a
502or a504is a genuine fresh attempt: it spends again, and it can succeed. This is what makes retry-after-a-5xx work; a stored failure would replay the failure. -
A key is replayed only when the earlier call succeeded and its response was stored. If the earlier call was refunded, ended without a stored response, or is older than the replay window, the key is taken over: the new request runs and is charged, whatever body it carries. Otherwise the same key sent with a different body is refused as
422 idempotency-key-conflictand nothing is charged for it — send the changed request with a new key. -
An identical request already in flight is answered, not raced. While the first send is still being processed, an identical second send receives
409 duplicate-request-in-flightwith aRetry-Afterheader, and nothing is charged for it. Wait the interval, ask again, and you get the stored result of the first send. -
Zero-cost endpoints ignore the header entirely.
POST /v1/validateconsumes no Credits, so there is no Spend for a key to protect — anIdempotency-Keysent to it is ignored. With an API Key it makes no Ledger call at all and keeps working at a zero Balance; a connected app that signed you in instead of holding a key makes one Ledger read there to confirm the connection is still approved, so while that read is failing it answers503 call-not-started. Nothing is charged either way.
What a key may contain
Any string you like, within three limits: 255 characters or fewer, no control
characters (tab, carriage return and line feed included), and not blank — a header
sent empty, or holding only whitespace, is not a key. A header that breaks any of the
three is refused before anything is spent, as
400 invalid-request; that error's wording is about the
request schema, but the header is what to correct. A key that passes is taken exactly as
sent and never trimmed, so surrounding spaces make two otherwise identical keys
different.
Why this API never retries for you
No request is ever retried on our side. A Metered Call can consume a Credit before it
fails, so a gateway that re-issued requests on its own could charge twice for one
intent. Retry belongs to you, and the Idempotency-Key is what makes it safe.