Recover tasks with idempotency
Guide
Use the Task model for lifecycle states and result fields.
Idempotency
Section titled “Idempotency”Any paid create endpoint accepts an Idempotency-Key header. Reusing the
same key for the same request replays the
original response instead of creating — and charging for — a second task. Send
a fresh value of at most 255 characters per logical operation, and reuse it
when you retry after a network timeout. If the original request is still
running or its response is still being finalized, a concurrent same-body
retry returns 409 CONFLICT; error.details.taskId, when present, identifies
the already-created task to poll. Retry the same request and key shortly after
the first request finishes. Reusing a key with a different request body also
returns 409 CONFLICT and must be corrected rather than retried:
Keys are scoped to your customer account and the operation. Rotating an API key within that account does not make an uncertain write a new operation. Modern and Legacy routes have separate namespaces: never fail over an uncertain write between them. Save the original route, request body, key, and task receipt.
No fixed key-expiry interval is published. Do not reuse a key after an assumed expiry; use a new unique key for every new logical operation. The retry guarantee is not an archival lookup service: store the task ID and your own job record.
| Situation | Next step |
|---|---|
| HTTP/connection outcome unknown | Retry the original route and body with the saved key; never infer absence from a missing response |
| 409 with taskId | Read that task; it may already have charged or completed |
| 409 without taskId, same body | Back off and retry with the same key; contact support with X-Request-Id if it persists |
| 409 because the body differs | Restore the original body to recover it; a genuinely new operation needs a new key |
| Terminal failure with retryable=true | Inspect settlement; a deliberate new attempt uses a new key |
For each new logical operation, set and save a fresh REQUEST_KEY once.
Reuse it with the exact same route and body only when recovering that operation.
Use a different saved key when trying a different example or export format.
export REQUEST_KEY="$(uuidgen)"curl -X POST https://api.omnapi.com/api/v1/producer/generate/image \ -H "x-api-key: sk_live_..." \ -H "Idempotency-Key: $REQUEST_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "..." }'Timeouts
Section titled “Timeouts”There is no single platform-wide ten-minute task timeout. Each feature has a
hard delivery deadline derived from its runtime policy; that deadline is
separate from the best-effort estimatedCompletionTime in a create receipt.
At the deadline, OmnAPI performs a final authoritative status read. If the
operation is still non-terminal, the Task becomes FAILED with EXPIRED or
PROVIDER_PROCESSING_TIMEOUT. Eligible charged credits are refunded; partial
or otherwise billable output follows the product’s settlement rules. Inspect
retryable and refunded, then submit a new logical request with a new
idempotency key when retry is appropriate.
This hard deadline remains distinct from a sync-wait timeout. A sync wait
that ends first returns HTTP 202 with status: "PROCESSING" and does not fail
or settle the Task.