Build

Video API

Turn a text prompt into an MP4: create a video, poll it, then download it.

1. Create a video

Set MINIROUTER_API_KEY to a funded API key. This starts a 4-second clip, holds credit and saves its id.

Create
curl --fail-with-body --retry 0 https://api.minirouter.sh/v1/videos \
  -H "Authorization: Bearer $MINIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "model": "google/veo-3.1-lite-generate-001",
  "prompt": "A paper boat drifting down a rainy street at dusk",
  "seconds": 4,
  "size": "1280x720"
}' | tee video.json
VIDEO_ID=$(jq -r .id video.json)

2. Poll until it finishes

Repeat every 10 seconds until status is completed or failed.

Poll
curl --fail-with-body https://api.minirouter.sh/v1/videos/$VIDEO_ID \
  -H "Authorization: Bearer $MINIROUTER_API_KEY"

3. Download the MP4

Downloads are free for 24 hours after completion.

Download
curl --fail-with-body https://api.minirouter.sh/v1/videos/$VIDEO_ID/content \
  -H "Authorization: Bearer $MINIROUTER_API_KEY" \
  --output video.mp4

Use the OpenAI SDK

Point the client at MiniRouter and turn off retries: a retried create starts a second video.

video.mjs
// npm install openai@7.4.0
import OpenAI from 'openai';
import { writeFile } from 'node:fs/promises';
import { setTimeout as sleep } from 'node:timers/promises';

const client = new OpenAI({
  baseURL: 'https://api.minirouter.sh/v1',
  apiKey: process.env.MINIROUTER_API_KEY,
  maxRetries: 0,
});
let video = await client.videos.create({
  model: 'google/veo-3.1-lite-generate-001',
  prompt: 'A paper boat drifting down a rainy street at dusk',
  seconds: '4', size: '1280x720',
});
while (video.status === 'queued' || video.status === 'in_progress') {
  await sleep(10_000);
  video = await client.videos.retrieve(video.id);
}
if (video.status === 'failed') throw new Error(video.error?.message);
const content = await client.videos.downloadContent(video.id);
await writeFile('video.mp4', Buffer.from(await content.arrayBuffer()));

Only create, retrieve and download are supported. Values from video.controls work even where the SDK types omit them; TypeScript needs a cast.

Choose a model

Text-to-video models in the live catalog. Open a model for its full price table, or copy its ID.

17 models for text to video

Alibaba

  • Wan v2.5 Text-to-Video Previewalibaba/wan-v2.5-t2v-preview
    480p, 720p, 1080p · 5 or 10 seconds · from $0.0525/s
  • Wan v2.6 Text-to-Videoalibaba/wan-v2.6-t2v
    720p, 1080p · 2–15 seconds · from $0.105/s
  • Wan v2.7 Text-to-Videoalibaba/wan-v2.7-t2v
    720p, 1080p · 2–15 seconds · from $0.105/s

ByteDance

  • Seedance v1.0 Probytedance/seedance-v1.0-pro
    480p, 720p, 1080p · 2–12 seconds · from $0.025515/s
  • Seedance v1.0 Pro Fastbytedance/seedance-v1.0-pro-fast
    480p, 720p, 1080p · 2–12 seconds · from $0.010185/s
  • Seedance v1.5 Probytedance/seedance-v1.5-pro
    480p, 720p, 1080p · 4–12 seconds · audio · from $0.012705/s

Google

  • Veo 3.1google/veo-3.1-generate-001
    720p, 1080p, 4K · 4, 6 or 8 seconds · audio · from $0.21/s
  • Veo 3.1 Fast Generategoogle/veo-3.1-fast-generate-001
    720p, 1080p, 4K · 4, 6 or 8 seconds · audio · from $0.105/s
  • Veo 3.1 Lite Generategoogle/veo-3.1-lite-generate-001
    720p, 1080p · 4, 6 or 8 seconds · audio · from $0.0315/s

Kling AI

  • Kling v2.5 Turbo Text-to-Videoklingai/kling-v2.5-turbo-t2v
    720p, 1080p · 5 or 10 seconds · from $0.0441/s
  • Kling v2.6 Text-to-Videoklingai/kling-v2.6-t2v
    720p, 1080p · 5 or 10 seconds · audio · from $0.0441/s
  • Kling v3.0 Text-to-Videoklingai/kling-v3.0-t2v
    720p, 1080p · 3–15 seconds · audio · from $0.1764/s

MiniMax

  • MiniMax H3minimax/minimax-h3
    768p, 2K · 4–15 seconds · from $0.084/s
  • MiniMax H3 Maxminimax/minimax-h3-max
    480p, 768p · 5–15 seconds · from $0.0525/s

xAI

  • Grok Imaginespacexai/grok-imagine-video
    480p, 720p · 1–15 seconds · from $0.0525/s
  • Grok Imagine Video 1.5spacexai/grok-imagine-video-1.5
    480p, 720p, 1080p · 1–15 seconds · from $0.084/s
  • Grok Imagine Video 1.5 Litespacexai/grok-imagine-video-1.5-lite
    480p, 720p, 1080p · 1–15 seconds · from $0.021/s

List models in code

Video models are the GET /v1/models entries with "type": "video".

List video models
curl -s https://api.minirouter.sh/v1/models | jq '.data[]
  | select(.type == "video")
  | {id, controls: .video.controls, prices: .video.pricing.prices}'
video.controls.sizes
Accepted size values, each with a price tier and aspect_ratio.
video.controls.seconds
Accepted durations.
video.controls.audio
true if the model can add sound.
video.controls.max_prompt_chars
Longest accepted prompt.
video.pricing.prices
usd_per_second by tier and audio.

Request body

model
Required. A video model id.
prompt
Required. Up to max_prompt_chars characters.
seconds
Required. One of video.controls.seconds, as a number or string.
size
Required. One of video.controls.sizes, such as 1280x720.
audio
Optional, default false. true adds sound where the model supports it, at the audio price.

Send JSON or multipart fields, up to 256 KiB. Video is text to video only: image_url, file parts and any other field return 400.

Read the status

Create and poll return the video object. cost is a MiniRouter extension.

Video object
{
  "id": "req_5f2c9e8a1b7d4c3e9f6a0b2d8c4e1f7a",
  "object": "video",
  "model": "google/veo-3.1-lite-generate-001",
  "status": "in_progress",
  "progress": 50,
  "created_at": 1793145600,
  "completed_at": null,
  "expires_at": null,
  "seconds": "4",
  "size": "1280x720",
  "error": null,
  "cost": {
    "status": "pending",
    "usd": null
  }
}

Video status

queued
Accepted, not started yet.
in_progress
Generating.progress is 0 while queued, 50 while generating and 100 when completed.
completed
Ready to download until expires_at.
failed
error says why. Nothing is charged.

Cost status

pending
Credit is held. usd is null.A completed video stays pending until the provider reports its cost.
settled
usd is the final charge.
released
The hold was returned. usd is "0".

Pricing and holds

Prices are per second of output, by size tier and audio, and include MiniRouter's 5% fee.

  1. 01HoldThe extra second covers clips that run long. The minimum hold is $0.00002.At create: (seconds + 1) × the per-second price.
  2. 02GenerateA failed or cancelled video releases the hold.
  3. 03SettleWhat the provider bills, at the listed price and never more than the hold. The rest returns.

For example, 4 seconds at $0.0315 a second holds $0.1575. If the provider bills 4 seconds, you pay $0.126 and $0.0315 returns.

Video is paid from credit; provider keys (BYOK) are not used. Key spend limits apply to the hold.

Limits

Hours content is kept after completion
24
Videos in progress per account
2
Minutes before a running video is cancelled
45
Charged for a failed video
$0

A video counts toward the 2 until its cost settles. Polls and downloads count toward your key's rate limit. Only the account that created a video can read it.

Errors

invalid_request
400. A field is missing, unsupported or not in video.controls, or the provider refused the prompt. Nothing is charged.
insufficient_credits
402. Your balance cannot cover the hold.
rate_limited
429. Too many requests on this key, polls included.
videos_unavailable
503. Video is paused, or your account already has 2 videos in progress. Nothing is charged.
video_capacity
503. Provider or download capacity is full. Retry after Retry-After.
video_request_failed
502. The create was not confirmed and may still run. Its x-minirouter-request-id is the video id: poll it before creating another.
video_not_found
404. No video with this id on your account.
video_not_ready
409. Not completed yet. Failed videos have no content.
video_expired
410. More than 24 hours since completion.
video_content_unavailable
502. The download failed. Retry; downloads are free.

Other codes are in Errors.

Choose your path