# Get the result

`GET /v1/generations/{id}` returns the generation. Poll it every few seconds until `status` is `succeeded` or `failed`. Polling is free and never counts against a rate limit.

```bash cURL
ID=gen_4Fq9xT2mLr7Kd1sV8bN3pZ0c

curl -s https://vidlab.ai/v1/generations/$ID \
  -H "Authorization: Bearer $VIDLAB_API_KEY"
```

```python Python
import os, requests

job_id = "gen_4Fq9xT2mLr7Kd1sV8bN3pZ0c"
r = requests.get(
    f"https://vidlab.ai/v1/generations/{job_id}",
    headers={"Authorization": f"Bearer {os.environ['VIDLAB_API_KEY']}"},
)
job = r.json()["data"]
print(job["status"], [o["url"] for o in job["outputs"]])
```

```js JavaScript
const jobId = "gen_4Fq9xT2mLr7Kd1sV8bN3pZ0c";
const res = await fetch(`https://vidlab.ai/v1/generations/${jobId}`, {
  headers: { Authorization: `Bearer ${process.env.VIDLAB_API_KEY}` },
});
const { data: job } = await res.json();
console.log(job.status, job.outputs.map((o) => o.url));
```

A finished generation:

```json
{
  "data": {
    "id": "gen_4Fq9xT2mLr7Kd1sV8bN3pZ0c",
    "object": "generation",
    "status": "succeeded",
    "model": "seedance-2.5",
    "variant": "720p",
    "units": 5,
    "price_usd": 1.05,
    "outputs": [{ "url": "https://...", "mime": "video/mp4" }],
    "created_at": "2026-11-01T18:04:11.000Z",
    "finished_at": "2026-11-01T18:06:02.000Z"
  }
}
```

- Poll every 3 seconds for images and every 5 to 10 for video. VidLab asks the provider on its own schedule, so polling faster does not finish sooner.
- `GET /v1/jobs/{id}`, `/v1/jobs/{id}/status` and `/v1/jobs/{id}/result` return the same answer.
- Another account's id answers `404 generation_not_found`.

## Download the file

The files are in `outputs`. Download them with your key, so you never depend on a link that expires: `GET /v1/generations/{id}/content` is the first file, `/content/2` the second, and so on. The answer redirects to the stored file, so follow redirects (`curl -L`; `fetch` and `requests` do by default).

```bash cURL
curl -sL https://vidlab.ai/v1/generations/$ID/content \
  -H "Authorization: Bearer $VIDLAB_API_KEY" -o out.mp4
```

```python Python
import os, requests

job_id = "gen_4Fq9xT2mLr7Kd1sV8bN3pZ0c"
file = requests.get(
    f"https://vidlab.ai/v1/generations/{job_id}/content",
    headers={"Authorization": f"Bearer {os.environ['VIDLAB_API_KEY']}"},
)
open("out.mp4", "wb").write(file.content)
```

```js JavaScript
import { writeFile } from "node:fs/promises";

const jobId = "gen_4Fq9xT2mLr7Kd1sV8bN3pZ0c";
const file = await fetch(`https://vidlab.ai/v1/generations/${jobId}/content`, {
  headers: { Authorization: `Bearer ${process.env.VIDLAB_API_KEY}` },
});
await writeFile("out.mp4", Buffer.from(await file.arrayBuffer()));
```

- A generation that is not finished answers `409 not_ready` (with `Retry-After`), a failed one `409 generation_failed`, and a number past the last file `404 output_not_found`.
- The `url` in `outputs` is a signed link that lasts 6 hours; each poll returns a working one. The files themselves are kept for 30 days after the generation finished (`outputs_kept_until`). Copy files you want to keep longer to your own storage.
- An image call with `n` above 1 returns one output per image.

## List generations

`GET /v1/generations` returns your generations, newest first, with the same key. It is free and never rate limited. Use it for a task log, or to find an id you lost.

| Query | Values | What it does |
| - | - | - |
| `limit` | 1 to 100 (default 25) | How many generations in the page. |
| `starting_after` | A generation id | The next page: send the last id of the page before. |
| `status` | `queued`, `running`, `succeeded`, `failed` | Only generations in that status. |
| `model` | A model id | Only that model's generations. |

```bash cURL
curl -s "https://vidlab.ai/v1/generations?limit=10&status=succeeded" \
  -H "Authorization: Bearer $VIDLAB_API_KEY"
```

The answer is `{ "object": "list", "data": [generation, ...], "has_more": false }`. When `has_more` is `true`, call again with `starting_after` set to the last `id`. A bad query value answers `400` (`invalid_limit`, `invalid_status`, `invalid_model`, `invalid_starting_after`).
