> ## Documentation Index
> Fetch the complete documentation index at: https://docs.viggle.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate Video (from First Frame and/or Text)

> Generate a MiniMax H3 video anchored on a starting frame, uploaded directly or by URL.

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)](/v1/api-reference/videos/create-from-text), [Generate Video (from First-Last Frames and/or Text)](/v1/api-reference/videos/create-from-first-last-frame), [Generate Video (from Reference Video/Image)](/v1/api-reference/videos/create-from-reference-video), and [Using Viggle-Animate](/v1/api-reference/videos/create-from-character-animation) — 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.

<Note>
  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](/v1/pricing).
</Note>

## Request parameters

Send `multipart/form-data`.

| Parameter | Type | Required | Default | Description |
| - | - | :-: | - | - |
| `prompt` | string | Yes | — | Non-empty text description of the desired video. Still required even with a first frame supplied. |
| `quality` | string | Yes | — | `low` for faster generation and quicker iteration, or `high` for higher-fidelity output. Both tiers are billed at the same per-second rate for a given `resolution`. |
| `first_frame_image` | file | One of | — | First-frame image uploaded directly. Supply exactly one of `first_frame_image` or `first_frame_image_url`. |
| `first_frame_image_url` | string (URI) | One of | — | Publicly reachable URL of the first-frame image; the service fetches and re-hosts it. Supply instead of `first_frame_image`. |
| `duration_s` | number | No | `5` | Requested video duration in seconds, 5–15 inclusive; defaults to 5. Rounded up to determine the credit charge. |
| `resolution` | string | No | `768p` | `480p`, `768p`, `1080p`, `2k`, or `4k`. `4k` is billed at **$0.05/sec (5 credits/second)**; the rest are billed at **$0.01/sec (1 credit/second)**. |
| `aspect_ratio` | string | No | `16:9` | `16:9`, `9:16`, `1:1`, `4:3`, `3:4`, or `21:9`. Does not affect price. |
| `seed` | integer | No | — | ≥ 0. Omit for a random seed. |
| `watermark` | boolean | No | `false` | Whether to burn in a Viggle watermark. |
| `enhance` | boolean | No | `true` | Whether to run a low-effort AI Planner pass that rewrites `prompt` before generation — the supplied first frame is unchanged. Pass `false` to use `prompt` exactly as given. Does not affect price. |
| `priority` | integer | No | `1000` | Admission-queue priority tier. Must be one of the server's configured tiers (currently `1000` or `0`). Most callers never need to set this. |

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.

| Field | Type | Always present | Description |
| - | - | :-: | - |
| `id` | string | Yes | Public video ID, `vid_`-prefixed. |
| `status` | string | Yes | Always `queued` on acceptance. |
| `progress` | integer or null | Yes | Always `null` on acceptance. |
| `created_at` | string | Yes | ISO 8601 creation timestamp, second precision. |

```json theme={null}
{
  "id": "vid_3f2a9c",
  "status": "queued",
  "progress": null,
  "created_at": "2026-08-24T09:12:03Z"
}
```

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](/v1/api-reference/videos/get) for the full shape once the video is processing or done.

## Examples

<CodeGroup>
  ```bash cURL (file upload) theme={null}
  curl https://apis.viggle.ai/v1/videos \
    -H "Authorization: Bearer $VIGGLE_API_KEY" \
    -F prompt="camera slowly zooms out" \
    -F quality=high \
    -F first_frame_image=@first.png
  ```

  ```bash cURL (URL) theme={null}
  curl https://apis.viggle.ai/v1/videos \
    -H "Authorization: Bearer $VIGGLE_API_KEY" \
    -F prompt="camera slowly zooms out" \
    -F quality=high \
    -F first_frame_image_url=https://example.test/first.png
  ```

  ```python Python theme={null}
  import os, requests
  with open("first.png", "rb") as image:
      response = requests.post(
          "https://apis.viggle.ai/v1/videos",
          headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
          data={"prompt": "camera slowly zooms out", "quality": "high"},
          files={"first_frame_image": image},
      )
  response.raise_for_status()
  video = response.json()
  ```

  ```javascript JavaScript theme={null}
  const form = new FormData();
  form.append("prompt", "camera slowly zooms out");
  form.append("quality", "high");
  form.append("first_frame_image", firstFrameFile);
  const response = await fetch("https://apis.viggle.ai/v1/videos", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
    body: form,
  });
  const video = await response.json();
  ```
</CodeGroup>

## Common errors

| Error | Cause |
| - | - |
| `400 INVALID_REQUEST` — "supply only one of first\_frame\_image or first\_frame\_image\_url" | Both the file and URL form of the first frame supplied together. |
| `400 INVALID_REQUEST` — "enhance must be a boolean" | `enhance` supplied with a value that isn't parseable as a boolean. |
| `400 INVALID_REQUEST` — "invalid render request: unsupported priority 500" | `priority` set to an integer outside the server's configured tiers (currently `1000` or `0`); the message ends with the value you sent (here `500`). |
| `400 INVALID_REQUEST` — "priority must be an integer" | `priority` isn't parseable as an integer. |

## Next step

Use [Get Video](/v1/api-reference/videos/get) with the returned `id` to poll for the result.

<CardGroup cols={3}>
  <Card title="Quick Start: First Frame to Video" icon="rocket" href="/v1/guides/quickstart-first-frame-to-video">
    Follow the complete create-and-poll flow.
  </Card>

  <Card title="Generate Video (from Text)" icon="text" href="/v1/api-reference/videos/create-from-text">
    Generate from a prompt alone, with no frame image.
  </Card>

  <Card title="Generate Video (from First-Last Frames and/or Text)" icon="images" href="/v1/api-reference/videos/create-from-first-last-frame">
    Also anchor the end of the video on a last frame.
  </Card>

  <Card title="Generate Video (from Reference Video/Image)" icon="clapperboard" href="/v1/api-reference/videos/create-from-reference-video">
    Carry a subject or style from a reference video and/or up to 4 images.
  </Card>

  <Card title="Using Viggle-Animate" icon="person-running" href="/v1/api-reference/videos/create-from-character-animation">
    Apply a driving video's motion and/or character images on a separate backend.
  </Card>
</CardGroup>


## OpenAPI

````yaml openapi.yaml POST /v1/videos
openapi: 3.0.3
info:
  title: Viggle API
  description: Generate AI-powered character animation videos
  version: 2.0.0
  contact:
    name: Viggle Support
    url: https://viggle.ai
servers:
  - url: https://apis.viggle.ai
    description: Production server
security:
  - bearerAuth: []
tags:
  - name: Renders
    description: Prepare inputs, create renders, observe progress, and retrieve results.
  - name: Credits
    description: Read the credit balance available to the calling principal.
  - name: Characters
    description: |
      Create, list, inspect, and delete reusable character assets. `type`
      selects whether creation also extracts a 3D vsplat; export its
      download URL separately once ready.
  - name: Motions
    description: |
      Create, list, inspect, and delete reusable motion assets, and import one
      from an official motion template. `type` selects whether creation also
      extracts or generates a 3D animation; export its download URL
      separately once ready.
  - name: Videos
    description: >
      Generate a MiniMax H3 video from text, frames, or references (`vid_`

      prefix) or a character-animation video from a character image and/or
      driving video

      (`anim_` prefix), and read the unified view over every video the

      caller owns — H3 generations, character-animation generations, and

      character+motion Renders (`render_` prefix) — merged into one

      resource.
  - name: Images
    description: |
      Viggle Image — generate 1–6 PNG images from a text prompt with the
      `qwen` model, optionally guided by up to 8 reference images
      (`img_` prefix), and retrieve them by ID.
paths:
  /v1/videos:
    post:
      tags:
        - Videos
      summary: >-
        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
      description: >
        Generates a Viggle-optimized MiniMax H3 video with native audio, or

        (for character-animation mode) a character-animation video on a

        separate backend. `multipart/form-data` for every mode;

        character-animation mode also accepts a plain `application/json`

        body. The fields supplied select one of five generation modes:


        - Neither frame field nor any reference or character-animation
          field supplied: text-to-video from `prompt` alone.
        - `first_frame_image`/`first_frame_image_url` 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, carrying the subject/style of a reference video and/or
          up to 4 reference images into the new video. Mutually exclusive
          with the frame fields.
        - `driving_video`/`driving_video_url` and/or `character_image`/
          `character_image_url`/`character_image_urls` supplied:
          character-animation generation — animates up to 4 character
          images, or with an optional driving video, replaces up to 5
          people in it with the supplied characters.
          Mutually exclusive with every field above, including `quality`.
          See `CreateVideoForm` and `Generate Video (from Character
          Animation)`.

        `quality=low` generates faster for quicker iteration; `quality=high`

        produces higher-fidelity output. Both tiers are billed at the same

        per-second rate for a given `resolution`, and `enhance` does not

        affect price either — see `CreateVideoForm` below.

        Character-animation mode has no `quality` tier and is billed at

        $0.01/sec (1 credit/second) of the driving video's duration,

        rounded up, instead — or a flat 11 credits without a driving

        video.


        All five modes answer `200` with the same minimal acceptance shape;

        poll `GET /v1/videos/{video_id}` for the final result.
      operationId: createVideo
      parameters:
        - $ref: '#/components/parameters/RequestId'
        - $ref: '#/components/parameters/SourceChannel'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/CreateVideoForm'
      responses:
        '200':
          description: Video generation accepted and queued.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoCreateResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/V1Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    RequestId:
      name: X-Request-Id
      in: header
      required: false
      description: >-
        Optional caller-supplied correlation ID, up to 128 characters. The
        service returns the effective value in the response header for tracing
        and support.
      schema:
        type: string
        minLength: 1
        maxLength: 128
    SourceChannel:
      name: X-Viggle-Source
      in: header
      required: false
      description: >-
        Optional source-channel label, up to 128 characters, used to attribute
        traffic to an SDK, integration, product surface, or internal workflow.
      schema:
        type: string
        minLength: 1
        maxLength: 128
  schemas:
    CreateVideoForm:
      description: |
        Body of `POST /v1/videos`, `multipart/form-data` only (character-
        animation mode below also accepts a plain `application/json` body —
        see `Generate Video (from Character Animation)`). 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 optional. Without
          one, up to 4 character images are accepted, all references of one
          character; with one, up to 5 are accepted, each replacing one
          person in the driving video. 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 any
        frame/reference field above) — doing so answers
        `400 INVALID_REQUEST` with "driving_video_url/character_image_url
        cannot be combined with quality". A driving video is optional; when
        supplied, use `driving_video` (an uploaded file) or
        `driving_video_url`, not both. It is checked against a 5–15 second
        (inclusive) duration window (truncated to whole seconds first, so
        15.9s is accepted as 15s), on top of the same at-least-64x64 and
        even-dimension checks. At least one character image is required, as
        `character_image` uploads or values supplied through
        `character_image_url`/`character_image_urls`
        — uploads and URL fields cannot be combined ("supply character
        images as uploads or as character_image_url/character_image_urls,
        not both"), `character_image_url`/`character_image_urls` remain
        mutually exclusive with each other ("supply only one of
        character_image_url or character_image_urls"). Up to 4 images are
        accepted without a driving video, and up to 5 with one; going over
        answers `400 INVALID_REQUEST` with "at most 4 character images are
        allowed" (or "at most 5 ..." with a driving video).

        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: with a driving video it reserves the
        driving video's measured duration rounded up (5–16 credits); without
        one it reserves a flat 11 credits. 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.
      type: object
      properties:
        prompt:
          type: string
          minLength: 1
          description: >-
            Text description of the desired video. Required and non-empty for
            text, first-frame, first+last-frame, and reference-video modes.
            Optional (and merely a style/content hint, not enforced non-empty)
            for character-animation mode.
          example: A paper airplane gliding through a sunlit office
        quality:
          type: string
          enum:
            - low
            - high
          description: >-
            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.
          example: low
        first_frame_image:
          type: string
          format: binary
          description: >-
            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:
          type: string
          format: uri
          description: >-
            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:
          type: string
          format: binary
          description: >-
            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:
          type: string
          format: uri
          description: >-
            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:
          type: array
          maxItems: 1
          items:
            type: string
            format: binary
          description: >-
            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`.
        reference_video_url:
          type: array
          maxItems: 1
          items:
            type: string
            format: uri
          description: >-
            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`.
        reference_image:
          type: array
          maxItems: 4
          items:
            type: string
            format: binary
          description: >-
            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.
        reference_image_url:
          type: array
          maxItems: 4
          items:
            type: string
            format: uri
          description: >-
            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`.
        driving_video:
          type: string
          format: binary
          description: >-
            Optional driving video uploaded directly for character-animation
            generation. Mutually exclusive with `driving_video_url`. When
            present, the request may carry up to 5 character images, each
            replacing one person in the video; it is validated for 5–15 second
            duration, at least 64x64, and even dimensions, then staged to object
            storage.
        driving_video_url:
          type: string
          format: uri
          description: >-
            Optional `https://` driving-video URL for character-animation
            generation. Mutually exclusive with `driving_video`. When present,
            the request may carry up to 5 character images, each replacing one
            person in the video; it must be 5–15 seconds long, at least 64x64,
            with even dimensions.
        character_image:
          type: array
          maxItems: 5
          items:
            type: string
            format: binary
          description: >-
            Character reference images uploaded directly for character-animation
            generation. Up to 4 are accepted without a driving video, or 5 when
            a driving video is present. Mutually exclusive with URL-form
            character images.
        character_image_url:
          type: array
          maxItems: 5
          items:
            type: string
            format: uri
          description: >-
            Repeatable character reference image `https://` URL. Up to 4 are
            accepted without a driving video, or 5 when a driving video is
            present. Mutually exclusive with `character_image_urls` and uploaded
            character images.
        character_image_urls:
          type: array
          maxItems: 5
          items:
            type: string
            format: uri
          description: >-
            Same as `character_image_url`, supplied as one JSON-array field. Up
            to 4 are accepted without a driving video, or 5 when a driving video
            is present. Mutually exclusive with `character_image_url` and
            uploaded character images.
        priority:
          type: integer
          description: >-
            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".
          default: 1000
        duration_s:
          type: number
          minimum: 5
          maximum: 15
          default: 5
          description: >-
            Requested video duration in seconds, between 5 and 15 inclusive.
            Defaults to 5.
        resolution:
          type: string
          enum:
            - 480p
            - 768p
            - 1080p
            - 2k
            - 4k
          default: 768p
          description: >-
            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).
        aspect_ratio:
          type: string
          enum:
            - '16:9'
            - '9:16'
            - '1:1'
            - '4:3'
            - '3:4'
            - '21:9'
          default: '16:9'
          description: Output aspect ratio.
        seed:
          type: integer
          format: int64
          minimum: 0
          description: >-
            Deterministic generation seed. Omit for a random seed. H3 modes only
            — not applicable to character-animation mode.
        watermark:
          type: boolean
          default: false
          description: Whether to burn in a Viggle watermark.
        enhance:
          type: boolean
          default: true
          description: >-
            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.
    VideoCreateResponse:
      description: |
        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.
      type: object
      additionalProperties: false
      required:
        - id
        - status
        - progress
        - created_at
      properties:
        id:
          type: string
          description: >-
            Public video ID — `vid_`-prefixed for the four H3 modes,
            `anim_`-prefixed for character-animation mode.
          minLength: 1
        status:
          description: Lifecycle state at acceptance time; always `queued`.
          allOf:
            - $ref: '#/components/schemas/ResourceStatus'
        progress:
          type: integer
          description: Always null on acceptance.
          nullable: true
          minimum: 0
          maximum: 100
        created_at:
          type: string
          description: ISO 8601 creation timestamp, second precision.
          nullable: true
          format: date-time
    ResourceStatus:
      description: |
        The public lifecycle shared by every asynchronous resource. It carries
        the same values as `RenderStatus`.
      type: string
      enum:
        - queued
        - processing
        - ready
        - failed
        - cancelled
    ErrorResponse:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          description: >-
            Top-level draft-flow error payload containing the stable code,
            message, retry guidance, correlation ID, and error-specific details.
          allOf:
            - $ref: '#/components/schemas/ErrorBody'
    ErrorBody:
      type: object
      additionalProperties: false
      required:
        - code
        - message
        - retryable
        - request_id
        - details
        - remediation
      properties:
        code:
          description: Stable error category from the draft-based render error vocabulary.
          allOf:
            - $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
          description: >-
            Human-readable explanation suitable for logs or presentation to a
            developer.
        retryable:
          type: boolean
          description: >-
            Whether retrying the operation without changing its semantic input
            may succeed.
        request_id:
          type: string
          description: >-
            Correlation identifier for tracing and support. Include it when
            reporting the failure.
        details:
          type: object
          description: Error-specific structured context; available keys depend on `code`.
          additionalProperties: true
        remediation:
          description: Suggested recovery action and optional retry delay.
          allOf:
            - $ref: '#/components/schemas/ErrorRemediation'
    ErrorCode:
      description: |
        The failure vocabulary of the draft-based render flow. The resource
        operations project the same vocabulary onto the lower_snake_case codes
        described by `ResourceError`.
      type: string
      enum:
        - UNAUTHENTICATED
        - INVALID_CREDENTIAL
        - FORBIDDEN
        - INVALID_REQUEST
        - INVALID_CHARACTER
        - INVALID_MOTION
        - UNSUPPORTED_MEDIA
        - CONTENT_POLICY_VIOLATION
        - UPLOAD_REQUIRED
        - UPLOAD_MISMATCH
        - UPLOAD_EXPIRED
        - DRAFT_NOT_FOUND
        - DRAFT_ALREADY_CONSUMED
        - RENDER_NOT_FOUND
        - RENDER_NOT_CANCELLABLE
        - CHARACTER_NOT_FOUND
        - MOTION_NOT_FOUND
        - MOTION_NOT_READY
        - MOTION_TEMPLATE_NOT_FOUND
        - AVATAR_NOT_FOUND
        - ANIMATION_NOT_FOUND
        - EXTRACTION_UNAVAILABLE
        - EXTRACTION_FAILED
        - IDEMPOTENCY_KEY_REUSED
        - INSUFFICIENT_CREDITS
        - RATE_LIMITED
        - SERVICE_BUSY
        - INTERNAL_ERROR
        - NOT_FOUND
        - TASK_FAILED
    ErrorRemediation:
      type: object
      additionalProperties: false
      required:
        - action
        - retry_after_ms
      properties:
        action:
          type: string
          description: >-
            Suggested machine-readable or human-readable next action, such as
            retrying later, uploading media again, or correcting input.
        retry_after_ms:
          type: integer
          description: >-
            Recommended delay in milliseconds before retrying; null when no
            timed retry is advised.
          nullable: true
          format: int64
          minimum: 0
  headers:
    RequestId:
      description: Stable request identifier for support and tracing.
      schema:
        type: string
  responses:
    BadRequest:
      description: Invalid request.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    V1Unauthorized:
      description: Missing, invalid, or expired credential.
      headers:
        WWW-Authenticate:
          schema:
            type: string
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    PaymentRequired:
      description: Insufficient credits.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Credential does not grant access to this resource.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: Rate limit exceeded.
      headers:
        Retry-After:
          schema:
            type: integer
            minimum: 0
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: Unexpected server error.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailable:
      description: Service temporarily unavailable.
      headers:
        Retry-After:
          schema:
            type: integer
            minimum: 0
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key or OAuth access token
      description: |
        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.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.