Skip to main content
POST
Generate a video from text, from a first and optional last frame, from a reference video/image, or from a driving video and a character image
Send multipart/form-data with a first frame — as an uploaded file or a URL, never both — and no last frame. Supplying a first frame with no last frame is what selects this mode of POST /v1/videos, generating a Viggle-optimized MiniMax H3 video with native audio. This uses the same POST /v1/videos endpoint as Generate Video (from Text), Generate Video (from First-Last Frames and/or Text), Generate Video (from Reference Video/Image), and Using Viggle-Animate — which mode runs is selected by which fields you send, not by a separate parameter. A first frame cannot be combined with any reference or character-animation field.
Every generated video includes native audio — there’s no separate audio flag or field. Pricing (1 credit = $0.01): ⌈duration_s⌉ × the per-second rate for resolution — $0.01/sec (1 credit/second) at 480p/768p/1080p/2k for both low and high, rising to $0.05/sec (5 credits/second) at 4k. Image-conditioned generation costs the same as text-only for the same quality, resolution, and duration; aspect_ratio and enhance don’t affect price. See Pricing and retention.

Request parameters

Send multipart/form-data. Provide exactly one of first_frame_image or first_frame_image_url. Supplying both answers 400 INVALID_REQUEST — “supply only one of first_frame_image or first_frame_image_url”.

Image limits

These apply to first_frame_image and first_frame_image_url:
  • Size: up to 20 MiB per uploaded image; an image fetched from a URL field may be up to 30 MiB.
  • Format: detected from the image bytes, not the file extension or Content-Type — JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF.
  • Dimensions: no minimum or maximum. An image at or above 4K — long edge ≥ 3840 px or short edge ≥ 2160 px — is downscaled to fit within 1920×1080 (1080×1920 for portrait), keeping its aspect ratio.
An oversized or empty upload answers 400 INVALID_REQUEST — “invalid or oversized first_frame_image upload” (naming the field), and an upload that can’t be decoded answers “first_frame_image must be a valid image”. For the URL form, an image over the limit answers “failed to fetch first_frame_image_url: media exceeds size limit”, and one that can’t be decoded answers “first_frame_image_url is not a valid image”.

Response parameters

Returns 200 OK — an acceptance acknowledgment, not the final result.
This response deliberately carries none of the fields GET /v1/videos/{video_id} returns (stage, video_url, alpha_url, completed_at, error). See Get Video for the full shape once the video is processing or done.

Examples

Common errors

Next step

Use Get Video with the returned id to poll for the result.

Quick Start: First Frame to Video

Follow the complete create-and-poll flow.

Generate Video (from Text)

Generate from a prompt alone, with no frame image.

Generate Video (from First-Last Frames and/or Text)

Also anchor the end of the video on a last frame.

Generate Video (from Reference Video/Image)

Carry a subject or style from a reference video and/or up to 4 images.

Using Viggle-Animate

Apply a driving video’s motion and/or character images on a separate backend.

Authorizations

Authorization
string
header
required

Server-side SDK clients use a project API key. Remote MCP clients use an OAuth access token. Never expose a project API key in browser code.

Headers

X-Request-Id
string

Optional caller-supplied correlation ID, up to 128 characters. The service returns the effective value in the response header for tracing and support.

Required string length: 1 - 128
X-Viggle-Source
string

Optional source-channel label, up to 128 characters, used to attribute traffic to an SDK, integration, product surface, or internal workflow.

Required string length: 1 - 128

Body

multipart/form-data

Body of POST /v1/videos: H3 uses multipart/form-data; character animation also accepts application/json and application/x-www-form-urlencoded. Which fields are supplied selects the generation mode:

  • Neither first_frame_image/first_frame_image_url nor last_frame_image/last_frame_image_url nor any reference or character-animation field supplied: text-to-video.
  • A first frame supplied, no last frame: first-frame-to-video.
  • Both a first frame and a last frame supplied: first+last-frame-to-video.
  • Any of reference_video/reference_video_url/ reference_image/reference_image_url supplied: reference-video (omni-reference) generation.
  • driving_video/driving_video_url and/or character_image/ character_image_url/character_image_urls supplied: character-animation generation, dispatched to a separate backend from the four modes above. A driving video is required (image-only requests are not supported); image usage depends on enhance_mode and target tags as described below. It has no quality tier, no duration_s/resolution/ aspect_ratio/seed, and prompt is optional rather than required; see below and Generate Video (from Character Animation) for its own fields, pricing, and constraints.

Within a frame slot, supply at most one of the file and the URL form. Supplying both first_frame_image and first_frame_image_url (or both last_frame_image and last_frame_image_url) answers 400 INVALID_REQUEST with "supply only one of first_frame_image or first_frame_image_url" (or the last_frame_* equivalent). A last frame requires a first frame; supplying a last frame with no first frame answers 400 INVALID_REQUEST with "a last frame requires a first frame".

Reference-video mode is selected purely by whether any of the four reference fields is present — there is no separate source/mode parameter, and no error if you meant to but forgot: supplying none of reference_video/reference_video_url/reference_image/ reference_image_url simply generates text-to-video instead (the first bullet above), the same way omitting first_frame_image/ last_frame_image falls back to text-to-video rather than erroring. reference_video and reference_video_url are declared as arrays for forward compatibility, but at most 1 reference video is accepted today; supplying any combination of the two fields that adds up to more than 1 (two files, two URLs, or one of each) answers 400 INVALID_REQUEST with "at most 1 reference video(s) allowed". reference_image and reference_image_url may be mixed freely, but their combined count cannot exceed 4; going over answers 400 INVALID_REQUEST with "at most 4 reference images are allowed". Reference fields cannot be combined with first_frame_image/last_frame_image (file or URL form); doing so answers 400 INVALID_REQUEST with "reference_video/reference_image cannot be combined with first_frame_image/last_frame_image". The reference video itself (independent of duration_s, the target duration of the generated video) must be 0.5–600 seconds long and at least 64x64 with even width and height, the same constraints enforced on uploaded video elsewhere in this API, and at most 100 MiB whether uploaded or fetched from reference_video_url.

Frame and reference images (first_frame_image, last_frame_image, reference_image) may be up to 20 MiB each when uploaded, and up to 30 MiB when fetched from the matching *_url field. The format is detected from the image bytes — JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF — and there is no minimum or maximum dimension; an image at or above 4K (long edge >= 3840 px or short edge >= 2160 px) is downscaled to fit 1920x1080, keeping its aspect ratio. An oversized upload answers 400 INVALID_REQUEST with "invalid or oversized first_frame_image upload" (naming the field), an undecodable one with "first_frame_image must be a valid image"; a URL that can't be decoded answers "first_frame_image_url is not a valid image", and an unreadable reference video URL answers "reference_video_url is not a valid video".

Character-animation mode cannot be combined with quality or H3 frame/reference fields. For character animation, supply character images as character_image uploads or character_image_url/ character_image_urls (uploads and URLs cannot be combined in the same request).

A driving video is required: supply exactly one of driving_video (upload) or driving_video_url (URL). Image-only requests are not supported; omitting the video returns HTTP 400 INVALID_REQUEST before media staging or task admission, regardless of image count, prompt, or enhance_mode. One image replaces one target character. In planner (default) or normal mode, replacing 2 or 3 characters requires ordered <Character1>, <Character2> (and <Character3>) descriptions in prompt, one per image, describing targets in the source video. Without these tags, only the first image is used. In agent mode, 1-10 images are used in order as Character1..N; tags are optional. The driving video supplies the source motion.

For planner and normal, use a driving video 5-16 seconds long. For agent, use 5-60 seconds. Both uploads and URLs undergo API media validation with a 100 MiB limit. The API currently checks duration after truncating to whole seconds, accepting 5-60 whole seconds for all modes; this does not override the worker's 16-second limit in planner/normal. A longer video can be queued and then fail in those modes. Uploaded videos are staged to object storage; URL-form sources are also fetched by the worker.

Billed at ⌈duration_s⌉ × the per-second credit rate for resolution (currently 1 credit/second — $0.01/sec — at 480p, 768p, 1080p, and 2k, rising to 5 credits/second — $0.05/sec — at 4k; the same rate applies to both quality tiers). quality, aspect_ratio, and enhance do not affect price, and image/video-conditioned generation (first-frame, first-last-frame, or reference-video) costs the same as text-only for the same quality, resolution, and duration. Character-animation mode is billed at 1 credit/second instead: it reserves the driving video's measured duration rounded up. On completion the charge is settled against the finished video's duration, never above the reservation. It is not tied to duration_s; see Generate Video (from Character Animation).

Every generated video includes native audio; there is no separate audio flag or field.

prompt
string

Required for H3 generation. For character animation, planner/normal use ordered Character tags for multiple targets; agent reads the editing instruction directly. See the animation path descriptions above.

Minimum string length: 1
Example:

"A paper airplane gliding through a sunlit office"

quality
enum<string>

Generation quality tier. low generates faster, for quicker iteration; high generates slower but produces higher-fidelity output. Both tiers are billed at the same per-second rate for a given resolution — see resolution below. Required for every mode except character-animation, which has no quality tiers and rejects this field outright if supplied.

Available options:
low,
high
Example:

"low"

first_frame_image
file

First-frame image uploaded directly. Mutually exclusive with first_frame_image_url. Supplying either switches on first-frame-to-video mode. Cannot be combined with any reference_video/reference_image field. Up to 20 MiB; JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF, detected from the file contents. An image with a long edge of 3840 px or more, or a short edge of 2160 px or more, is downscaled to fit 1920x1080, keeping its aspect ratio.

first_frame_image_url
string<uri>

Publicly reachable URL of the first-frame image; the service fetches and re-hosts it. Mutually exclusive with first_frame_image. Cannot be combined with any reference_video/reference_image field. The fetched image may be up to 30 MiB, in the same formats and with the same downscaling as the upload form.

last_frame_image
file

Last-frame image uploaded directly. Mutually exclusive with last_frame_image_url. Valid only alongside a first frame. Cannot be combined with any reference_video/reference_image field. Up to 20 MiB; JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF, detected from the file contents. An image with a long edge of 3840 px or more, or a short edge of 2160 px or more, is downscaled to fit 1920x1080, keeping its aspect ratio.

last_frame_image_url
string<uri>

Publicly reachable URL of the last-frame image; the service fetches and re-hosts it. Mutually exclusive with last_frame_image. Valid only alongside a first frame. Cannot be combined with any reference_video/reference_image field. The fetched image may be up to 30 MiB, in the same formats and with the same downscaling as the upload form.

reference_video
file[]

Reference video uploaded directly, for reference-video (omni-reference) generation. Declared as an array for forward compatibility, but at most 1 is accepted today — combined with reference_video_url. Not required if at least one reference image is supplied instead. Up to 100 MiB, in any container with a readable video stream (MP4, MOV, WebM, etc.). Must be 0.5–600 seconds long and at least 64x64 with even width/height. Cannot be combined with first_frame_image/last_frame_image.

Maximum array length: 1
reference_video_url
string<uri>[]

Publicly reachable URL of the reference video; the service fetches and re-hosts it. Declared as an array for forward compatibility, but at most 1 is accepted today — combined with reference_video. Same size, duration, and resolution constraints as reference_video.

Maximum array length: 1
reference_image
file[]

Reference images uploaded directly, for reference-video (omni-reference) generation. Up to 4 total, combined with reference_image_url. Can be freely mixed with reference_image_url. Up to 20 MiB; JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF, detected from the file contents. An image with a long edge of 3840 px or more, or a short edge of 2160 px or more, is downscaled to fit 1920x1080, keeping its aspect ratio.

Maximum array length: 4
reference_image_url
string<uri>[]

Publicly reachable URLs of reference images; the service fetches and re-hosts each one. Up to 4 total, combined with reference_image. Can be freely mixed with reference_image. Each fetched image may be up to 30 MiB, in the same formats and with the same downscaling as reference_image.

Maximum array length: 4
driving_video
file

Source video upload for character animation, at most 100 MiB. Use 5-16 seconds for planner/normal, or 5-60 seconds for agent. Cannot be combined with driving_video_url. Character animation requires exactly one of driving_video or driving_video_url; image-only requests return 400 INVALID_REQUEST.

driving_video_url
string<uri>

Source video URL for character animation, under the same limits as driving_video. Cannot be combined with driving_video. Character animation requires exactly one of driving_video or driving_video_url; image-only requests return 400 INVALID_REQUEST.

character_image
file[]

Ordered character image uploads, at most 20 MiB per image. Requires a driving video. Image usage depends on enhance_mode and prompt tags as described above.

Maximum array length: 10
character_image_url
string<uri>[]

One character image URL. Requires a driving video. Use character_image_urls for multiple images in JSON. Cannot be combined with character_image_urls or uploads.

Maximum array length: 10
character_image_urls
string<uri>[]

Ordered character image URLs. Requires a driving video. Image usage depends on enhance_mode and prompt tags as described above. Cannot be combined with character_image_url or uploads.

Maximum array length: 10
enhance_mode
enum<string>
default:planner

How a character animation prepares the driving video for the render. planner writes the prompt and paints the pinned frames; normal repaints the first frame and uses a fixed prompt; agent hands the whole edit (plan, paints, renders, review, final cut) to an AI agent. Omit it for planner. Character animation only: H3 generation ignores it and uses enhance.

Available options:
planner,
normal,
agent
priority
integer
default:1000

Admission-queue priority tier, shared by H3 and character-animation modes. Defaults to 1000 (top tier) — most callers never need to set this. Must be one of the server's configured tiers (currently 1000 or 0). An unsupported integer answers 400 INVALID_REQUEST with "invalid render request: unsupported priority 500" (ending with the value sent) in H3 modes, or "unsupported priority" in character-animation mode; a non-integer answers "priority must be an integer".

duration_s
number
default:5

H3 generation only. Requested video duration in seconds, between 5 and 15 inclusive. Defaults to 5. Does not set character animation duration; that comes from the driving video.

Required range: 5 <= x <= 15
resolution
enum<string>
default:768p

Output resolution tier — also selects the per-second credit rate charged for this request. 480p, 768p, 1080p, and 2k are billed at $0.01/sec (1 credit/second); 4k is billed at $0.05/sec (5 credits/second).

Available options:
480p,
768p,
1080p,
2k,
4k
aspect_ratio
enum<string>
default:16:9

Output aspect ratio.

Available options:
16:9,
9:16,
1:1,
4:3,
3:4,
21:9
seed
integer<int64>

Deterministic generation seed. Omit for a random seed. H3 modes only — not applicable to character-animation mode.

Required range: x >= 0
watermark
boolean
default:false

Whether to burn in a Viggle watermark.

enhance
boolean
default:true

Whether to run a low-effort AI Planner pass that rewrites only prompt before generation; any supplied frame or reference video/image is left unchanged. H3 modes only — not applicable to character-animation mode. Defaults to true; pass false to use prompt exactly as given. Does not affect price.

Response

Video generation accepted and queued.

Acceptance acknowledgment for POST /v1/videos, shared by all five generation modes. This is a queued confirmation, not the final result — poll GET /v1/videos/{video_id} (or watch it via GET /v1/videos) until status reaches ready, then read video_url from that response.

id
string
required

Public video ID — vid_-prefixed for the four H3 modes, anim_-prefixed for character-animation mode.

Minimum string length: 1
status
enum<string>
required

Lifecycle state at acceptance time; always queued.

Available options:
queued,
processing,
ready,
failed,
cancelled
progress
integer | null
required

Always null on acceptance.

Required range: 0 <= x <= 100
created_at
string<date-time> | null
required

ISO 8601 creation timestamp, second precision.