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

> Retrieve the current state of an image generation job, and its PNG download URLs once ready.

`GET /v1/images/{image_id}` returns the current state of a job created by [Generate Image](/v1/api-reference/images/create) — the same Image object the create request answered with. Poll every 2–3 seconds until `status` is `ready` or `failed`, then download each PNG from `images[].url`.

You can only read jobs created with the same API key. An unknown ID, or one created by a different key, answers `404 NOT_FOUND` — the two cases are deliberately indistinguishable.

## Request parameters

| Parameter | Type | Required | Description |
| - | - | :-: | - |
| `image_id` | string | Yes | Full image job ID returned by Generate Image, `img_` prefix. |

## Response parameters

Returns `200 OK` with an Image object.

| Field | Type | Description |
| - | - | - |
| `id` | string | Image job ID, `img_` prefix. |
| `status` | string | `queued`, `processing`, `ready`, or `failed` — see [Status and errors](#status-and-errors). |
| `model` | string | Model used; currently `qwen`. |
| `progress` | integer or null | Share of the requested images completed: `0` while `queued`, 0–99 while `processing`, `100` when `ready`, `null` when `failed`. |
| `images` | array | Always empty before `ready`. Once `ready`, all `n` images in request order. |
| `images[].url` | string or null | Signed download URL of the PNG, valid for **1 hour**. Fetch the job again for a fresh one. `null` once the file has been deleted at the end of the [retention period](#data-retention). |
| `images[].width` / `images[].height` | integer | Actual size in pixels — see [Output sizes](/v1/api-reference/images/create#output-sizes). |
| `images[].seed` | integer | Seed this image was actually generated with. |
| `created_at` | string or null | Creation time, RFC 3339. |
| `completed_at` | string or null | End time; set once the job is `ready` or `failed`. |
| `error` | object or null | Failure details, only when `status` is `failed`. |

### Ready example

Signature query parameters shortened:

```json theme={null}
{
  "id": "img_b16a190d-2d44-41a0-8056-ef68183c3b9e",
  "status": "ready",
  "model": "qwen",
  "progress": 100,
  "images": [
    {"url": "https://storage.googleapis.com/viggle/image-generation/b16a190d-2d44-41a0-8056-ef68183c3b9e/0.png?X-Goog-Signature=...", "width": 1376, "height": 768, "seed": 0},
    {"url": "https://storage.googleapis.com/viggle/image-generation/b16a190d-2d44-41a0-8056-ef68183c3b9e/1.png?X-Goog-Signature=...", "width": 1376, "height": 768, "seed": 1}
  ],
  "created_at": "2026-10-12T08:20:00Z",
  "completed_at": "2026-10-12T08:20:22Z",
  "error": null
}
```

### Failed example

```json theme={null}
{
  "id": "img_b16a190d-2d44-41a0-8056-ef68183c3b9e",
  "status": "failed",
  "model": "qwen",
  "progress": null,
  "images": [],
  "created_at": "2026-10-12T08:20:00Z",
  "completed_at": "2026-10-12T08:35:00Z",
  "error": {
    "code": "SERVICE_BUSY",
    "message": "The image service is busy; try again later.",
    "retryable": true,
    "request_id": null,
    "details": {},
    "remediation": { "action": "retry", "retry_after_ms": null }
  }
}
```

## Status and errors

A job only moves forward: `queued` → `processing` → `ready` or `failed`. It is never `cancelled`. A job either produces all `n` images or fails as a whole — it never returns a partial set.

| `status` | Meaning |
| - | - |
| `queued` | Accepted and waiting for a GPU. At peak times a job can stay here for a while. |
| `processing` | Generating, one image at a time; `progress` rises as each image finishes. |
| `ready` | All images are done and `images` is filled in. |
| `failed` | Failed; see `error`. |

`error.code` on a failed job:

| `code` | `retryable` | When | What to do |
| - | :-: | - | - |
| `SERVICE_BUSY` | `true` | The generation service is busy or temporarily unavailable, or the job didn't finish within 15 minutes. | Create a new job with the same parameters later. |
| `TASK_FAILED` | `true` | Any other generation or upload failure. | Create a new job. If it keeps happening, contact us with the job `id`. |
| `INVALID_REQUEST` | `false` | The model rejected the request — for example, a reference image it can't use. | Change the parameters or reference images, then try again. |

A failed job is refunded in full, even if some images had already been generated before it failed. Retrying means creating a new job, which reserves its own credits.

HTTP errors from this endpoint:

| HTTP | `code` | Meaning |
| - | - | - |
| `401` | `UNAUTHENTICATED` | Missing or invalid API key. |
| `404` | `NOT_FOUND` | The job doesn't exist, or belongs to a different key. |
| `429` | `RATE_LIMITED` | Too many requests; retry later. |
| `500` | `INTERNAL_ERROR` | Internal server error. Retryable. |
| `503` | `SERVICE_BUSY` | Service temporarily unavailable. Retryable. |

These use the same error object as a failed job's `error`, wrapped as `{"error": {...}}`. See [Errors and recovery](/v1/production/errors).

## Timing

Measured in production on 2026-10-12: two `1K` images took about 17–22 seconds; one `2K` image with a reference image took about 37 seconds. Images are generated one at a time, so a larger `n` takes longer, and at peak times a job first waits in `queued`. A job that hasn't finished within 15 minutes fails with `SERVICE_BUSY`.

## Data retention

* Generated images are deleted **24 hours after the job finishes** — download them before then. Afterwards this endpoint still returns the job, still `ready`, but every `images[].url` is `null`.
* Reference images you upload, or that Viggle downloads from a `reference_image_url`, are deleted within 24 hours.
* Customer data is never used to train models.

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl https://apis.viggle.ai/v1/images/img_b16a190d-2d44-41a0-8056-ef68183c3b9e \
    -H "Authorization: Bearer $VIGGLE_API_KEY"
  ```

  ```python Python theme={null}
  import os, requests
  response = requests.get(
      "https://apis.viggle.ai/v1/images/img_b16a190d-2d44-41a0-8056-ef68183c3b9e",
      headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
  )
  response.raise_for_status()
  image = response.json()
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://apis.viggle.ai/v1/images/img_b16a190d-2d44-41a0-8056-ef68183c3b9e", {
    headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
  });
  const image = await response.json();
  ```

  ```go Go theme={null}
  req, _ := http.NewRequest("GET", "https://apis.viggle.ai/v1/images/img_b16a190d-2d44-41a0-8056-ef68183c3b9e", 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()
  ```

  ```javascript @viggle/sdk theme={null}
  const image = await viggle.images.get("img_b16a190d-2d44-41a0-8056-ef68183c3b9e");
  console.log(image.status, image.images.map((generated) => generated.url));
  ```
</CodeGroup>

<Card title="Quick Start: Viggle Image" icon="rocket" href="/v1/guides/quickstart-image">
  Follow the complete create, poll, and download flow.
</Card>


## OpenAPI

````yaml openapi.yaml GET /v1/images/{image_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/images/{image_id}:
    parameters:
      - $ref: '#/components/parameters/ImageId'
      - $ref: '#/components/parameters/RequestId'
      - $ref: '#/components/parameters/SourceChannel'
    get:
      tags:
        - Images
      summary: Get an image generation
      description: |
        Returns the current state of an image generation job created with
        the calling API key; an unknown ID, or one created by another key,
        answers `404 NOT_FOUND`. 24 hours after the job finished its files
        are deleted: it stays `ready` here, with every image `url` null.
      operationId: getImage
      responses:
        '200':
          description: Current image generation state.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Image'
        '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:
    ImageId:
      name: image_id
      in: path
      required: true
      description: >-
        Public image job ID (`img_` prefix) returned by `POST /v1/images`. It
        must have been created with the calling API key.
      schema:
        type: string
        minLength: 1
      example: img_b16a190d-2d44-41a0-8056-ef68183c3b9e
    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:
    Image:
      description: |
        An image generation job (`img_` prefix), returned by both
        `POST /v1/images` and `GET /v1/images/{image_id}`. It only moves
        forward — `queued` → `processing` → `ready` or `failed` — and is
        never `cancelled`. `images` stays empty until the job is `ready`,
        then lists every generated image in request order. A job either
        produces all `n` images or fails; it never returns a partial set.
      type: object
      additionalProperties: false
      required:
        - id
        - status
        - model
        - progress
        - images
        - created_at
        - completed_at
        - error
      properties:
        id:
          type: string
          minLength: 1
          description: Public image job ID, `img_` prefix.
        status:
          type: string
          enum:
            - queued
            - processing
            - ready
            - failed
          description: Lifecycle state. `ready` and `failed` are terminal.
        model:
          type: string
          description: Model used for generation; currently always `qwen`.
        progress:
          type: integer
          nullable: true
          minimum: 0
          maximum: 100
          description: >-
            Share of the requested images generated so far — `0` while queued,
            0–99 while processing, `100` when ready, null when failed.
        images:
          type: array
          description: Empty until `ready`, then all `n` generated images in request order.
          items:
            $ref: '#/components/schemas/GeneratedImage'
        created_at:
          type: string
          format: date-time
          nullable: true
          description: Creation timestamp, RFC 3339.
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Terminal-state timestamp; set once the job is `ready` or `failed`,
            null before that.
        error:
          type: object
          nullable: true
          description: |
            Failure details, only when `status` is `failed`; otherwise null.
            `code` is `SERVICE_BUSY` (retryable — the generation service is
            busy or unavailable, or the job did not finish within 15
            minutes), `TASK_FAILED` (retryable — any other generation or
            upload failure), or `INVALID_REQUEST` (not retryable — the model
            rejected the request, for example an unusable reference image).
          allOf:
            - $ref: '#/components/schemas/ErrorBody'
    GeneratedImage:
      type: object
      additionalProperties: false
      required:
        - url
        - width
        - height
        - seed
      properties:
        url:
          type: string
          format: uri
          nullable: true
          description: >-
            Signed download URL of the PNG, valid for 1 hour; fetch the job
            again for a fresh one. Null once the file has been deleted, 24 hours
            after the job finished.
        width:
          type: integer
          minimum: 1
          description: Actual width in pixels.
        height:
          type: integer
          minimum: 1
          description: Actual height in pixels.
        seed:
          type: integer
          format: int64
          minimum: 0
          description: Seed actually used for this image.
    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.