Create Video
Starts a video render and answers 202 at once with the job; poll its polling_url, or pass callback_url to be notified. The request follows OpenRouter's video API, so the OpenRouter SDKs work by changing the base URL and key. OpenAI/Sora field names are accepted too: seconds for duration, size, and input_reference (an uploaded file in multipart/form-data, an https URL string, or {image_url}) for the first frame. GET /v1/videos/models lists the models with what each accepts.
Modes (minimax-h3): text only; frame_images with a first_frame, a last_frame or both; or input_references (up to 9 images, 3 videos and 3 audio clips, 12 in all). When both frame_images and input_references are sent, frame_images is used.
Media: an https URL or a base64 data URI. Images JPG, PNG, WEBP, HEIC or HEIF up to 30 MB; videos MP4 or MOV up to 50 MB, 2-15 s; audio WAV or MP3 up to 15 MB, 2-15 s.
Sizes (minimax-h3): 4 to 15 seconds at 24 fps, with stereo AAC audio. Send aspect_ratio or size:
aspect_ratio |
size |
|---|---|
16:9 (default) |
1344x768 |
9:16 |
768x1344 |
4:3 |
1024x768 |
3:4 |
768x1024 |
1:1 |
768x768 |
21:9 |
1536x672 |
Output: duration snaps to the model's frame grid, so a 4 s request is about 4.4 s; read output.duration. Videos have a generated soundtrack unless generate_audio is false.
Prompts are used as written. MiniMax's and fal's APIs rewrite prompts by default, so the same prompt can give a different video here.
Expected wait: while a job is pending, queue_position counts the jobs ahead of it for the same model. Once it starts, a minimax-h3 render takes about 3 seconds per second of video for text and frame jobs, and about 5 seconds per second with input_references: a 6 s text job is ready in about 20 s. At 2K a render takes about 3 times as long: a 15 s text job takes about 140 s. 4K adds SeedVR2's upscale of that 2K render, about 18 s per second of video (a 15 s text job takes about 7 minutes), plus any wait for a free upscaler, which progress does not count. progress is estimated from these times.
Quality (minimax-h3): quality picks a tier, the same in every mode. turbo (or auto, low; the default) uses H3's Turbo LoRA: 4 denoising steps, or 8 with input_references. standard (or medium) runs the full base model at 20 steps and bills 1.5 times the seconds; max (or high) runs 40 steps and bills 3 times; ultra runs 50 steps and bills 5 times. For finer control send num_inference_steps from 10 to 50 instead (OpenRouter's SDKs: provider. or .num_inference_steps); more steps take longer and cost more. Sending a tier and a different step count is a 400.
Billing: per second of requested duration at the model's price (pricing_skus in GET /v1/videos/models; standard_per_second, max_per_second and ultra_per_second are the tiers' prices, 2K_per_second and 4K_per_second the 2K and 4K prices), only when the job completes. standard bills 1.5 times the seconds, max 3 times and ultra 5 times; resolution: 2K and 4K (Turbo only) 3 times: 4K bills as the 2K it upscales. A raw num_inference_steps bills the tier whose step range holds it: 10 to 20 as standard, 21 to 40 as max, 41 to 50 as ultra (quality_ in GET /v1/videos/models). Billed seconds are rounded up to a whole second: a 5 s job at standard bills 8 s. usage.billed_seconds shows the result. Failed and cancelled jobs are not billed.
Guides: Async jobs, Webhooks, Render a video with webhooks, Write prompts for MiniMax-H3
Body
application/jsonA control another video model takes that this model does not have (guidance_scale, negative_prompt; minimax-h3 is CFG-distilled and has neither) is a 400 with metadata.error_type unsupported_, and so is lora or loras. Any other field the model does not read is accepted and listed in the job's warnings; the video is made without it.
-
model string required
-
prompt string required
Must be a string (a list or number is a 400).
at most 8000 characters -
duration integer
Seconds of video. minimax-h3 takes 4-15; default 6. A whole number sent as text (
"8") is accepted. -
seconds integer
OpenAI/Sora's name for
duration;durationwins when both are sent. -
resolution string
minimax-h3:
2Krenders the 768p preset and enlarges it 2x (16:9 is 2688x1536). It bills 3 times the seconds times thequalitytier, takes about 3 times as long, and runs at every tier:qualitystandard,maxorultra, or basenum_inference_steps, renders the 768p preset on the base weights before the same upscale.4Kis the 2K render enlarged 1.5x by SeedVR2 after the engine (16:9 is 4032x2304, the soundtrack kept): it bills as 2K (the upscale is free), runs at Turbo only (any other tier at 4K is a 400), and takes about 18 s more per second of video, plus any wait for the upscaler; the job'soutput.upscalesays it was applied.default 768p768p2K4K -
aspect_ratio stringdefault 16:916:99:164:33:41:121:9
-
size string
Width x height; an alternative to
aspect_ratio, and must agree with it when both are sent. The second six are 2K and the last six 4K (seeresolution).1344x768768x13441024x768768x1024768x7681536x6722688x15361536x26882048x15361536x20481536x15363072x13444032x23042304x40323072x23042304x30722304x23044608x2016 -
frame_images array of objectsat most 2 items
-
input_references array of objects
Reference media for the subject, style or sound. Ignored when
frame_imagesis sent. -
input_reference string or object
OpenAI/Sora's first frame, as an https URL (or base64 data URI) string or as
{image_url}. Ignored whenframe_imagesis sent. Any other type is a 400. -
generate_audio boolean
Strictly
trueorfalse(inmultipart/form-datathe texttrueorfalse); anything else is a 400.default true -
seed integer
-
num_inference_steps integer
minimax-h3: the number of denoising steps. Omit it for the Turbo LoRA (4 steps, or 8 with
input_references); 10 to 50 runs the full base model, which takes longer and bills thequalitytier whose step range holds the count: 10 to 20 asstandard(1.5x), 21 to 40 asmax(3x), 41 to 50 asultra(5x; see Billing). Sending the Turbo count itself changes nothing. Preferquality. Also accepted underprovider.options(seeprovider).range 4–50 -
quality string
minimax-h3: the quality tier, the same in every mode.
turbo(auto,low; the default) is the Turbo LoRA at 1x the price;standard(medium) is 20 base steps at 1.5x;max(high) is 40 base steps at 3x;ultrais 50 base steps at 5x. The job stores the tier's own name. Sendingnum_inference_stepstoo is a 400 unless it is the tier's count. Also accepted underprovider.options(seeprovider).turbostandardmaxultraautolowmediumhigh -
start_time_seconds number
minimax-h3: where to start reading each reference video in
input_references, in seconds. Also accepted underprovider.options(seeprovider).at least 0 -
callback_url string
An https URL notified on completion, failure, cancellation and expiry. See
GET /v1/webhooks/secret. -
provider object
OpenRouter's provider preferences. The routing fields (
order,only,ignore,sort,allow_fallbacks, ...) are accepted and ignored.optionscarries the model's own settings (quality,num_inference_steps,start_time_secondsfor minimax-h3;GET /v1/videos/modelslists each model'sallowed_) for clients that cannot add top-level fields. From OpenRouter's SDKs usepassthrough_ parameters options.stealth: they keep only the slugs on their closed list and drop any other,vultrincluded, without an error. The first form present wins, the top level before any option; a key the model does not declare is a 400 naming its path.
Body
multipart/form-dataResponses
Accepted. The job, pending, with its polling_url and queue_position.
application/json · video-job-payload
A field the model does not support or a malformed input. The message names the field. Fields are typed, not coerced; prompt must be a string, generate_audio a boolean (true or false), input_reference a URL string or an object - and a whole number may be sent as text ("20").
application/json · error-payload
The API key is missing, unknown or not active. Send it as Authorization: Bearer <key>.
application/json · error-payload
Unknown video model
application/json · error-payload
Too many videos for this model from your subscription. At most the model's limit at once may be pending or rendering, and at most its limit a minute may be created (the model's page in the docs gives both). Wait for Retry-After, then retry.
application/json · error-payload
The model has no valid capability spec at the moment and is not served.
application/json · error-payload
A media input is over its size limit
application/json · error-payload
curl https://api.vultrinference.com/v1/videos \
-H "Authorization: Bearer $VULTR_INFERENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "minimax-h3",
"prompt": "A red fox trots through fresh snow at dawn, breath steaming.",
"duration": 6,
"aspect_ratio": "16:9",
"callback_url": "https://example.com/hooks/video"
}'import os
import requests
response = requests.post(
"https://api.vultrinference.com/v1/videos",
headers={"Authorization": f"Bearer {os.environ['VULTR_INFERENCE_API_KEY']}"},
json={
"model": "minimax-h3",
"prompt": "A red fox trots through fresh snow at dawn, breath steaming.",
"duration": 6,
"aspect_ratio": "16:9",
"callback_url": "https://example.com/hooks/video",
},
)
print(response.json())const response = await fetch("https://api.vultrinference.com/v1/videos", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VULTR_INFERENCE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "minimax-h3",
"prompt": "A red fox trots through fresh snow at dawn, breath steaming.",
"duration": 6,
"aspect_ratio": "16:9",
"callback_url": "https://example.com/hooks/video"
}),
});
console.log(await response.json());{
"id": "video_3f2a9c1e7b4d5a6c8e0f1a2b",
"object": "video",
"model": "string",
"status": "pending",
"progress": 0,
"created_at": 1790000000,
"polling_url": "string"
}