🎬 Async Media Generation

Video & Image Generation

Generate video (/v1/videos/generations) and images (/v1/images/generations) from text prompts. Generation runs asynchronously: you get a job id back in milliseconds, poll for completion, then download the file. The exact dollar cost is known and charged before the job starts — no surprises on the invoice.

1. How the Async Flow Works

A 5-second clip takes 1–3 minutes upstream (premium models can take longer), far past any sane HTTP timeout — so nothing holds a connection open. Three requests, start to finish:

  1. Submit — POST /v1/videos/generations validates your parameters, quotes the exact cost, charges your balance, and returns 202 with a job id.
  2. Poll — GET /v1/videos/generations/:id reports queued → running → succeeded (or failed, which refunds you automatically). Poll every 5–10 seconds.
  3. Download — GET /v1/videos/generations/:id/content streams the finished MP4 (or image file) with correct Content-Type. Re-download as often as you like for 30 days at no extra charge.
cURL — submit, poll, download
# 1. Submit (returns immediately)
curl https://api.nicrron.ai/v1/videos/generations \
  -H "Authorization: Bearer $NICRRON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bytedance/seedance-2.0",
    "prompt": "A cozy jazz cafe at night, rain on the window",
    "duration": 4,
    "resolution": "720p"
  }'
# -> 202 { "id": "vid-2f56b1de-...", "object": "video.generation",
#          "status": "queued", "cost": 1.2852, "billing_units": 4 }

# 2. Poll until status is "succeeded"
curl https://api.nicrron.ai/v1/videos/generations/vid-2f56b1de-... \
  -H "Authorization: Bearer $NICRRON_API_KEY"
# -> { "status": "succeeded", "content_url": "/v1/videos/generations/vid-.../content",
#      "file_size": 2003164, "completed_at": "2026-08-30T22:13:39.000Z" }

# 3. Download the video
curl -o cafe.mp4 \
  https://api.nicrron.ai/v1/videos/generations/vid-2f56b1de-.../content \
  -H "Authorization: Bearer $NICRRON_API_KEY"
TypeScript — full polling helper
const BASE = "https://api.nicrron.ai";
const headers = {
  Authorization: `Bearer ${process.env.NICRRON_API_KEY}`,
  "Content-Type": "application/json",
};

async function generateVideo(body: object): Promise<ArrayBuffer> {
  const submit = await fetch(`${BASE}/v1/videos/generations`, {
    method: "POST", headers, body: JSON.stringify(body),
  });
  if (submit.status !== 202) throw new Error(await submit.text());
  const { id, cost } = await submit.json();
  console.log(`Job ${id} queued — charged $${cost}`);

  for (;;) {
    await new Promise((r) => setTimeout(r, 5000));
    const poll = await fetch(`${BASE}/v1/videos/generations/${id}`, { headers });
    const job = await poll.json();
    if (job.status === "succeeded") break;
    if (job.status === "failed") throw new Error(job.error); // already refunded
  }

  const file = await fetch(`${BASE}/v1/videos/generations/${id}/content`, { headers });
  return file.arrayBuffer();
}

const mp4 = await generateVideo({
  model: "google/veo-3.1-fast",
  prompt: "Golden retriever surfing a wave at sunset",
  duration: 8,
  generate_audio: true,
});

2. Video Models & Their Parameters

Every model validates its own constraints at submit time — an unsupported duration or resolution returns a 400 listing what the model accepts, before anything is charged. Omitting model defaults to bytedance/seedance-1.0-pro.

ModelPriceDuration (s)ResolutionAspect RatiosAudio
bytedance/seedance-2.0$0.31/s (720p), $0.69/s (1080p)4–15720p, 1080p21:9, 16:9, 4:3, 1:1, 3:4, 9:16Native, on by default (included in price)
bytedance/seedance-1.0-pro$2.5/1M video tokens (~$0.62 per 1080p 5s)2–12480p, 720p, 1080p21:9, 16:9, 4:3, 1:1, 3:4, 9:16—
google/veo-3.1-fast$0.10/s ($0.15/s with audio)4, 6, or 8720p, 1080p16:9, 9:16Optional (`generate_audio: true`)
kling/v2.5-turbo-pro$0.07/s5 or 101080p (fixed)16:9, 9:16, 1:1—
minimax/hailuo-02-pro$0.48/video6 (fixed)1080p (fixed)— (prompt only)—
  • Cheapest test run: kling/v2.5-turbo-pro at 5s ≈ $0.37 — great for iterating on prompts before a premium render.
  • Best quality with sound: bytedance/seedance-2.0 — native synchronized audio (ambient sound, music, effects) at no extra cost.
  • seed is supported by Seedance 1.0 and Veo; camera_fixed by Seedance 1.0 only. Passing a parameter a model doesn't support returns a 400 rather than being silently dropped.
  • Prices shown are list rates; the exact all-in charge for your parameters is returned as cost in the 202 response — that number is authoritative.

3. Image Generation

Images use the same job API at /v1/images/generations and usually finish in seconds. Flat per-image pricing; prompt and optional seed are the only parameters. Omitting model defaults to google/nano-banana.

ModelUnderlying ModelPrice
google/nano-bananaGemini 2.5 Flash Image$0.039/image
google/nano-banana-proGemini 3 Pro Image$0.15/image
cURL — generate an image
curl https://api.nicrron.ai/v1/images/generations \
  -H "Authorization: Bearer $NICRRON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/nano-banana",
    "prompt": "Isometric pixel-art coffee shop, warm palette"
  }'
# -> 202 { "id": "vid-...", "object": "image.generation", "cost": 0.041, ... }
# Poll GET /v1/images/generations/:id, then download :id/content

4. Billing: Charge Upfront, Refund on Failure

  • Media pricing is deterministic from your parameters, so the full cost is computed and charged at submit. If your balance can't cover it, the submit returns 402 with the exact price and nothing is charged.
  • If generation fails for any reason — upstream error, content rejection, timeout — the job flips to failed and the full amount is automatically refunded to your balance. Exactly-once, ledger-backed.
  • Polling and downloading are free, and every generation appears in your dashboard logs with its cost.

5. 30-Day Retention

Finished videos and images are stored on Nicrron infrastructure for 30 days and can be re-downloaded any number of times without re-paying. After 30 days the file and its prompt are permanently deleted, the job status becomes expired, and the content route returns 410. Media generation is therefore exempt from our chat-side Zero Data Retention guarantee — see the privacy documentation for the exact retention terms.

6. Status & Error Reference

Code / StatusMeaning
queued → running → succeededThe happy path. succeeded adds content_url and file_size.
failedGeneration failed upstream; error explains why and the charge was refunded.
expiredMore than 30 days old; the output was deleted.
400Invalid parameters — the message lists what the model supports. Nothing charged.
402Insufficient credits for the quoted cost. Nothing charged.
404Unknown model, or a job id that isn't yours.
409Content requested before the job finished — keep polling.
410Content requested after the 30-day retention window.
Video & Image Generation API Guide | Nicrron Docs