Skip to main content
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.
POST https://api.getimg.ai/v2/videos/generations
GET  https://api.getimg.ai/v2/videos/generations/{id}

The generation flow

1

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".
2

Poll for completion

GET /v2/videos/generations/{id} periodically. The status will be pending, failed, or completed.
3

Download the video

When status is completed, download the video from the signed download URL in data[0].url.

Step 1: Submit

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"
{
  "id": "req-01HXYZVIDEO1234",
  "status": "pending"
}

Step 2: Poll for status

Poll the status endpoint with your generation ID.
StatusMeaningNext action
pendingStill processingWait and poll again
failedGeneration failedRead error.message, then submit a new generation if needed
completedVideo is readyDownload from data[0].url
import GetimgAI from "getimg-ai";

const client = new GetimgAI();

const result = await client.videos.generations.retrieve("req-01HXYZVIDEO1234");
console.log(result.status);
Completed response:
{
  "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.
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`);
}

Step 3: Download

The url in each data item is a signed download URL. Download the file before the deletes_at timestamp.
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);

Parameters

ParameterTypeDefaultDescription
modelstringrequiredModel identifier. See Models.
promptstringrequiredText description of the video to generate.
aspect_ratiostringmodel defaulte.g., 16:9, 1:1, 9:16.
resolutionstringmodel defaulte.g., 720p, 1080p.
durationintegermodel defaultDuration in seconds.
soundbooleanfalseGenerate audio, where supported by the model.
imagesarrayβ€”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.
{
  "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
}
Not all models support all roles. Unsupported roles return 400 with code invalid_parameter.

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 page.
{
  "model": "seedance-v1-5-pro",
  "prompt": "Ocean waves crashing on a rocky shore",
  "duration": 10,
  "sound": true
}

Full example

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})`);