Use this guide when you need to add text-to-video generation to an app with OpenRouter.
By the end, your implementation should submit a video job, poll for completion, and download the generated MP4.
Before you start
You need:
- An OpenRouter API key available as
OPENROUTER_API_KEY
- Node.js 20 or newer
- A video model slug, such as
google/veo-3.1-lite
If you haven’t chosen a model yet, read Choose a Video Generation Model first. It helps you pick one based on clip duration, output shape, input type, audio, provider controls, and cost.
Use the API reference pages as the source of truth for exact fields:
Before wiring the submit path, confirm that the selected model supports the duration, resolution, and aspect ratio you plan to send. For example, the model used below returned this metadata during QA:
Model metadata output:
Submitting POST /api/v1/videos starts a real video generation job and may spend OpenRouter credits.
Step 1: Submit the video job
Add a server-side submit step that sends POST /api/v1/videos with the chosen model, prompt, duration, resolution, and aspect ratio. Store the returned job object because the next step needs its id, status, and polling_url. Validate those values against the selected model’s supported fields from the video models API before submitting. Unsupported values return a 400 with the supported values.
Adapt this submit shape in the server route, queue, or worker that owns video generation:
A successful submit returns a job id. The QA run produced this shape:
Step 2: Poll until the job finishes
Add polling in a server route, queue worker, or background job. Treat completed as success. Treat failed, cancelled, and expired as terminal errors, and keep a bounded retry limit so the worker can’t run forever.
Polling logic:
Completed poll output:
Step 3: Download the video
When polling returns completed, download the first generated asset. The content endpoint is the most direct path; if you use a URL from unsigned_urls, include the bearer token when the URL points back to the OpenRouter API.
In Node.js, import writeFile from node:fs/promises or replace the file write with the storage layer your app uses.
The QA run saved the finished video after polling completed:
If your completed job includes unsigned_urls, this is the adaptable download shape:
Step 4: Put the sequence in your app
Keep the submit, poll, and download steps in the part of your app that owns long-running work. This complete example keeps the pieces together so you can adapt the sequence into a server route, queue, or worker:
Check your work
The job should move from pending or in_progress to completed, and the implementation should produce a playable MP4 from the completed job.