Video Generation
Generate videos with an OpenAI-compatible async API and signed completion callbacks
Video Generation
LLMGateway supports asynchronous video generation through an OpenAI-compatible POST /v1/videos flow.
Currently available models:
- Veo 3.1 through
avalanche(1080p, 4k) andgoogle-vertex(720p, 1080p, 4k) - Seedance 2.0, Seedance 2.0 Fast, and Seedance 1.5 Pro through
bytedance(720p, 1080p) - KLING v3.0 and KLING v3.0 Turbo through
atlascloud(720p, 1080p; KLING v3.0 also 4k)
You can find the current list of video-capable models on our models page with the video filter enabled or programmatically through the /v1/models endpoint.
What Works Today
POST /v1/videosGET /v1/videos/{video_id}GET /v1/videos/{video_id}/content- Optional signed callbacks with
callback_urlandcallback_secret
Request Format
LLMGateway currently supports a focused subset of the OpenAI video API.
Supported fields
| Field | Type | Required | Description |
|---|---|---|---|
model | string | yes | Any video-capable model from the filtered models page |
prompt | string | yes | Text prompt for the video |
seconds | number | yes | Duration in seconds. Supported values depend on the model (see below) |
size | string | no | widthxheight, limited to the sizes supported by the selected model and provider |
audio | boolean | no | Whether to include audio in the output (default true). Only honored when the model supports both audio and silent output |
image | object | no | Optional first frame for image-to-video generation (see first/last frame inputs below) |
last_frame | object | no | Optional ending frame when image is provided (see first/last frame inputs below) |
reference_images | array | no | One to three provider-specific image inputs |
input_reference | object | no | Alias for one or more reference_images |
reference_videos | array | no | One to three reference video HTTPS URLs (Seedance 2.0 only, see below) |
reference_audios | array | no | One to three reference audio HTTPS URLs (Seedance 2.0 only, see below) |
callback_url | string | no | LLMGateway extension for completion webhooks |
callback_secret | string | no | LLMGateway extension used to sign webhook deliveries |
Sizes and durations by model
| Model family | Provider | Supported sizes | Supported durations |
|---|---|---|---|
| Veo 3.1 | google-vertex | 1280x720, 720x1280, 1920x1080, 1080x1920, 3840x2160, 2160x3840 | 4, 6, 8, 10 |
| Veo 3.1 | avalanche | 1920x1080, 1080x1920, 3840x2160, 2160x3840 | 8 |
| Seedance 2.0 / 2.0 Fast / 1.5 Pro | bytedance | 1280x720, 720x1280, 1920x1080, 1080x1920 | 5, 10 |
| KLING v3.0 | atlascloud | 1280x720, 720x1280, 1920x1080, 1080x1920, 3840x2160, 2160x3840 | 5, 10 |
| KLING v3.0 Turbo | atlascloud | 1280x720, 720x1280, 1920x1080, 1080x1920 | 5, 10 |
Requests return 400 when the selected provider cannot serve the requested size or seconds. Seedance and KLING v3.0 derive aspect_ratio from the requested size (16:9 for landscape, 9:16 for portrait).
KLING v3.0 Turbo always generates audio and does not support audio: false; silent requests return a 400. Use KLING v3.0 (kling-v3-0) when you need silent output.
First/last frame inputs
Frame inputs interpolate a video between a starting frame and an optional ending frame. You provide the first frame as image and, optionally, the ending frame as last_frame. The gateway tags each one with the correct role for the provider, so you don't set roles yourself.
| Field | Required | Accepted input | Available on |
|---|---|---|---|
image | for frame mode | HTTPS URL or base64 data URL | Seedance 2.0 (bytedance), KLING v3.0 / Turbo (atlascloud), Veo 3.1 (google-vertex, avalanche), minimax, xai |
last_frame | no (needs image) | HTTPS URL or base64 data URL | Seedance 2.0 (bytedance), KLING v3.0 / Turbo (atlascloud), Veo 3.1 (google-vertex, avalanche) |
Rules and limits
- Seedance scope. Frame inputs are supported on Seedance 2.0 and Seedance 2.0 Fast (
seedance-2-0,seedance-2-0-fast). Sendingimage/last_frameto Seedance 1.5 Pro or any other ByteDance model returns a400. - KLING scope. Frame inputs are supported on KLING v3.0 and KLING v3.0 Turbo (
kling-v3-0,kling-v3-0-turbo). The gateway uploads base64 frames to AtlasCloud's media endpoint automatically, so both HTTPS URLs and base64 data URLs are accepted. last_framerequiresimage. Providinglast_framewithoutimagereturns a400.- Not combinable with references. First/last frame inputs (
image,last_frame) cannot be combined with reference inputs (reference_images,input_reference,reference_videos,reference_audios).
Example (Seedance 2.0)
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"prompt": "Morph smoothly from the first frame into the last frame",
"seconds": 5,
"size": "1280x720",
"image": { "image_url": "https://example.com/first-frame.png" },
"last_frame": { "image_url": "https://example.com/last-frame.png" }
}'Example (KLING v3.0 image-to-video)
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-v3-0",
"prompt": "Animate the scene with gentle camera motion",
"seconds": 5,
"size": "1280x720",
"image": { "image_url": "https://example.com/first-frame.png" }
}'Reference-guided generation (Seedance 2.0)
Seedance 2.0 (seedance-2-0, seedance-2-0-fast) can generate a video that is guided by reference images, videos, and audio — sometimes called omni-reference. You attach references as top-level fields in the same POST /v1/videos payload; the gateway forwards each one to the provider tagged with the correct role, so you don't set roles yourself.
| Reference type | Payload field | Count | Accepted input | Available on |
|---|---|---|---|---|
| Image | reference_images (input_reference alias) | 1–3 | HTTPS URL or base64 data URL | Seedance 2.0, Veo 3.1 (google-vertex, avalanche) |
| Video | reference_videos | 1–3 | HTTPS URL only | Seedance 2.0 |
| Audio | reference_audios | 1–3 | HTTPS URL only | Seedance 2.0 |
Each list item accepts either a bare URL string or an object form:
reference_images:"https://…/subject.png"or{ "image_url": "https://…/subject.png" }reference_videos:"https://…/motion.mp4"or{ "video_url": "https://…/motion.mp4" }reference_audios:"https://…/track.mp3"or{ "audio_url": "https://…/track.mp3" }
You can mix all three reference types in one request. The prompt can be a light instruction (for example "adapt this to show more detail") — the references drive the result.
Rules and limits
- HTTPS only for video and audio.
reference_videosandreference_audiosmust be publicly reachable HTTPS URLs (the provider fetches them). base64 data URLs are rejected for video/audio; images may be HTTPS URLs or base64 data URLs. - Reference video resolution. Seedance requires reference video frames to be at least ~409,600 pixels (roughly 480p or larger). Low-resolution clips such as 360p are rejected with a
400. - Not combinable with frames. Reference inputs (
reference_images,reference_videos,reference_audios) cannot be combined with the first/last frame inputs (image,last_frame). - Provider scope. Reference videos and audio are only supported on Seedance 2.0 models; sending them to other models returns a
400. KLING v3.0 does not support any reference inputs (reference_images,reference_videos,reference_audios); use first/last frame inputs instead. - Moderation still applies. The output is subject to the provider's content moderation. Blocked generations finish as
failedand are logged with acontent_filterfinish reason.
Examples
Reference images only (subjects / style):
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"prompt": "The subject walks through a neon-lit market at night",
"seconds": 5,
"size": "1280x720",
"reference_images": [
{ "image_url": "https://example.com/subject.png" },
{ "image_url": "https://example.com/style.png" }
]
}'Reference video only (motion / scene — let the clip drive the output):
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"prompt": "adapt this to show more detail",
"seconds": 5,
"size": "1280x720",
"reference_videos": ["https://example.com/reference-motion.mp4"]
}'All three reference types combined:
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"prompt": "The subject performs the choreography from the reference video",
"seconds": 5,
"size": "1280x720",
"reference_images": [
{ "image_url": "https://example.com/subject.png" }
],
"reference_videos": [
"https://example.com/reference-motion.mp4"
],
"reference_audios": [
"https://example.com/reference-track.mp3"
]
}'Not supported yet
- multipart uploads
nvalues other than1- remix/list/delete video endpoints
Create a Video
Video generation requires at least $1.00 in available organization credits before the job is submitted upstream.
Pricing is per second of generated video. For Seedance and KLING v3.0, enabling audio can increase the per-second rate on models that price audio and video separately.
Veo 3.1:
| Model | Provider | Supported sizes | Price |
|---|---|---|---|
veo-3.1-generate-preview | google-vertex | 1280x720, 720x1280, 1920x1080, 1080x1920 | $0.40 / second |
veo-3.1-fast-generate-preview | google-vertex | 1280x720, 720x1280, 1920x1080, 1080x1920 | $0.15 / second |
veo-3.1-generate-preview | google-vertex | 3840x2160, 2160x3840 | $0.60 / second |
veo-3.1-fast-generate-preview | google-vertex | 3840x2160, 2160x3840 | $0.35 / second |
veo-3.1-generate-preview | avalanche | 1920x1080, 1080x1920 | $0.40 / second |
veo-3.1-fast-generate-preview | avalanche | 1920x1080, 1080x1920 | $0.15 / second |
veo-3.1-generate-preview | avalanche | 3840x2160, 2160x3840 | $0.60 / second |
veo-3.1-fast-generate-preview | avalanche | 3840x2160, 2160x3840 | $0.35 / second |
Seedance (ByteDance):
| Model | Provider | Resolution | With audio | Video only |
|---|---|---|---|---|
seedance-2-0 | bytedance | 720p | $0.1512 / second | $0.1512 / second |
seedance-2-0 | bytedance | 1080p | $0.3402 / second | $0.3402 / second |
seedance-2-0-fast | bytedance | 720p | $0.121 / second | $0.121 / second |
seedance-2-0-fast | bytedance | 1080p | $0.2722 / second | $0.2722 / second |
seedance-1-5-pro | bytedance | 720p | $0.05184 / second | $0.02592 / second |
seedance-1-5-pro | bytedance | 1080p | $0.1166 / second | $0.05832 / second |
KLING (AtlasCloud):
| Model | Provider | Resolution | With audio | Video only |
|---|---|---|---|---|
kling-v3-0 | atlascloud | 720p | $0.126 / second | $0.084 / second |
kling-v3-0 | atlascloud | 1080p | $0.168 / second | $0.112 / second |
kling-v3-0 | atlascloud | 4k | $0.42 / second | $0.42 / second |
kling-v3-0-turbo | atlascloud | 720p | $0.168 / second | n/a (audio only) |
kling-v3-0-turbo | atlascloud | 1080p | $0.21 / second | n/a (audio only) |
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-generate-preview",
"prompt": "A cinematic aerial shot flying above a rainforest waterfall at sunrise",
"seconds": 8,
"size": "1920x1080"
}'Example response:
{
"id": "v_123",
"object": "video",
"model": "veo-3.1-generate-preview",
"status": "queued",
"progress": 0,
"created_at": 1773600000,
"completed_at": null,
"expires_at": null,
"error": null
}Retrieve Job Status
curl "https://api.llmgateway.io/v1/videos/v_123" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY"Typical statuses:
queuedin_progresscompletedfailedcanceledexpired
avalanche requests for 1080p and 4k stay in_progress until the upgraded output is ready. The gateway keeps polling the upstream upgrade endpoints and only marks the job completed once the requested resolution is available.
google-vertex follows Vertex AI's long-running operation flow. The gateway submits Veo generation with predictLongRunning, polls with fetchPredictOperation, and streams the final bytes through the gateway content endpoint once the operation is done.
bytedance uses the ModelArk /contents/generations/tasks endpoint. The gateway submits the job, polls the upstream task status, and exposes the final video bytes through the gateway content endpoint once the task succeeds.
atlascloud uses the AtlasCloud /api/v1/model/generateVideo endpoint and polls /api/v1/model/prediction/{id} for status. The gateway resolves the upstream KLING variant (standard, turbo, or 4k) and task type (text-to-video or image-to-video) from your request, then streams the final video bytes through the gateway content endpoint once the prediction completes.
Download the Video
Once the job is complete, stream the resulting video bytes from the content endpoint:
curl "https://api.llmgateway.io/v1/videos/v_123/content" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
--output video.mp4Signed Callbacks
LLMGateway can notify your application when the job reaches a terminal state.
curl -X POST "https://api.llmgateway.io/v1/videos" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-fast-generate-preview",
"prompt": "A slow-motion close-up of waves crashing against black volcanic rock",
"seconds": 8,
"callback_url": "https://example.com/webhooks/video",
"callback_secret": "whsec_your_secret_here"
}'Delivery behavior
- Callbacks are sent only for terminal states in v1
- Event types are
video.completedandvideo.failed - Deliveries retry with exponential backoff on network errors, timeouts, and non-2xx responses
- Each attempt is recorded internally in the webhook delivery log table
Headers
webhook-idwebhook-timestampwebhook-signature
Signature format
LLMGateway signs the string:
{webhook-id}.{webhook-timestamp}.{raw-request-body}using HMAC-SHA256 with your callback_secret, then sends:
webhook-signature: v1,{base64_signature}Verification example
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyWebhook(
body: string,
webhookId: string,
webhookTimestamp: string,
webhookSignature: string,
secret: string,
) {
const expected = createHmac("sha256", secret)
.update(`${webhookId}.${webhookTimestamp}.${body}`)
.digest("base64");
const provided = webhookSignature.replace(/^v1,/, "");
return timingSafeEqual(Buffer.from(expected), Buffer.from(provided));
}Related Docs
How is this guide?
Last updated on