> ## Documentation Index
> Fetch the complete documentation index at: https://docs.motion.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Polling Jobs

`POST /sessions` returns immediately with a `job_id` for a durable video job. The response includes `status_url`, an authenticated public API polling URL, and `chat_url`, a Motion app chat link for human review or continuation. Poll until the response includes a completed output and `output.download_url`, or until the job fails or requests input.

## Status endpoint

```http theme={null}
GET https://api.motion.so/api/motion/sessions/{job_id}
Authorization: Bearer motion_your_api_key
```

`status_url` points to this endpoint. It is not a browser-accessible Motion app page. Use `chat_url` when you need to open the Motion chat.

## Status values

| Status | Meaning |
| - | - |
| `queued` | The job was accepted and is waiting to start. |
| `created` | A legacy session is preparing to run. |
| `running` | The job is actively generating. |
| `awaiting_user_input` | The job is waiting on user input. API initiated runs auto approve planning stages where possible. |
| `completed` | New engine-backed jobs have a ready export. Older session jobs can finish before their export; always check output readiness. |
| `failed` | The job failed. Check the `error` field. |

## Polling interval

Start with a 2 to 5 second interval. Increase the interval for long-running jobs.

There is no separate public output or download endpoint. Output can be pending while a new engine-backed job remains `running`, or while an older session job reports `completed`. The MP4 is ready when `output.status === "completed"` and `output.download_url` is non-null.

The same status response can include `sources`, an additive array of source assets currently used in the composition. Use this to audit where media came from without exposing internal storage paths. Each source includes a category (`source_kind`), provider, source/display URLs when available, rights status, and `usages` entries with timestamps and scene/composition placement.

```js theme={null}
async function waitForVideoJob(jobId, apiKey) {
  while (true) {
    const response = await fetch(
      `https://api.motion.so/api/motion/sessions/${jobId}`,
      {
        headers: {
          Authorization: `Bearer ${apiKey}`,
        },
      },
    )
    if (!response.ok) throw new Error(`Status request failed: ${response.status}`)
    const job = await response.json()
    if (job.status === 'failed' || job.status === 'awaiting_user_input' || job.output?.status === 'failed') {
      return job
    }
    if (job.output?.status === 'completed' && job.output?.download_url) return job
    await new Promise((resolve) => setTimeout(resolve, 3000))
  }
}
```

## Reply or resume

When `status` is `awaiting_user_input`, send your reply to `POST /sessions/{job_id}/followups`. If `insufficient_credits` is true, add credits before continuing the same job. Follow-ups preserve the engine and template; omit `effort` to retain its current value.

Signed download URLs expire. Poll the same job again to obtain a current URL.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.