Promoat / Partner API docs

Videos

Jobs & polling

Video endpoints return a workflow_id, and this endpoint is how you follow it: status, cost as it settles, and the finished video URL. No webhooks — poll it.

The status endpoint

GET/api/partner/v1/jobs/{workflowId}/status

Free to call, as often as you like. The response is the job's whole story:

FieldTypeDescription
workflow_idstringThe id you got when queueing.
statusenumqueuedrunningcompleted or failed.
video_url / image_urlstring | nullThe finished output, present once completed.
resultobject | nullGeneric envelope with video_url / image_url / audio_url / asset_id when present.
credits_estimatedint | nullThe reservation made at queue time.
credits_actualint | nullThe measured charge, recorded at completion.
credits_consumedint | nullThe one to display: null while queued/running, the actual charge once completed, 0 on failed (full refund) unless partial work was billed.
error_messagestring | nullWhy a failed job failed.
queued_at / completed_attimestampsFor your own duration metrics.
A completed multi-scene job (real shape)
{
  "workflow_id": "partner_scn_1783515143595_pnusyce",
  "status": "completed",
  "error_message": null,
  "credits_estimated": 620,
  "credits_actual": 561,
  "credits_consumed": 561,
  "video_url": "https://…/video.mp4",
  "result": { "video_url": "https://…/video.mp4", "asset_id": "…" },
  "queued_at": "2026-07-08T04:12:23.595Z",
  "completed_at": "2026-07-08T04:31:02.114Z"
}

A sane poll loop

  • Interval: every 5–10 seconds is plenty — jobs take minutes, not milliseconds.
  • Timeout: give talking-head jobs ~10 minutes and multi-scene ~25 before alarming. A job that's still running is genuinely still working.
  • Terminal states are terminal. Once completed or failed, the record never changes — cache it and stop polling.
Node example
async function waitForJob(workflowId) {
  for (;;) {
    const res = await fetch(
      `https://platform.promoat.ai/api/partner/v1/jobs/${workflowId}/status`,
      { headers: { Authorization: `Bearer ${process.env.PROMOAT_KEY}` } },
    );
    const job = await res.json();
    if (job.status === 'completed') return job;
    if (job.status === 'failed') throw new Error(job.error_message ?? 'job failed');
    await new Promise((r) => setTimeout(r, 8000));
  }
}

Showing progress to your users

While status is running, the job's row in GET /usage/jobs carries a metadata.phase field you can surface as a progress label — multi-scene jobs move from generating to finalizing as the video is produced.

404 on a status poll?

The workflow_id is wrong or belongs to a different key — existence is never leaked. Ids are returned only once, at queue time; if you lost one, find it in GET /usage/jobs.

Try it

Paste any workflow_id from a video you've queued (or grab one from your job history below):

Try itGET/api/partner/v1/usage/jobsfree
Add your API key in the sidebar to enable this.
Try itGET/api/partner/v1/jobs/{workflow_id}/statusfree
Add your API key in the sidebar to enable this.