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:
- Submit —
POST /v1/videos/generationsvalidates your parameters, quotes the exact cost, charges your balance, and returns202with a job id. - Poll —
GET /v1/videos/generations/:idreportsqueued → running → succeeded(orfailed, which refunds you automatically). Poll every 5–10 seconds. - Download —
GET /v1/videos/generations/:id/contentstreams the finished MP4 (or image file) with correctContent-Type. Re-download as often as you like for 30 days at no extra charge.
# 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"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.
| Model | Price | Duration (s) | Resolution | Aspect Ratios | Audio |
|---|---|---|---|---|---|
| bytedance/seedance-2.0 | $0.31/s (720p), $0.69/s (1080p) | 4–15 | 720p, 1080p | 21:9, 16:9, 4:3, 1:1, 3:4, 9:16 | Native, on by default (included in price) |
| bytedance/seedance-1.0-pro | $2.5/1M video tokens (~$0.62 per 1080p 5s) | 2–12 | 480p, 720p, 1080p | 21: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 8 | 720p, 1080p | 16:9, 9:16 | Optional (`generate_audio: true`) |
| kling/v2.5-turbo-pro | $0.07/s | 5 or 10 | 1080p (fixed) | 16:9, 9:16, 1:1 | — |
| minimax/hailuo-02-pro | $0.48/video | 6 (fixed) | 1080p (fixed) | — (prompt only) | — |
- Cheapest test run:
kling/v2.5-turbo-proat 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. seedis supported by Seedance 1.0 and Veo;camera_fixedby 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
costin 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.
| Model | Underlying Model | Price |
|---|---|---|
| google/nano-banana | Gemini 2.5 Flash Image | $0.039/image |
| google/nano-banana-pro | Gemini 3 Pro Image | $0.15/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/content4. 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
402with the exact price and nothing is charged. - If generation fails for any reason — upstream error, content rejection, timeout — the job flips to
failedand 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 / Status | Meaning |
|---|---|
| queued → running → succeeded | The happy path. succeeded adds content_url and file_size. |
| failed | Generation failed upstream; error explains why and the charge was refunded. |
| expired | More than 30 days old; the output was deleted. |
| 400 | Invalid parameters — the message lists what the model supports. Nothing charged. |
| 402 | Insufficient credits for the quoted cost. Nothing charged. |
| 404 | Unknown model, or a job id that isn't yours. |
| 409 | Content requested before the job finished — keep polling. |
| 410 | Content requested after the 30-day retention window. |