---
title: Polling
description: How often to check a job and when to stop.
---
Polling `GET /v1/jobs/{id}/status` is the default way to wait for a job. The API tells you how long to wait between checks, so you do not have to guess.

## The loop

1. Submit. Keep `status_url` from the response.
2. Wait `next_poll_after_seconds` (also sent as the `x-sume-poll-after` header).
3. Call `status_url`.
4. Stop when `terminal` is `true`. If `next_action` is `fetch_result`, read `result_url`.

```js
async function waitForJob(statusUrl, apiKey) {
  for (;;) {
    const res = await fetch(statusUrl, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    if (res.status === 429 || res.status >= 500) {
      const wait = Number(res.headers.get("retry-after") ?? 5);
      await new Promise(r => setTimeout(r, wait * 1000));
      continue;
    }
    const { data } = await res.json();
    if (data.terminal) return data;
    const wait = data.next_poll_after_seconds ?? data.recommended_poll_interval_seconds ?? 2;
    await new Promise(r => setTimeout(r, wait * 1000));
  }
}
```

A job in progress looks like this:

```json
{
  "data": {
    "request_id": "job_7513b52d-3669-4ffe-b317-8b02000715eb",
    "job_id": "job_7513b52d-3669-4ffe-b317-8b02000715eb",
    "status": "IN_PROGRESS",
    "sume_status": "processing",
    "status_url": "https://api.open.sume.com/v1/jobs/job_7513b52d-3669-4ffe-b317-8b02000715eb/status",
    "result_url": "https://api.open.sume.com/v1/jobs/job_7513b52d-3669-4ffe-b317-8b02000715eb/result",
    "cancel_url": null,
    "cancelable": false,
    "next_action": "poll_status",
    "next_poll_after_seconds": 30,
    "recommended_poll_interval_seconds": 2,
    "retry_after_seconds": 30,
    "result_ready": false,
    "terminal": false,
    "queue_position": null
  }
}
```

## Intervals

Images usually finish in 5 to 30 seconds and video in one to several minutes. The API returns a short interval while a job is queued and a longer one once it is running. Follow it; polling faster does not finish the job sooner and spends your rate limit.

Set your own deadline per model. A job that is still `processing` past it can keep running: check it again later instead of resubmitting.

## Waiting inside the submit call

With `mode: "sync"` or `"subscribe"`, the submit call waits up to `wait_timeout_seconds` (at most 30) for the job. If the job is not done by then, the response carries `sync.timed_out: true` and the same URLs as an `async` submit. Poll from there; do not submit again.

## Prefer webhooks for long jobs

For video, a [webhook](/docs/webhooks) saves the polling. Keep a slow poll as a fallback in case a delivery is lost.
