Skip to main content
OpenRouter provides a dedicated asynchronous API for generating videos from text prompts, start and end frame images, and multimodal references. Because video generation takes significantly longer than text or image generation (typically 30 seconds to several minutes), requests follow an asynchronous submit-poll-download lifecycle.

Endpoints

The Video Generation API consists of four endpoints:

End-to-end workflow

Video generation follows three sequential steps:
  1. Submit: Send a generation request with a video model and prompt to POST /api/v1/videos. Receive a job ID (id) and relative polling URL (polling_url).
  2. Poll: Query GET /api/v1/videos/{jobId} at regular intervals (recommended: every 10–30 seconds) until status becomes completed or failed. Alternatively, supply a callback_url to receive a webhook notification upon completion.
  3. Download: Once completed, retrieve the generated video using either the signed storage URL (urls[0]) or the authenticated content proxy endpoint (unsigned_urls[0]).
In a multi-user app, one API key can poll, download, and continue every job the app created. Record which end user owns each job ID, and check that ownership before you act on a job ID supplied by a client.

cURL example

TypeScript example

Python example

Job lifecycle and statuses

The status field on GET /api/v1/videos/{jobId} reflects the current state of generation:

Downloading outputs: urls vs unsigned_urls

When a job reaches status: "completed", the response payload provides two distinct ways to access the generated video:

1. Pre-signed storage URLs (urls)

  • Authentication: No Authorization header required.
  • Validity: Temporary, valid until the Unix timestamp in expires_at.
  • Use case: Safe for direct client browser playback (<video src={urls[0]}>) or direct download links without exposing your OpenRouter API key.
  • Availability: Present when OpenRouter’s edge media storage has cached the output. Because these URLs grant direct read access while valid, treat them as bearer secrets.
  • Multi-user apps: Your API key can read every job your app created, so before returning urls to an end user, check that the requested job belongs to that user. Otherwise one user can play another user’s video by passing its job ID.

2. Authenticated content endpoint (unsigned_urls)

  • Authentication: Requires Authorization: Bearer <OPENROUTER_API_KEY>.
  • Validity: Permanent for as long as the generation record is retained.
  • Use case: Server-side processing, archival pipelines, or backend streaming proxies when urls is absent or expired.
  • Streaming in web apps: Because browser <video> tags cannot attach custom Authorization headers, never send unsigned_urls directly to the client browser with client-side API keys. Instead, implement a thin server-side proxy route in your web framework (e.g., Next.js app/api/videos/[id]/route.ts) that verifies the user session, checks that the requested job belongs to that user (your API key can read every job your app created), fetches GET /api/v1/videos/{jobId}/content using your server’s OPENROUTER_API_KEY, and pipes the video/mp4 response back to the client.

Request parameters

POST /api/v1/videos accepts the following parameters:

Image-to-video (frame_images)

To animate an existing image into a video, supply one or two frame images in frame_images. Supported frame types are first_frame (starts the clip from this image) and last_frame (ends the clip at this image):

Reference-to-video (input_references)

Reference-to-video guides character consistency, aesthetic style, or scene composition without locking the video to an exact starting pixel frame:

Model discovery

Query the dedicated Video Models endpoint to retrieve supported parameters, resolutions, durations, and pricing SKUs for every video model currently deployed:
Each model entry includes capability matrices and pricing units:

Webhooks and signature verification

When callback_url is configured on the request (or set as the workspace default in Workspace Settings), OpenRouter sends an HTTPS POST payload upon job completion, failure, expiration, or cancellation.

Webhook payload example

Verifying signatures

Setting a callback_url doesn’t create a signing secret. To get one, open your workspace settings and select Generate signing secret under Webhook signing secret; video and batch deliveries share it. With a secret configured, OpenRouter includes an X-OpenRouter-Signature header on every delivery containing a timestamp (t) and HMAC-SHA256 hash (v1). Without one, deliveries are unsigned and can’t be told apart from a forged request, so reject any delivery whose signature header is missing or invalid with a non-2xx response:
Verify signatures using the raw, unparsed request body:
Each delivery also carries an X-OpenRouter-Idempotency-Key header of the form <jobId>-<status>. Failed deliveries are retried, so use the key to deduplicate them. Record it in the same transaction that applies the event, return a non-2xx response if processing fails so the retry can recover, and acknowledge a key you’ve already recorded without acting on it again.

Zero Data Retention (ZDR) policy

Video generation is not eligible for Zero Data Retention (ZDR). Because video generation is asynchronous, provider endpoints must temporarily retain the generated media artifact so your application can retrieve it via the polling or content download endpoints. If your account or API key enforces ZDR mode, video generation requests will be rejected with an HTTP 400 error.