Investorlift DS
  • Getting started
  • The contract
  • Errors
  • API reference
IdempotencyRate limitsGlossaryReading a scoreThe History CallBatch scoringVersioning & deprecation
The contract

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

  1. The header is optional, and absence is never an error. A request without an Idempotency-Key is processed normally and charged per call. Nothing about the request changes except that a retry of it is a new, charged request.

  2. 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.

  3. 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-accepted instead 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.

  4. 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 502 or a 504 is 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.

  5. 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-conflict and nothing is charged for it — send the changed request with a new key.

  6. 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-flight with a Retry-After header, and nothing is charged for it. Wait the interval, ask again, and you get the stored result of the first send.

  7. Zero-cost endpoints ignore the header entirely. POST /v1/validate consumes no Credits, so there is no Spend for a key to protect — an Idempotency-Key sent 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 answers 503 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.

Last modified on September 1, 2026
Rate limits
On this page
  • The seven promises
  • What a key may contain
  • Why this API never retries for you