Skip to content

Async jobs (video / image / 3d)

Some provider APIs are asynchronous: you create a job, then poll until it reaches a terminal status. The gateway proxies these natively (same paths, same payloads as the provider) and adds tenant safety and accurate billing on top.

CREATE POST /<provider>/<create-path> → provider returns task_id
POLL GET /<provider>/<poll-path>/{id} → status: running | succeeded | ...
CANCEL DELETE /<provider>/<path>/{id} → (where the provider supports it)
LIST GET /<provider>/<list-path> → served from the gateway ledger

Example (BytePlus Seedance):

Terminal window
# CREATE
curl https://api.sociaro.com/byteplus/api/v3/contents/generations/tasks \
-H "Authorization: Bearer gw_live_..." \
-H "Content-Type: application/json" \
-d '{"model": "ep-m-...", "content": [{"type":"text","text":"A cat playing piano"}]}'
# → {"id": "cgt-...", ...} (the provider's own response shape)
# POLL until terminal
curl https://api.sociaro.com/byteplus/api/v3/contents/generations/tasks/cgt-... \
-H "Authorization: Bearer gw_live_..."

The Python SDK drives this loop for you (client.video.generate(...) / client.video.submit(...)).

  • Tenant isolation. Every job is recorded in the gateway’s ledger. Polling or cancelling a task that belongs to another organization returns 404 — the request never reaches the provider. Provider-side LIST is never proxied (it would leak other tenants’ jobs); the gateway serves LIST from its own ledger instead.
  • Accurate billing. At CREATE time the job is metered with a provisional cost (from your request’s duration/resolution parameters). When the job reaches a terminal state — via your poll, your cancel, or the gateway’s background poller — the cost is finalized exactly once: succeeded jobs get the real final cost, failed/cancelled jobs are zeroed.
  • Background finalization (reaper). If you stop polling, the gateway polls the provider itself and finalizes the job, so your analytics never show permanently “pending” spend. Jobs that can no longer be finalized are marked expired (e.g. after the polling TTL, or when upstream credentials were rotated mid-flight).
StatusMeaningBilling
pendingCreated, not yet terminalprovisional cost
succeededCompletedfinal cost (replaces provisional)
failedProvider reported failurecost zeroed
cancelledCancelledcost zeroed
expiredGateway could not finalize (expiration_reason: ttl or credential_rotated)provisional cost stands

Use GET /gw/async to list jobs with status, provisional/final cost and attribution — filterable by status, kind and time range, with cursor pagination. The same data backs the dashboard’s Async Jobs page.

In raw usage rows (GET /gw/usage), async requests appear with parse_status = provisional until finalization, then ok (succeeded), failed, cancelled, or expired.