Video Generation

How to generate videos with OpenRouter models

OpenRouter supports video generation through models that have "video" in their output_modalities. These models can create videos from text prompts (and optional reference images) via a dedicated asynchronous API.

Video generation uses the /api/v1/videos endpoint. This API may change.

Model Discovery

You can find video generation models in several ways:

Via the Video Models API

Use the dedicated video models endpoint to list all available video generation models along with their supported parameters:

$curl "https://openrouter.ai/api/v1/videos/models"

The response returns a data array where each model includes:

1{
2 "data": [
3 {
4 "id": "google/veo-3.1",
5 "canonical_slug": "google/veo-3.1",
6 "name": "Google: Veo 3.1",
7 "description": "...",
8 "created": 1719792000,
9 "supported_resolutions": ["720p", "1080p"],
10 "supported_aspect_ratios": ["16:9", "9:16", "1:1"],
11 "supported_sizes": ["1280x720", "1920x1080"],
12 "pricing_skus": {
13 "per-video-second": "0.50",
14 "per-video-second-1080p": "0.75"
15 },
16 "allowed_passthrough_parameters": ["output_config"]
17 }
18 ]
19}
FieldDescription
idModel slug to use in generation requests
canonical_slugPermanent model identifier
supported_resolutionsList of supported output resolutions (e.g., 720p, 1080p)
supported_aspect_ratiosList of supported aspect ratios (e.g., 16:9, 9:16)
supported_sizesList of supported pixel dimensions (e.g., 1280x720)
pricing_skusPricing information per SKU
allowed_passthrough_parametersProvider-specific parameters that can be passed through via the provider option

Use this endpoint to check which resolutions, aspect ratios, and passthrough parameters are supported by each model before submitting a generation request.

Via the Models API

You can also use the output_modalities query parameter on the Models API to discover video generation models:

$# List only video generation models
$curl "https://openrouter.ai/api/v1/models?output_modalities=video"

On the Models Page

Visit the Models page and filter by output modalities to find models capable of video generation. Look for models that list "video" in their output modalities.

How It Works

Unlike text or image generation, video generation is asynchronous because generating video takes significantly longer. The workflow is:

  1. Submit a generation request to POST /api/v1/videos
  2. Receive a job ID and polling URL immediately
  3. Poll the polling URL (GET /api/v1/videos/{jobId}) until the status is completed
  4. Download the video from the content URL (GET /api/v1/videos/{jobId}/content)

API Usage

Submitting a Video Generation Request

1import requests
2import json
3import time
4
5url = "https://openrouter.ai/api/v1/videos"
6headers = {
7 "Authorization": f"Bearer {API_KEY_REF}",
8 "Content-Type": "application/json"
9}
10
11payload = {
12 "model": "{{MODEL}}",
13 "prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background"
14}
15
16# Step 1: Submit the generation request
17response = requests.post(url, headers=headers, json=payload)
18result = response.json()
19
20job_id = result["id"]
21polling_url = result["polling_url"]
22print(f"Job submitted: {job_id}")
23print(f"Status: {result['status']}")
24
25# Step 2: Poll until completion
26while True:
27 time.sleep(30) # Wait 30 seconds between polls
28 poll_response = requests.get(polling_url, headers=headers)
29 status = poll_response.json()
30
31 print(f"Status: {status['status']}")
32
33 if status["status"] == "completed":
34 # Step 3: Download the video
35 content_url = status["unsigned_urls"][0]
36 video_response = requests.get(content_url)
37 with open("output.mp4", "wb") as f:
38 f.write(video_response.content)
39 print("Video saved to output.mp4")
40 break
41 elif status["status"] == "failed":
42 print(f"Generation failed: {status.get('error', 'Unknown error')}")
43 break

Request Parameters

ParameterTypeRequiredDescription
modelstringYesThe model to use for video generation (e.g., google/veo-3.1)
promptstringYesText description of the video to generate
durationintegerNoDuration of the generated video in seconds
resolutionstringNoResolution of the output video (e.g., 720p, 1080p)
aspect_ratiostringNoAspect ratio of the output video (e.g., 16:9, 9:16)
sizestringNoExact pixel dimensions in WIDTHxHEIGHT format (e.g., 1280x720). Interchangeable with resolution + aspect_ratio
input_referencesarrayNoReference images to guide video generation
generate_audiobooleanNoWhether to generate audio alongside the video. Defaults to true for models that support audio output
seedintegerNoSeed for deterministic generation (not guaranteed by all providers)
providerobjectNoProvider-specific passthrough configuration

Supported Resolutions

  • 480p
  • 720p
  • 1080p
  • 1K
  • 2K
  • 4K

Supported Aspect Ratios

  • 16:9 — Widescreen landscape
  • 9:16 — Vertical/portrait
  • 1:1 — Square
  • 4:3 — Standard landscape
  • 3:4 — Standard portrait
  • 21:9 — Ultra-wide
  • 9:21 — Ultra-tall

Using Reference Images

You can provide reference images to guide the video generation. This is useful for creating videos based on existing visual content:

1import requests
2
3url = "https://openrouter.ai/api/v1/videos"
4headers = {
5 "Authorization": f"Bearer {API_KEY_REF}",
6 "Content-Type": "application/json"
7}
8
9payload = {
10 "model": "{{MODEL}}",
11 "prompt": "Animate this character walking through a forest",
12 "input_references": [
13 {
14 "type": "image_url",
15 "image_url": {
16 "url": "https://example.com/character.png"
17 }
18 }
19 ],
20 "aspect_ratio": "16:9",
21 "resolution": "1080p"
22}
23
24response = requests.post(url, headers=headers, json=payload)
25result = response.json()
26print(f"Job submitted: {result['id']}")

Provider-Specific Options

You can pass provider-specific options using the provider parameter. Options are keyed by provider slug, and only the options for the matched provider are forwarded:

1{
2 "model": "google/veo-3.1",
3 "prompt": "A time-lapse of a flower blooming",
4 "provider": {
5 "options": {
6 "google-vertex": {
7 "parameters": {
8 "personGeneration": "allow",
9 "negativePrompt": "blurry, low quality"
10 }
11 }
12 }
13 }
14}

Use the Video Models API to check which passthrough parameters each model supports via the allowed_passthrough_parameters field.

Response Format

Submit Response (202 Accepted)

When you submit a video generation request, you receive an immediate response with the job details:

1{
2 "id": "abc123",
3 "polling_url": "https://openrouter.ai/api/v1/videos/abc123",
4 "status": "pending"
5}

Poll Response

When polling the job status, the response includes additional fields as the job progresses:

1{
2 "id": "abc123",
3 "generation_id": "gen-1234567890-abcdef",
4 "polling_url": "https://openrouter.ai/api/v1/videos/abc123",
5 "status": "completed",
6 "unsigned_urls": [
7 "https://openrouter.ai/api/v1/videos/abc123/content?index=0"
8 ],
9 "usage": {
10 "cost": 0.25,
11 "is_byok": false
12 }
13}

Job Statuses

StatusDescription
pendingThe job has been submitted and is queued
in_progressThe video is being generated
completedThe video is ready to download
failedThe generation failed (check the error field)

Downloading the Video

Once the job status is completed, the unsigned_urls array contains URLs to download the generated video content. You can also use the content endpoint directly:

$curl "https://openrouter.ai/api/v1/videos/{jobId}/content?index=0" \
> -H "Authorization: Bearer $OPENROUTER_API_KEY" \
> --output video.mp4

The index query parameter defaults to 0 and can be used if the model generates multiple video outputs.

Best Practices

  • Detailed Prompts: Provide specific, descriptive prompts for better video quality. Include details about motion, camera angles, lighting, and scene composition
  • Appropriate Resolution: Higher resolutions take longer to generate and cost more. Choose the resolution that fits your use case
  • Polling Interval: Use a reasonable polling interval (e.g., 30 seconds) to avoid excessive API calls. Video generation typically takes 30 seconds to several minutes depending on the model and parameters
  • Error Handling: Always check the job status for failed state and handle the error field appropriately
  • Reference Images: When using reference images, ensure they are high quality and relevant to the desired video output

Troubleshooting

Job stays in pending for a long time?

  • Video generation can take several minutes depending on the model, resolution, and server load
  • Continue polling at regular intervals

Generation failed?

  • Check the error field in the poll response for details
  • Verify the model supports video generation (output_modalities includes "video")
  • Ensure your prompt is appropriate and within model guidelines
  • Check that any reference images are accessible and in supported formats

Model not found?

  • Use the Video Models API or the Models page to find available video generation models
  • Verify the model slug is correct (e.g., google/veo-3.1)