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

# Generate videos

> Submit, poll, and download video generations.

Use `POST /v2/videos/generations` to start a video generation. Video generation is asynchronous, so you submit once, poll for status, and download the finished asset when it's ready.

```text theme={null}
POST https://api.getimg.ai/v2/videos/generations
GET  https://api.getimg.ai/v2/videos/generations/{id}
```

## The generation flow

<Steps>
  <Step title="Submit a generation request">
    POST to `/v2/videos/generations` with your model, prompt, and parameters. The API returns `HTTP 202` with a generation ID and `status: "pending"`.
  </Step>

  <Step title="Poll for completion">
    GET `/v2/videos/generations/{id}` periodically. The status will be `pending`, `failed`, or `completed`.
  </Step>

  <Step title="Download the video">
    When status is `completed`, download the video from the signed download URL in `data[0].url`.
  </Step>
</Steps>

## Step 1: Submit

<CodeGroup>
  ```javascript Node.js theme={null}
  import GetimgAI from "getimg-ai";

  const client = new GetimgAI();

  const result = await client.videos.generations.create({
    model: "seedance-v1-5-pro",
    prompt: "A drone shot over a futuristic city skyline at sunset",
    aspect_ratio: "16:9",
    resolution: "1080p",
    duration: 5,
    sound: true,
  });

  const generationId = result.id; // e.g., "req-01HXYZVIDEO1234"
  ```

  ```python Python theme={null}
  from getimg import GetimgAI

  client = GetimgAI()

  result = client.videos.generations.create(
      model="seedance-v1-5-pro",
      prompt="A drone shot over a futuristic city skyline at sunset",
      aspect_ratio="16:9",
      resolution="1080p",
      duration=5,
      sound=True,
  )

  generation_id = result.id  # e.g., "req-01HXYZVIDEO1234"
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.getimg.ai/v2/videos/generations \
    -H "Authorization: Bearer $GETIMG_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "seedance-v1-5-pro",
      "prompt": "A drone shot over a futuristic city skyline at sunset",
      "aspect_ratio": "16:9",
      "resolution": "1080p",
      "duration": 5,
      "sound": true
    }'
  ```
</CodeGroup>

```json theme={null}
{
  "id": "req-01HXYZVIDEO1234",
  "status": "pending"
}
```

## Step 2: Poll for status

Poll the status endpoint with your generation ID.

| Status      | Meaning           | Next action                                                  |
| ----------- | ----------------- | ------------------------------------------------------------ |
| `pending`   | Still processing  | Wait and poll again                                          |
| `failed`    | Generation failed | Read `error.message`, then submit a new generation if needed |
| `completed` | Video is ready    | Download from `data[0].url`                                  |

<CodeGroup>
  ```javascript Node.js theme={null}
  import GetimgAI from "getimg-ai";

  const client = new GetimgAI();

  const result = await client.videos.generations.retrieve("req-01HXYZVIDEO1234");
  console.log(result.status);
  ```

  ```python Python theme={null}
  from getimg import GetimgAI

  client = GetimgAI()

  result = client.videos.generations.retrieve("req-01HXYZVIDEO1234")
  print(result.status)
  ```

  ```bash cURL theme={null}
  curl https://api.getimg.ai/v2/videos/generations/req-01HXYZVIDEO1234 \
    -H "Authorization: Bearer $GETIMG_API_KEY"
  ```
</CodeGroup>

**Completed response:**

```json theme={null}
{
  "id": "req-01HXYZVIDEO1234",
  "status": "completed",
  "model": "seedance-v1-5-pro",
  "data": [
    {
      "url": "https://api.getimg.ai/v2/downloads/req-01HXYZVIDEO1234/0?exp=1760000000&sig=ca4f0f...",
      "width": 1920,
      "height": 1080,
      "duration": 5,
      "fps": 24,
      "has_sound": true,
      "mime_type": "video/mp4",
      "deletes_at": "2026-05-02T12:30:00.000Z"
    }
  ],
  "usage": {
    "total_cost": 0.25,
    "billable_unit": "video_second",
    "unit_price": 0.05,
    "quantity": 5
  }
}
```

### Polling strategy

Poll every 5 seconds as a starting point. Set a timeout so your integration stays responsive and does not poll forever.

<CodeGroup>
  ```javascript Node.js theme={null}
  import GetimgAI from "getimg-ai";

  const client = new GetimgAI();

  async function pollVideo(generationId, interval = 5000, timeout = 300000) {
    const start = Date.now();

    while (Date.now() - start < timeout) {
      const result = await client.videos.generations.retrieve(generationId);

      if (result.status === "completed") return result;
      if (result.status === "failed") {
        throw new Error(`Generation failed: ${result.error.message}`);
      }

      await new Promise((r) => setTimeout(r, interval));
    }

    throw new Error(`Video not ready after ${timeout / 1000}s`);
  }
  ```

  ```python Python theme={null}
  import time
  from getimg import GetimgAI

  client = GetimgAI()

  def poll_video(generation_id, interval=5, timeout=300):
      elapsed = 0
      while elapsed < timeout:
          result = client.videos.generations.retrieve(generation_id)

          if result.status == "completed":
              return result
          if result.status == "failed":
              raise Exception(f"Generation failed: {result.error.message}")

          time.sleep(interval)
          elapsed += interval

      raise TimeoutError(f"Video not ready after {timeout}s")
  ```

  ```bash cURL theme={null}
  while true; do
    response=$(curl -s https://api.getimg.ai/v2/videos/generations/req-01HXYZVIDEO1234 \
      -H "Authorization: Bearer $GETIMG_API_KEY")

    status=$(printf '%s' "$response" | jq -r '.status')
    echo "Status: $status"

    if [ "$status" = "completed" ] || [ "$status" = "failed" ]; then
      printf '%s\n' "$response"
      break
    fi

    sleep 5
  done
  ```
</CodeGroup>

## Step 3: Download

The `url` in each data item is a signed download URL. Download the file before the `deletes_at` timestamp.

<CodeGroup>
  ```javascript Node.js theme={null}
  import { writeFile } from "node:fs/promises";

  const download = await fetch("https://api.getimg.ai/v2/downloads/req-01HXYZVIDEO1234/0?exp=1760000000&sig=ca4f0f...");
  const buffer = Buffer.from(await download.arrayBuffer());
  await writeFile("video.mp4", buffer);
  ```

  ```python Python theme={null}
  import httpx

  with open("video.mp4", "wb") as f:
      f.write(httpx.get("https://api.getimg.ai/v2/downloads/req-01HXYZVIDEO1234/0?exp=1760000000&sig=ca4f0f...").content)
  ```

  ```bash cURL theme={null}
  curl -o video.mp4 "https://api.getimg.ai/v2/downloads/req-01HXYZVIDEO1234/0?exp=1760000000&sig=ca4f0f..."
  ```
</CodeGroup>

## Parameters

| Parameter      | Type    | Default       | Description                                                             |
| -------------- | ------- | ------------- | ----------------------------------------------------------------------- |
| `model`        | string  | required      | Model identifier. See [Models](https://getimg.ai/app/developer/models). |
| `prompt`       | string  | required      | Text description of the video to generate.                              |
| `aspect_ratio` | string  | model default | e.g., `16:9`, `1:1`, `9:16`.                                            |
| `resolution`   | string  | model default | e.g., `720p`, `1080p`.                                                  |
| `duration`     | integer | model default | Duration in seconds.                                                    |
| `sound`        | boolean | `false`       | Generate audio, where supported by the model.                           |
| `images`       | array   | --            | First frame, last frame, or reference image inputs.                     |

## Using frame and reference images

Video models support multiple image roles in the `images` array:

* **`first_frame`**: the opening frame of the video
* **`last_frame`**: the closing frame of the video. This always requires a `first_frame`.
* **`reference_image`**: a style or content reference when you need the output to stay closer to an existing visual direction. You cannot combine it with `first_frame` or `last_frame`.

```json theme={null}
{
  "model": "seedance-v1-5-pro",
  "prompt": "Transition from sunrise to dusk over mountain landscape",
  "images": [
    {
      "url": "https://your-bucket.s3.amazonaws.com/sunrise.png",
      "role": "first_frame"
    },
    {
      "url": "https://your-bucket.s3.amazonaws.com/dusk.png",
      "role": "last_frame"
    }
  ],
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "duration": 10
}
```

<Note>
  Not all models support all roles. Unsupported roles return `400` with code `invalid_parameter`.
</Note>

## Failure states

Video generations can fail after submission.

* If polling returns `status: "failed"`, treat that generation as terminal.
* Read `error.message` for the reason.
* Fix the input, wait if the problem is temporary, or submit a new generation.

## Sound

Set `sound: true` to generate audio. Supported models are listed on the [Models](https://getimg.ai/app/developer/models) page.

```json theme={null}
{
  "model": "seedance-v1-5-pro",
  "prompt": "Ocean waves crashing on a rocky shore",
  "duration": 10,
  "sound": true
}
```

## Full example

<CodeGroup>
  ```javascript Node.js theme={null}
  import { writeFile } from "node:fs/promises";
  import GetimgAI from "getimg-ai";

  const client = new GetimgAI();

  const { id } = await client.videos.generations.create({
    model: "seedance-v1-pro",
    prompt: "A timelapse of clouds rolling over a mountain peak",
    aspect_ratio: "16:9",
    resolution: "1080p",
    duration: 10,
    sound: true,
  });
  console.log(`Submitted: ${id}`);

  let result = await client.videos.generations.retrieve(id);
  while (result.status === "pending") {
    await new Promise((r) => setTimeout(r, 5000));
    result = await client.videos.generations.retrieve(id);
    console.log(`Status: ${result.status}`);
  }

  if (result.status === "failed") {
    throw new Error(`Failed: ${result.error.message}`);
  }

  const video = result.data[0];
  const download = await fetch(video.url);
  const buffer = Buffer.from(await download.arrayBuffer());
  await writeFile("output.mp4", buffer);

  console.log(`Saved output.mp4 (${video.width}x${video.height}, ${video.duration}s, ${video.fps}fps)`);
  console.log(`Sound: ${video.has_sound}`);
  console.log(`Cost: ${result.usage?.total_cost} (${result.usage?.quantity} ${result.usage?.billable_unit})`);
  ```

  ```python Python theme={null}
  import time
  import httpx
  from getimg import GetimgAI

  client = GetimgAI()

  submission = client.videos.generations.create(
      model="seedance-v1-pro",
      prompt="A timelapse of clouds rolling over a mountain peak",
      aspect_ratio="16:9",
      resolution="1080p",
      duration=10,
      sound=True,
  )
  print(f"Submitted: {submission.id}")

  result = client.videos.generations.retrieve(submission.id)
  while result.status == "pending":
      time.sleep(5)
      result = client.videos.generations.retrieve(submission.id)
      print(f"Status: {result.status}")

  if result.status == "failed":
      raise RuntimeError(f"Failed: {result.error.message}")

  video = result.data[0]
  with open("output.mp4", "wb") as f:
      f.write(httpx.get(video.url).content)

  print(f"Saved output.mp4 ({video.width}x{video.height}, {video.duration}s, {video.fps}fps)")
  print(f"Sound: {video.has_sound}")
  if result.usage:
      print(f"Cost: {result.usage.total_cost} ({result.usage.quantity} {result.usage.billable_unit})")
  ```

  ```bash cURL theme={null}
  submission=$(curl -s -X POST https://api.getimg.ai/v2/videos/generations \
    -H "Authorization: Bearer $GETIMG_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "seedance-v1-pro",
      "prompt": "A timelapse of clouds rolling over a mountain peak",
      "aspect_ratio": "16:9",
      "resolution": "1080p",
      "duration": 10,
      "sound": true
    }')

  generation_id=$(printf '%s' "$submission" | jq -r '.id')
  echo "Submitted: $generation_id"

  while true; do
    result=$(curl -s "https://api.getimg.ai/v2/videos/generations/$generation_id" \
      -H "Authorization: Bearer $GETIMG_API_KEY")
    status=$(printf '%s' "$result" | jq -r '.status')
    echo "Status: $status"

    if [ "$status" = "failed" ]; then
      printf '%s\n' "$result" | jq -r '.error.message'
      exit 1
    fi

    if [ "$status" = "completed" ]; then
      download_url=$(printf '%s' "$result" | jq -r '.data[0].url')
      curl -L "$download_url" -o output.mp4
      break
    fi

    sleep 5
  done
  ```
</CodeGroup>

## Related pages

* [Media responses](/guides/media-responses)
* [Errors](/guides/errors)
* [Rate limits](/guides/rate-limits)
* [Models](/guides/models)
