Skip to content

Video generation

Video is generated asynchronously: you create a job, poll until it finishes, then download the result. Generating a clip takes from tens of seconds to several minutes. Video models include veo-3.1-generate-preview, veo-3.1-fast-generate-preview, seedance-2-0, kling-v3-0, grok-imagine-video-1-5 and wan-2-6-t2v — see the models page for each one's lengths, sizes and price.

1. Create a job

curl https://api.cloakray.com/v1/videos \
  -H "Authorization: Bearer $CLOAKRAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "veo-3.1-fast-generate-preview",
    "prompt": "A paper boat drifting across a quiet pond at sunrise",
    "seconds": 8,
    "size": "1280x720"
  }'
{
  "id": "video_7f3a...",
  "object": "video",
  "model": "veo-3.1-fast-generate-preview",
  "status": "queued",
  "progress": 0,
  "created_at": 1767225600,
  "completed_at": null,
  "error": null
}
FieldWhat it does
modelRequired. A video model.
promptRequired. What the video should show.
secondsLength. Each model offers a fixed set, for example 4, 6, 8 or 10.
sizeOutput size as widthxheight, from the sizes the model offers.
audiofalse for a silent clip, on models that can do both. Silent clips are often cheaper.
imageA first frame to animate, on models that support image-to-video.

2. Poll the status

curl https://api.cloakray.com/v1/videos/$VIDEO_ID \
  -H "Authorization: Bearer $CLOAKRAY_API_KEY"

status moves from queued to in_progress, then ends as completed or failed (or expired). Poll every 10–20 seconds with backoff rather than in a tight loop; polling is free.

3. Download the video

Once the job is completed:

curl https://api.cloakray.com/v1/videos/$VIDEO_ID/content \
  -H "Authorization: Bearer $CLOAKRAY_API_KEY" \
  --output video.mp4

Download it promptly and store it yourself; finished videos are not kept indefinitely. Reading the status or the content again does not charge again.

In code

const headers = { Authorization: `Bearer ${process.env.CLOAKRAY_API_KEY}`, "Content-Type": "application/json" };
const base = "https://api.cloakray.com/v1/videos";

let job = await (await fetch(base, {
  method: "POST",
  headers,
  body: JSON.stringify({ model: "veo-3.1-fast-generate-preview", prompt: "A paper boat drifting across a pond", seconds: 8 }),
})).json();

while (job.status === "queued" || job.status === "in_progress") {
  await new Promise((resolve) => setTimeout(resolve, 15_000));
  job = await (await fetch(`${base}/${job.id}`, { headers })).json();
}

if (job.status !== "completed") throw new Error(job.error?.message ?? job.status);
const video = await fetch(`${base}/${job.id}/content`, { headers });

Ownership and pricing

A job ID belongs to the project whose key created it; keys from other projects get a 404. Video is priced per second of output, by resolution and by whether it has audio, and shown on each model's page. Before a job starts, your balance must cover its estimated price; a job that fails is not charged.

Use an Idempotency-Key when creating jobs, so a retried request returns the job you already started instead of paying for a second one.