> ## 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.

# Get Video

> Retrieve the full state of a Render, generated video, or video upscale through one unified endpoint.

`GET /v1/videos/{video_id}` accepts a character+motion Render ID (`render_`), a MiniMax H3 generation ID (`vid_`), a character-animation generation ID (`anim_`), or a [2x video upscale](/v1/api-reference/videos/super-resolution) ID (`vsr_`), and returns its current durable state. Poll every 3–5 seconds until the status is terminal, or use [Watch Render](/v1/api-reference/renders/events) for a push-based alternative on a Render-sourced ID.

This endpoint replaces the retired `GET /v1/renders/{render_id}`.

<Note>
  `GET /v1/renders/{render_id}` no longer accepts `GET` — it now answers `405 Method Not Allowed`, not `404`, because other methods remain registered on that path. A router only answers `404` when a path has no method registered at all; here it still has at least one, so the retired method 405s instead. If your integration checked for a `404` to detect that the old route was gone, accept `405` too, or switch straight to this endpoint.
</Note>

## Request parameters

| Parameter | Type | Required | Description |
| - | - | :-: | - |
| `video_id` | string | Yes | Full public video ID: `render_...`, `vid_...`, `anim_...`, or `vsr_...`. Poll with the same value every 3–5 seconds until the video reaches a terminal status. |

## Response parameters

Returns `200 OK` with a Video object.

| Field | Type | Always present | Description |
| - | - | :-: | - |
| `id` | string | Yes | Requested video ID. |
| `status` | string | Yes | `queued`, `processing`, `ready`, `failed`, or `cancelled`. An H3 (`vid_`) video never reports `cancelled` — a backend cancellation or timeout surfaces as `failed`. |
| `stage` | string or null | Yes | Populated only when this is a Render-sourced video and `status` is `processing`; `null` otherwise, and always `null` for an H3 video. The server returns `null` for every non-`processing` status by design — there is no `stage: "ready"`. |
| `progress` | integer or null | Yes | Progress from 0 to 100, or `null`. |
| `video_url` | string or null | Yes | Downloadable output once ready; `null` until then. |
| `alpha_url` | string or null | Yes | Render-only: populated only when a Render was created with `background_mode=transparent` and is `ready`. Always `null` for an H3 video. |
| `created_at` | string or null | Yes | Render-sourced timestamps carry nanosecond precision; H3-sourced timestamps carry second precision. |
| `completed_at` | string or null | Yes | See **Completion timing** below. |
| `error` | object or null | Yes | Structured failure details when `status` is `failed`. |
| `seed` | integer | H3 only | The seed actually used for generation — a caller-supplied value echoed back, or the value generated when [Generate Video](/v1/api-reference/videos/create-from-text) omitted one. Present only on an H3-origin video (`vid_` prefix); absent — not `null` — on Render-, character-animation-, and upscale-origin videos. Generated seeds usually exceed JavaScript's safe-integer range — see the warning below. |
| `queue_position` | integer or null | `vid_` and `anim_` | Exact number of tasks ahead while the video is `queued`. `null` once processing starts and at terminal states. Omitted entirely for `render_` and `vsr_` videos. |
| `estimated_wait_seconds` | integer or null | `vid_` and `anim_` | Rough estimate based on fleet-wide average render time and current queue/dispatch state — while `queued`, the expected time until the video finishes; while `processing`, the remaining average render time. `null` at terminal states, for queued work below the top priority tier (new top-tier work can keep preempting it), or when no bounded estimate is available. Omitted entirely for `render_` and `vsr_` videos. |

<Warning>
  A generated `seed` is a random 63-bit integer (0 to 2^63 − 1), so it almost always exceeds `Number.MAX_SAFE_INTEGER` (2^53 − 1). JavaScript's `JSON.parse` silently rounds it — `4271960385017522688` in the example below would come back as a different number, and resubmitting that value won't reproduce the video. Read the response with a 64-bit-safe JSON parser (for example, `json-bigint`) if you need the exact value, or supply your own `seed` no larger than 2^53 − 1 when creating the video.
</Warning>

This response does not include `links` — unlike the Render object returned by [Render Video (from Character and/or Motion)](/v1/api-reference/renders/create), a video fetched here carries no `self`/`events`/`download` shortcut. Use the same `video_id` for further Get Video calls, and [Download Render](/v1/api-reference/renders/download) for a Render-sourced ID.

## Completion timing

On a Render-sourced video, `completed_at` can lag `status` reaching `ready` by up to roughly 30 seconds before it backfills — it isn't a permanent gap. Decide whether a video is finished by checking `status == "ready"` or whether `video_url` is populated, not by whether `completed_at` is non-null.

### Render-sourced example

```json theme={null}
{
  "id": "render_a1b2c3",
  "status": "ready",
  "stage": null,
  "progress": 100,
  "video_url": "https://assets.viggle.ai/render_a1b2c3.mp4",
  "alpha_url": null,
  "created_at": "2026-08-25T09:12:03.123456789Z",
  "completed_at": "2026-08-25T09:13:47Z",
  "error": null
}
```

### H3-sourced example

```json theme={null}
{
  "id": "vid_3f2a9c",
  "status": "ready",
  "stage": null,
  "progress": 100,
  "video_url": "https://storage.googleapis.com/...signed...",
  "alpha_url": null,
  "created_at": "2026-08-24T09:12:03Z",
  "completed_at": "2026-08-24T09:13:47Z",
  "error": null,
  "seed": 4271960385017522688,
  "queue_position": null,
  "estimated_wait_seconds": null
}
```

### Character-animation-sourced example

```json theme={null}
{
  "id": "anim_7c1e4b",
  "status": "ready",
  "stage": null,
  "progress": 100,
  "video_url": "https://storage.googleapis.com/...signed...",
  "alpha_url": null,
  "created_at": "2026-09-09T09:12:03Z",
  "completed_at": "2026-09-09T09:13:47Z",
  "error": null,
  "queue_position": null,
  "estimated_wait_seconds": null
}
```

No `seed` field — it's H3-only. `queue_position` and `estimated_wait_seconds` are present on both, `null` once the video is terminal.

### Failed example

```json theme={null}
{
  "id": "render_a1b2c3",
  "status": "failed",
  "stage": null,
  "progress": null,
  "video_url": null,
  "alpha_url": null,
  "created_at": "2026-08-25T09:12:03.123456789Z",
  "completed_at": "2026-08-25T09:13:50Z",
  "error": {
    "code": "TASK_FAILED",
    "message": "The render could not be completed.",
    "retryable": false,
    "request_id": "req_123abc",
    "details": {},
    "remediation": { "action": "contact_support", "retry_after_ms": null }
  }
}
```

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://apis.viggle.ai/v1/videos/render_a1b2c3" -H "Authorization: Bearer $VIGGLE_API_KEY"
  ```

  ```python Python theme={null}
  import os, requests
  response = requests.get("https://apis.viggle.ai/v1/videos/render_a1b2c3", headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"})
  response.raise_for_status()
  video = response.json()
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://apis.viggle.ai/v1/videos/render_a1b2c3", { headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` } });
  const video = await response.json();
  ```

  ```go Go theme={null}
  req, _ := http.NewRequest("GET", "https://apis.viggle.ai/v1/videos/render_a1b2c3", nil)
  req.Header.Set("Authorization", "Bearer "+os.Getenv("VIGGLE_API_KEY"))
  resp, err := http.DefaultClient.Do(req)
  if err != nil { panic(err) }
  defer resp.Body.Close()
  ```
</CodeGroup>


## OpenAPI

````yaml openapi.yaml GET /v1/videos/{video_id}
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/{video_id}:
    parameters:
      - $ref: '#/components/parameters/VideoId'
      - $ref: '#/components/parameters/RequestId'
      - $ref: '#/components/parameters/SourceChannel'
    get:
      tags:
        - Videos
      summary: Get the current durable state of a video
      description: |
        Accepts a Render ID (`render_` prefix), an H3 generation ID
        (`vid_` prefix), a character-animation generation ID (`anim_`), or
        a video-super-resolution ID (`vsr_`), and returns its full current
        state. This endpoint replaces
        the retired `GET /v1/renders/{render_id}`.
      operationId: getVideo
      responses:
        '200':
          description: Current video state.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Video'
        '401':
          $ref: '#/components/responses/V1Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    VideoId:
      name: video_id
      in: path
      required: true
      description: >-
        Public video ID owned by the caller — a Render (`render_` prefix), H3
        generation (`vid_`), character-animation generation (`anim_`), or
        super-resolution task (`vsr_`).
      schema:
        type: string
        minLength: 1
      example: render_123
    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
  headers:
    RequestId:
      description: Stable request identifier for support and tracing.
      schema:
        type: string
  schemas:
    Video:
      description: |
        Unified, read-only full-state resource for a finished
        character+motion Render (`render_` prefix), a MiniMax H3
        video generation (`vid_` prefix), or a character-animation
        generation (`anim_` prefix). It carries no `links` field — unlike
        the Render object returned by `POST /v1/renders`, there is no
        unified `self`/`events`/`download` shortcut here.

        `stage` is populated only when this is a Render-sourced video and
        `status` is `processing`; it is null in every other case, including
        every H3 and character-animation video. `alpha_url` is populated
        only on a Render-sourced video created with
        `background_mode=transparent` once it is `ready`; it is always null
        otherwise. `seed` is H3-only — present (not present-but-null; simply
        absent from the response) only on an H3-origin video, never on a
        Render-sourced or character-animation one.
      type: object
      additionalProperties: false
      required:
        - id
        - status
        - stage
        - progress
        - video_url
        - alpha_url
        - created_at
        - completed_at
        - error
      properties:
        id:
          type: string
          description: >-
            Public video ID — a Render (`render_` prefix), an H3 generation
            (`vid_` prefix), or a character-animation generation (`anim_`
            prefix).
          minLength: 1
        status:
          description: >-
            Overall lifecycle. `ready`, `failed`, and `cancelled` are terminal
            states.
          allOf:
            - $ref: '#/components/schemas/ResourceStatus'
        stage:
          type: string
          description: >-
            Coarse pipeline phase, Render-only. Null except while a
            Render-sourced video's `status` is `processing`; always null for an
            H3 video.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/RenderStage'
        progress:
          type: integer
          description: >-
            Best-effort completion percentage from 0 through 100; null when the
            source pipeline reports no estimate.
          nullable: true
          minimum: 0
          maximum: 100
        video_url:
          type: string
          description: >-
            Short-lived URL of the completed video; null until ready or when no
            output was produced.
          nullable: true
          format: uri
        alpha_url:
          type: string
          description: >-
            Render-only alpha/mask video URL for transparent-background output;
            null on every H3 video and on any Render not created with
            `background_mode=transparent`.
          nullable: true
          format: uri
        created_at:
          type: string
          description: >-
            Creation timestamp. Render-sourced videos report nanosecond
            precision; H3 videos report second precision.
          nullable: true
          format: date-time
        completed_at:
          type: string
          description: |
            Terminal-state timestamp; null while the video is active. On a
            Render-sourced video this can lag `status` reaching `ready` by
            up to roughly 30 seconds before it is backfilled — use `status`
            (or check `video_url`), not the presence of this field, to
            detect completion.
          nullable: true
          format: date-time
        error:
          type: object
          description: >-
            Structured failure details when `status` is `failed`; otherwise
            null.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ErrorBody'
        seed:
          type: integer
          format: int64
          description: >-
            H3-only — present only on an H3-origin video, absent (not null) on
            Render-, character-animation-, and super-resolution-sourced ones.
            The seed actually used for generation — a caller-supplied value
            echoed back, or the value generated when `POST /v1/videos` omitted
            one. Generated seeds are random 63-bit integers (0 to 2^63−1), so
            they usually exceed 2^53 − 1 — parse this field with a 64-bit-safe
            JSON decoder; JavaScript's `JSON.parse` silently rounds it.
        queue_position:
          type: integer
          nullable: true
          minimum: 0
          description: >-
            Present on H3 (`vid_`) and character-animation (`anim_`) videos.
            Exact number of tasks ahead while the video is queued. Present as
            `null` once processing starts and at terminal states; absent
            entirely for Render- and super-resolution-origin videos.
        estimated_wait_seconds:
          type: integer
          nullable: true
          minimum: 0
          description: >-
            Present on H3 (`vid_`) and character-animation (`anim_`) videos.
            Approximate remaining wait in seconds, based on fleet-wide average
            render time and current queue/dispatch state — while queued, the
            expected wait to finish; while processing, the remaining average
            render time. Present as `null` at terminal states, for queued work
            below the top priority tier (which new top-tier work can keep
            preempting), or when no bounded estimate is available; absent
            entirely for Render- and super-resolution-origin videos.
    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
    RenderStage:
      description: |
        A coarse progress hint. `analyzing`, `rendering`, and `finishing` are
        emitted for renders created through the `multipart/form-data` form;
        every other value belongs to the draft-based pipeline. Treat an
        unrecognized value as "in progress" rather than failing.
      type: string
      enum:
        - queued
        - preparing
        - generating
        - finalizing
        - ready
        - failed
        - cancelled
        - analyzing
        - rendering
        - finishing
    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'
    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'
    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
  responses:
    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'
    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'
    NotFound:
      description: Draft or render not found.
      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.