Docs
Get an API key
API reference›Videos

Create Video

POST /v1/videos Models: Video View .md

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. 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 3 times the seconds; max (or high) runs 40 steps and bills 5 times. For finer control send num_inference_steps from 10 to 50 instead (OpenRouter's SDKs: provider.options.stealth.quality 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 and max_per_second are the tiers' prices), only when the job completes. standard bills 3 times the seconds and max 5 times. A raw num_inference_steps bills steps / 6 times the seconds, never more than the next tier up (19 steps bill as standard), rounded up to a whole second: a 10 s job at 25 steps bills 42 s. usage.billed_seconds shows the result. Failed and cancelled jobs are not billed.

A 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_parameter, 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 7000 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; duration wins when both are sent.

  • resolution string
  • aspect_ratio string
    default 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.

    1344x768768x13441024x768768x1024768x7681536x672
  • frame_images array of objects
    at most 2 items
    3 fields
    • type string required
      image_url
    • image_url object required
      1 field
      • url string required

        An https URL or a base64 data URI.

    • frame_type string required
      first_framelast_frame
  • input_references array of objects

    Reference media for the subject, style or sound. Ignored when frame_images is sent.

    5 fields
    • type string required
      image_urlvideo_urlaudio_url
    • image_url object
      1 field
      • url string required

        An https URL or a base64 data URI.

    • video_url object
      1 field
      • url string required

        An https URL or a base64 data URI.

    • audio_url object
      1 field
      • url string required

        An https URL or a base64 data URI.

    • role string

      driving and control are reserved for models that support them.

      default referencereference
  • input_reference string or object

    OpenAI/Sora's first frame, as an https URL (or base64 data URI) string or as {image_url}. Ignored when frame_images is sent. Any other type is a 400.

    One of 2
    • string
    • object
      • image_url string
  • generate_audio boolean

    Strictly true or false (in multipart/form-data the text true or false); 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 steps / 6 times the seconds, capped at the next quality tier up (see Billing). Sending the Turbo count itself changes nothing. Prefer quality. Also accepted under provider.options (see provider).

    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 3x; max (high) is 40 base steps at 5x. The job stores the tier's own name. Sending num_inference_steps too is a 400 unless it is the tier's count. Also accepted under provider.options (see provider).

    turbostandardmaxautolowmediumhigh
  • start_time_seconds number

    minimax-h3: where to start reading each reference video in input_references, in seconds. Also accepted under provider.options (see provider).

    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. options carries the model's own settings (quality, num_inference_steps, start_time_seconds for minimax-h3; GET /v1/videos/models lists each model's allowed_passthrough_parameters) for clients that cannot add top-level fields. From OpenRouter's SDKs use options.stealth: they keep only the slugs on their closed list and drop any other, vultr included, 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.

Fields as multipart/form-data
  • model string required
  • prompt string required
  • seconds string
  • size string
  • input_reference string (binary)

    The first frame.

  • generate_audio string
    truefalse
  • callback_url string

Accepted. The job, pending, with its polling_url and queue_position.

application/json · video-job-payload

18 fields
  • id string required
  • object string required
    video
  • model string required
  • status string required

    OpenAI's SDKs (requests with X-Stainless-Lang) see queued for pending, and cancelled and expired as failed with that reason as error.code; everyone else sees the states below.

    • pending: queued; see queue_position.
    • in_progress: rendering; see progress.
    • completed: the video is ready at unsigned_urls until expires_at. The only billed status.
    • failed: see error. Not billed.
    • cancelled: cancelled with DELETE /v1/videos/{id}. Not billed.
    • expired: a completed job past its 7-day retention; the video is deleted.
    pendingqueuedin_progresscompletedfailedcancelledexpired
  • progress integer required

    Estimated percent complete while rendering.

  • created_at integer required
  • completed_at integer
  • expires_at integer

    When the video is deleted.

  • polling_url string required
  • seconds string

    The requested duration.

  • size string
  • queue_position integer

    Jobs ahead of this one for the same model, while pending.

  • unsigned_urls array of strings

    Where to download each output (send your API key).

  • output object

    What was rendered.

    6 fields
    • duration number
    • fps number
    • width integer
    • height integer
    • has_audio boolean
    • count integer
  • warnings array of objects

    What the request sent that was not read. Always present; an empty list says nothing was ignored.

    3 fields
    • code string

      unknown_parameter: not a video request field, so it was not read. Codes are open: ignore one you do not know.

    • field string
    • message string
  • usage object
    6 fields
    • cost number

      USD.

    • output_seconds integer

      Seconds of video requested.

    • billed_seconds integer

      Seconds billed at the model's price; more than output_seconds for the standard (3x) and max (5x) quality tiers and for base num_inference_steps (steps / 6, capped at the next tier up).

    • input_image_count integer
    • input_video_seconds number
    • input_audio_seconds number
  • error string or object

    Why a failed job failed. A string beside error_code; for OpenAI's SDKs an object with code and message.

    One of 2
    • string
    • object
      • code string

        The same values as error_code, and cancelled or expired for a job in that state.

        invalid_requestpayload_too_largetimeoutprovider_errorserver_errorcancelledexpired
      • message string
  • error_code string
    • invalid_request: an input could not be used, for example a media URL that could not be fetched or a file of the wrong type. Fix the request before sending it again.
    • payload_too_large: a media input was over its size limit.
    • timeout: the render took too long.
    • provider_error: the render failed or was interrupted on our side. Sending the same request again is safe.
    • server_error: the job could not run, for example because its model or API key was removed.
    invalid_requestpayload_too_largetimeoutprovider_errorserver_error
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"
  }'
Response · 202
{
    "id": "video_3f2a9c1e7b4d5a6c8e0f1a2b",
    "object": "video",
    "model": "string",
    "status": "pending",
    "progress": 0,
    "created_at": 1790000000,
    "polling_url": "string"
}