Idempotency and retries
Recover a completed decision without repeating inference or its charge.
Send a key for each logical operation
The client must supply Idempotency-Key. SDK 0.3.0 does not create one automatically. A UUID is suitable. A key is 1–128 characters, starts with a letter or digit, and then allows letters, digits, dots, underscores, colons, and hyphens.
Keep the key with the operation before sending it. Reuse it after a lost response or connection timeout. A newly generated key means a new billable operation.
const operationKey = crypto.randomUUID();
const result = await client.evaluate(request, {
maxRetries: 0,
timeoutMs: 30_000,
headers: { 'Idempotency-Key': operationKey },
});request and client here are the request object and configured client from the quickstart. Reconstruct the same request and reuse operationKey when recovering that operation.
Scope and comparison
A key is scoped to an account, across its API keys and session playground. Other accounts have separate key namespaces. Revocation still applies: a revoked API key cannot authenticate a replay.
The platform compares the validated canonical request, including every extension field. Object key order and formatting whitespace do not change the hash; array order, question content, state values, null versus omitted fields, and scoring rubric order do. An omitted model is resolved to the deployment default (otherwise jev-latest) before hashing; explicit aliases and versions remain unchanged. Reuse the same effective model when recovering. A different canonical body returns 409 idempotency_conflict.
The original request text can therefore differ in whitespace without changing the logical operation. Decimal identity preserves high-precision distinctions: 9007199254740993 must not share a hash with 9007199254740992, nor 1e-400 with zero. Equivalent decimal spellings canonicalize together, and duplicate keys are rejected. Native success fidelity compares a gateway response to the upstream response from that same call, not two independent model evaluations. The raw user idempotency key is never forwarded to the shared upstream operator account.
State transitions
| Existing operation | Response to the same key and body | Client action |
|---|---|---|
| No retained operation | A new inference can begin and reserve credits. | Track this key until the outcome is known. |
| Pending | 409 request_in_progress, Retry-After: 2. | Wait, then retry the same key and body. |
| Succeeded | Original status, response text and allowed headers, with X-Idempotency-Replayed: true; no new inference or debit. | Use the recovered answer. |
| Failed and refunded | 409 idempotency_failed. | Use a new key only for a deliberate new attempt. |
| Different canonical body | 409 idempotency_conflict. | Restore the original body or assign a new key to a different operation. |
| Replay record without an answer | 410 idempotency_expired. | Reconcile the old operation before starting a new one. |
A new-format successful replay returns the original platform ID in X-Request-Id, the original upstream tracking IDs, X-Idempotency-Replayed: true, and X-System-One-Credits: 0. Its cached body is unchanged and receives no new replayed, billing or request_id. Any such fields already present belong to the provider, not platform accounting. The account rate limit still applies to replay attempts.
Cache upgrade and response modes
New cache records store a versioned envelope containing the response's text, status and allowed headers in the existing response_json column. The envelope is internal storage, not the public response body. typesafe-native preserves the original TypeSafe text; openrouter-adapted replays the saved adapted response without claiming native TypeSafe byte fidelity.
Pre-upgrade unversioned records cannot recover the original upstream text. They are served as X-System-One-Response-Mode: legacy-cache without a new inference or debit. Old platform billing, request_id and replayed body additions are removed; previously synthesized rounding and warnings cannot reliably be distinguished from provider fields and may remain. These caches expire on the same 24-hour schedule. No database schema or account/ledger migration is needed.
Retention and failures
Completed operation keys and cached answers are retained for 24 hours from request creation. After expiration, a key can start a new operation; there is no lifetime deduplication guarantee. The cleanup job also clears old replay data. Without an idempotency key, no answer is cached and a repeat request is a separate inference.
An ordinary inference failure refunds the reservation before returning its error. A crash may leave a pending reservation. Reservations older than 15 minutes become eligible for reconciliation by the cleanup job, scheduled every 15 minutes; recovery is not immediate. Keep the original key and request ID while the outcome remains uncertain.
503 request_reconciliation_pending means that immediate credit reconciliation did not complete. X-System-One-Credits is omitted because the charge is unsettled; a missing header is not a zero charge. Do not assume a new attempt is free or reuse a new key blindly. Keep X-Request-Id, check usage, and let the deployment operator investigate if reconciliation does not complete.
SDK retries
The SDK’s default retry policy can retry network errors and selected HTTP failures; it does not automatically handle the platform’s 409 states. The examples set maxRetries: 0 so the application can follow the table above. Enabling SDK retries does not create an idempotency key: always supply and retain one. The Worker itself does not retry upstream inference.
The raw HTTP classification headers differ from SDK error classes. Project SDK 0.3.0 APIError exposes status, request ID and retry delay, not the full body or classification headers. Use raw Fetch to distinguish the 409 codes through X-System-One-Error-Code. Upstream errors keep their original status and valid JSON except for documented safety replacements; check Error-Source rather than treating every 401 as an expired platform session. The official client's separate retry configuration also needs an explicit retained key.