Skip to main content
Rendering a video, editing footage, analyzing media and generating 3D take minutes. Those capabilities accept the request, answer immediately with a jobId, and keep working. You collect the result from one endpoint, GET /v1/jobs/{jobId}, whatever capability created the job. Capabilities that return a job include POST /v1/video/render, POST /v1/video/edit, POST /v1/video/edit/approve, POST /v1/video/ugc, POST /v1/video/footage, POST /v1/3d/from-text and POST /v1/3d/from-image. GET /v1/capabilities marks each of them with async: true.

Poll a job

Poll every 15–30 seconds and add a little random jitter when you start many jobs at once. A job that belongs to another workspace answers 404 not_found, exactly like one that does not exist.

Job statuses

Branch on status. It is a closed set and safe to switch on. phase is a progress label such as narrating — show it to people, but do not branch on it, because its values change as pipelines evolve.
awaiting_review waits for a person. A footage edit submitted with reviewCuts: true stops when its cut list is ready. Read the proposed cuts with GET /v1/jobs/{jobId}/proposal, then approve them with POST /v1/video/edit/approve — or let someone review them in the dashboard. See Video, footage & 3D.
A qa_failed result is diagnostic only. Its artifacts are evidence of why the release check failed — read artifacts.scriptReview — not output you can ship. Fix the cause and render again.
A job that ends as failed, cancelled or qa_failed after being charged is refunded. You are never charged for output you cannot release.

Collect the artifacts

When status is done, job.artifacts holds the outputs:
A field that is null means that artifact was not produced. Which fields appear depends on kind: a footage edit (video.edit) also carries outputKind, summary and packaging, and while it is awaiting_review, a review block with the size of the pending decision.

Downloading

Render links are signed: fetch them without an Authorization header, from a browser, a downloader or a <video> tag. The bytes come straight from storage, so large files download at full speed. For 3D jobs (kind: "asset.animate"), artifacts.download points at GET /v1/jobs/{jobId}/download. Send your API key and follow the 307 redirect; the redirect target is a short-lived signed URL that needs no key.
Signed links expire. Download promptly, and store the job id rather than the URL. Poll the job again whenever you need fresh links.

Follow progress with events

Instead of polling the job, you can read its ordered event log. Each event has a sequence; send the last one you processed as after to resume exactly where you left off.
For a live feed, GET /v1/jobs/{jobId}/stream-token returns a short-lived WebSocket url scoped to the job. If the connection drops, replay from your last sequence with the events endpoint, then reconnect. For delivery to your own server, see Webhooks.

List jobs

GET /v1/jobs lists recent render and footage-edit jobs, newest first. Filter by projectId, kind or status, and page with cursor — see Pagination.

Cancel a job

POST /v1/jobs/{jobId}/cancel stops a render, footage edit, media analysis or 3D job. Cancelling is safe to retry: a job that already finished returns its current status. A cancelled job that produced nothing releasable is refunded.
A late completion can never revive or publish a cancelled job.

When a capability is unavailable

Some capabilities need GPU capacity. When one cannot run, the call is refused up front with 503 capability_unavailable — before you are charged and before any work starts — rather than failing partway. Check available in GET /v1/capabilities before building a flow that depends on it.