OmnAPI Task Model
Every generation on OmnAPI — image, lyrics, music, music video — is a task.
Whatever endpoint you call, you get back the same task descriptor, poll the
same GET /api/v1/tasks/{taskId}, read the same status enum, and consume the
same resources[]. Learn it once here; each module guide
(Producer, Suno, MV) then
only documents its own inputs and outputs.
Authentication is the same everywhere: the x-api-key header (see
Authentication).
The request config
Section titled “The request config”Every product or module task-creating endpoint accepts an optional, identical
config object for cross-cutting task settings. It is never module-specific:
{ "config": { "priority": 5, "tags": ["alpha", "experiment-7"], "metadata": { "orderId": "ord_123", "source": "my-app" }, "webhookUrl": "https://yourapp.com/callbacks/omnapi" }}| Field | Type | Notes |
|---|---|---|
priority | int | 1–10, default 5. Higher runs sooner under contention. |
tags | string[] | Up to 20 free-form labels, echoed back on read. |
metadata | object | Free-form JSON, echoed back on read. Your own correlation data. |
webhookUrl | string (URL) | Receive task.* events for this task. See Webhook Events. |
Running a task: async (default) vs sync
Section titled “Running a task: async (default) vs sync”Async (the default)
Section titled “Async (the default)”Module create endpoints return a descriptor in a non-terminal state. Producer
and MV return immediately. Suno song and derive endpoints may wait briefly for
provider acknowledgement so their product receipt can include real clipIds;
send Prefer: respond-async to skip that wait. Poll the returned taskId
until it reaches a terminal execution state:
{ "taskId": "task_01H...", "status": "PENDING", "creditsRequired": 8}Suno song delivery has an additional product view at
GET /api/v1/suno/generations/{generationId}. Use it for per-clip
submitted | queued | streaming | complete | error states and early playable
URLs in clips[].playback.url; use the Task descriptor for execution and
billing. Live playback does not require an SSE subscription or a separate
playback-session request. See Suno playback.
Generic task creation
Section titled “Generic task creation”Most integrations should use the product endpoints because they give clearer
request fields. POST /api/v1/tasks is available when you want to submit by
model path directly:
{ "model": "producer/lyria-3-preview/generate-image", "inputParameters": { "prompt": "synthwave album cover, neon palms" }, "priority": 5, "metadata": { "orderId": "ord_123" }}Generic task creation keeps task config fields flat at the top level:
priority, tags, metadata, and webhookUrl. Do not send a top-level
config wrapper on /api/v1/tasks; module endpoints use config because their
own generation fields already occupy the top level.
The API Reference publishes model as a closed enum and shows the exact
inputParameters schema for each feature branch. Vidu Direct and Subtitle Sync
are intentionally available only through /api/v1/vidu/* and
/api/v1/subtitles/*; their model paths are not accepted here. For MV, only
the unified managed-create model is accepted generically. If a product guide
and a generic feature appear to overlap, prefer the product endpoint because
its request and product response are the stable customer contract.
Sync (block for the result)
Section titled “Sync (block for the result)”Where a short blocking call is useful, use POST /api/v1/tasks/sync with the
same body shape as POST /api/v1/tasks. A sync call waits up to the server-side
timeout and then:
- completes in time →
200with the full terminal descriptor (resources/outputResultspopulated). - times out →
202withstatus: "PROCESSING"and a structuredpollUrl. The task is not failed — it’s still running; keep pollingpollUrl(which is/api/v1/tasks/{taskId}).
// 202 Accepted — the wait timed out, the task is still running{ "taskId": "task_01H...", "status": "PROCESSING", "pollUrl": "/api/v1/tasks/task_01H...", "creditsRequired": 12}List, cancel, and stream
Section titled “List, cancel, and stream”| Endpoint | Use when |
|---|---|
GET /api/v1/tasks | List recent tasks for your account or key. Use query filters from the API Reference for status/date pagination. |
GET /api/v1/tasks/{taskId} | Read one task descriptor. This is the canonical poll endpoint. |
POST /api/v1/tasks/{taskId}/cancel | Request cancellation for an active task when the API key has cancel scope. Pre-submit work can be cancelled immediately; post-submit work requires explicit Provider confirmation. |
GET /api/v1/tasks/{taskId}/stream | Subscribe to server-sent task status events instead of polling. Still handle reconnects and terminal-state reads. |
The task list returns a customer-safe pricing summary with the quote version
and final billed components (key, label, and credits). It does not expose
internal pricing limits, pricing-rule configuration, or provider/model
availability flags. Use creditsRequired and creditsCharged for the task
totals, and the pricing.components array when you need the itemized final
amount.
Cancellation is bounded by the Provider submission fence:
- Before the Provider request starts, a successful
200response atomically marks the taskCANCELLED, refunds the exact credits deducted at creation, and removes the inactive queue job. - After submission starts, OmnAPI cancels and refunds only when the Provider explicitly confirms remote cancellation.
- If submission outcome is unknown, the Provider does not support confirmed
cancellation, or cancellation times out/fails, the API returns
409 CONFLICT. The task remains active, is not refunded, and must continue to be polled. Direct Suno, Producer, and MV tasks currently follow this rule after submission.
Treat only 200 with success: true as a settled cancellation. On 409, read
details.cancellationReason for the diagnostic reason and continue polling the
original task. This prevents an already accepted Provider job from completing
for free after a local-only cancellation.
The stream endpoint is a standard text/event-stream response:
curl -N https://api.omnapi.com/api/v1/tasks/task_01H.../stream \ -H "x-api-key: $OMNAPI_KEY" \ -H "Accept: text/event-stream"| SSE event | data payload | Client action |
|---|---|---|
connected | { taskId, status, task } initial snapshot | Render immediately; it may already be terminal |
update | Latest task descriptor | Replace the locally cached task |
complete | Terminal task descriptor | Persist outputs and close the stream |
reconnect | { taskId, reason, pollUrl } plus an SSE retry hint | Close, poll pollUrl, then reconnect if still active |
error | { message } | Close and confirm terminal state through the poll URL |
Comment heartbeats (: ping) arrive every 25 seconds and carry no business
state. Always perform a final GET /api/v1/tasks/{taskId} after a disconnect
whose last event was not complete.
For webhook delivery, prefer Webhook Events on
production backends. SSE is useful for user-facing dashboards and short-lived
interactive sessions. Because the stream endpoint requires x-api-key, browser
clients should use fetch streaming or a backend proxy rather than native
EventSource, which cannot set custom headers.
Status lifecycle
Section titled “Status lifecycle”PENDING ──► PROCESSING ──► COMPLETED │ ├──► FAILED │ └──► CANCELLEDTerminal states are COMPLETED, FAILED, CANCELLED — stop
polling once you hit one. The enum is uppercase and identical across every
endpoint and webhook payload.
| State | Meaning |
|---|---|
PENDING | Queued for processing. |
PROCESSING | Generation in progress (also the sync-timeout state). |
COMPLETED | Done — resources and outputResults are populated. |
FAILED | Generation or validation error — errorCode + errorMessage populated; eligible credits refunded unless partial output was billable. |
CANCELLED | Cancelled before completion; eligible credits refunded. |
Polling
Section titled “Polling”Back off with a cap. Polling faster will not make generation complete sooner and can consume your rate-limit budget.
The following is a client-side example policy, not a promise about OmnAPI’s internal polling cadence. Start quickly for interactive work, then cap the interval:
| Attempt | Wait before next |
|---|---|
| 1 | 2s |
| 2 | 4s |
| 3 | 8s |
| 4 | 15s |
| 5+ | 30s (capped) |
async function pollTask(taskId: string, apiKey: string) { const waits = [2, 4, 8, 15, 30]; // client-side seconds for (let i = 0; ; i++) { const r = await fetch(`https://api.omnapi.com/api/v1/tasks/${taskId}`, { headers: { "x-api-key": apiKey }, }); const task = await r.json(); if (["COMPLETED", "FAILED", "CANCELLED"].includes(task.status)) return task; const wait = waits[Math.min(i, waits.length - 1)]; await new Promise((res) => setTimeout(res, wait * 1000)); }}Task descriptor & resources
Section titled “Task descriptor & resources”GET /api/v1/tasks/{taskId} returns the canonical descriptor:
{ "taskId": "task_01H...", "status": "COMPLETED", "inputParameters": { "prompt": "..." }, "creditsRequired": 8, "creditsCharged": 8, "refunded": false, "retryable": false, "warningCodes": [], "resources": [ { "id": "res_01H...", "type": "image", "url": "https://cdn.omnapi.com/...", "contentType": "image/png" } ], "outputResults": { /* endpoint-specific, informational */ }, "errorCode": null, "errorMessage": null, "createdAt": "2026-05-23T10:00:00Z", "updatedAt": "2026-05-23T10:00:18Z"}resourcesis the normalized, cross-module output array ({ id, type, url, contentType, ...metadata }). Prefer it when wiring downstream code.typeisimage/audio/video/text.outputResultscarries endpoint-specific details — treat it as informational.inputParameterscan echo request inputs for debugging and audit trails; avoid sending secrets or sensitive personal data in task requests.creditsRequiredis deducted when the task is created.creditsChargedis the final billed amount after completion, failure, cancellation, or partial output handling; see Credits & Billing.refundedis the final refund signal;retryableis the service’s terminal retry recommendation.- Signed resources may include
urlExpiresAt,retainedUntil, andassetStatus. Refresh the task to renew a URL and copy durable assets beforeretainedUntil.urlExpiresAtwill never be later thanretainedUntil. - Provider-account ids, tokens, viewer controls, and raw provider job ids are not part of the public task contract.
For the exhaustive field shapes of every public request and response, use the Interactive API Reference.
Idempotency
Section titled “Idempotency”Any paid create endpoint accepts an Idempotency-Key header. Reusing the
same key for the same request (within the retention window) replays the
original response instead of creating — and charging for — a second task. Send
a fresh value of at most 128 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:
curl -X POST https://api.omnapi.com/api/v1/producer/generate/image \ -H "x-api-key: sk_live_..." \ -H "Idempotency-Key: 7d3a1f2e-..." \ -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.
See also
Section titled “See also”- Webhook Events — push delivery of
task.*(and per-stage) events instead of polling. - Errors — the error envelope + the full code reference.
- Credits & Billing — pricing, charge caps, and refunds.
- Rate Limits — IP limits, API-key tier limits, and
Retry-After. - Interactive API Reference — OpenAPI-generated field shapes.