> ## 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 or an H3 text-to-video generation through one unified endpoint.

`GET /v1/videos/{video_id}` accepts either a character+motion Render ID (`render_` prefix, from [Render Video (from Character and/or Motion)](/v1/api-reference/renders/create)) or a MiniMax H3 text-to-video generation ID (`vid_` prefix, from [Generate Video (from Text)](/v1/api-reference/videos/create-from-text), [First Frame](/v1/api-reference/videos/create-from-first-frame), or [First-Last Frames](/v1/api-reference/videos/create-from-first-last-frame)) 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 returned by Render Video (from Character and/or Motion) or List Videos — `render_...` or `vid_...`. 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`.                                                                                                                                                                                  |
| `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`.                                                                                                                                                                                       |

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
}
```

### 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 text-to-video (`vid_` prefix), and read the
      unified view over every video the caller owns — H3 generations and
      character+motion Renders (`render_` prefix) — merged into one
      resource.
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 either a Render ID (`render_` prefix) or an H3 generation ID
        (`vid_` prefix) 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) or an
        H3 text-to-video generation (`vid_` prefix).
      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) or a MiniMax H3
        text-to-video generation (`vid_` 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 video. `alpha_url` is populated only on a Render-sourced
        video created with `background_mode=transparent` once it is
        `ready`; it is always null on an H3 video.
      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) or an H3 generation
            (`vid_` 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'
    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
    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.

````