> ## 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 Job Status

> Check render job status and progress

Check where a render job is at. This comes back right away, so poll it every 3–5 seconds until the job is `complete` or `failed`. Once it's done, grab the finished video from `cdn_url`.

<Note>
  This endpoint does **not** require authentication. You can poll job status without an API key.
</Note>

<Warning>
  Job status and `cdn_url` are available for **1 hour** after job creation. After that, the job data expires from the status endpoint. Download or save the `cdn_url` promptly.
</Warning>

## Response fields

Key fields in the response:

| Field                      | Description                                                                                                                                                                                              |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`                   | Current job status: `queued`, `processing`, `complete`, or `failed`                                                                                                                                      |
| `progress_pct`             | Estimated progress percentage (0-100)                                                                                                                                                                    |
| `checkpoint`               | Last **completed** pipeline stage: `ref_done`, `dri_done`, `bg_done`, `render_done`. Stays empty for the entire first stage, since there's nothing completed yet -- use `current_stage` for a live view. |
| `current_stage`            | Pipeline stage the worker is running **right now**: `ref`, `dri`, `bg`, or `render`. Only set while `status` is `processing`.                                                                            |
| `current_stage_started_at` | ISO 8601 timestamp when `current_stage` started. Use it to show elapsed time for the running stage.                                                                                                      |
| `cdn_url`                  | Direct URL to download the final video (available when `status` is `complete`)                                                                                                                           |
| `error_code`               | Structured error code when `status` is `failed` (e.g. `CS-UORC01-009`)                                                                                                                                   |
| `error_message`            | Human-readable error description when `status` is `failed`                                                                                                                                               |

<Note>
  `current_stage` and `current_stage_started_at` are the recommended way to show live progress -- they're always populated once a stage starts, unlike `checkpoint` which lags one stage behind.
</Note>

## Polling examples

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  job_id = "job_abc123xyz"
  url = f"https://apis.viggle.ai/api/render/{job_id}"

  while True:
      data = requests.get(url).json()
      print(f"Status: {data['status']} ({data.get('progress_pct', 0)}%)")

      if data["status"] == "complete":
          print(f"Video ready: {data['cdn_url']}")
          break
      elif data["status"] == "failed":
          print(f"Error {data.get('error_code')}: {data.get('error_message')}")
          break

      time.sleep(3)
  ```

  ```javascript JavaScript theme={null}
  const jobId = "job_abc123xyz";
  const url = `https://apis.viggle.ai/api/render/${jobId}`;

  while (true) {
    const resp = await fetch(url);
    const data = await resp.json();
    console.log(`Status: ${data.status} (${data.progress_pct ?? 0}%)`);

    if (data.status === "complete") {
      console.log(`Video ready: ${data.cdn_url}`);
      break;
    } else if (data.status === "failed") {
      console.error(`Error ${data.error_code}: ${data.error_message}`);
      break;
    }

    await new Promise(r => setTimeout(r, 3000));
  }
  ```

  ```bash cURL theme={null}
  # Single status check (poll by repeating this call every 3-5 seconds)
  curl "https://apis.viggle.ai/api/render/job_abc123xyz"
  ```
</CodeGroup>


## OpenAPI

````yaml GET /api/render/{job_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: []
paths:
  /api/render/{job_id}:
    get:
      tags:
        - Render
      summary: Get Job Status
      description: >-
        Check render job status and progress. Returns immediately. Poll every
        3-5 seconds until status is complete or failed. Use the cdn_url field to
        download the final video.
      operationId: getRenderJobStatus
      parameters:
        - name: job_id
          in: path
          required: true
          schema:
            type: string
          example: job_abc123xyz
      responses:
        '200':
          description: Job status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RenderJob'
        '404':
          description: Job not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorStructured'
              example:
                detail:
                  error_code: CS-UORC01-003
                  message: >-
                    Job not found. Check the job_id, or it may have expired
                    (jobs are available for 1 hour).
        '410':
          description: Result expired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorStructured'
              example:
                detail:
                  error_code: CS-UORC01-003
                  message: >-
                    This job's result has expired. Job data is available for 1
                    hour after creation.
      security: []
components:
  schemas:
    RenderJob:
      type: object
      properties:
        job_id:
          type: string
          example: job_abc123xyz
        status:
          type: string
          enum:
            - queued
            - processing
            - complete
            - failed
            - cancelled
        mode:
          type: string
          description: The render mode used (e.g. full_pipeline, preprocessed)
          nullable: true
        checkpoint:
          type: string
          description: Last completed processing stage within the pipeline
          nullable: true
        current_stage:
          type: string
          enum:
            - ref
            - dri
            - bg
            - render
          description: >-
            Pipeline stage the worker is currently running. Only set while
            status is processing.
          nullable: true
        current_stage_started_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 timestamp when current_stage started
        progress_pct:
          type: number
          description: Estimated progress percentage (0-100)
          nullable: true
          example: 60
        cdn_url:
          type: string
          format: uri
          nullable: true
          description: >-
            CDN URL to download the final video (available when status is
            complete)
        mask_cdn_url:
          type: string
          format: uri
          nullable: true
          description: >-
            CDN URL for the alpha/mask video (transparent mode only). White =
            character, black = background. Use with cdn_url for compositing.
        error:
          type: string
          nullable: true
          description: Short error label when status is failed
        error_code:
          type: string
          nullable: true
          description: Structured error code (e.g. CS-UORC01-002) when status is failed
        error_message:
          type: string
          nullable: true
          description: Human-readable error description when status is failed
        progress:
          type: object
          nullable: true
          description: v1 compat progress object
          properties:
            completed_chunks:
              type: integer
            total_chunks:
              type: integer
            percent:
              type: number
        download_url:
          type: string
          format: uri
          nullable: true
          description: Mirrors cdn_url when complete
        chunks:
          type: array
          items:
            type: object
          description: Always an empty array in v2. Retained for backward compatibility.
        created_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the job was created
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the job completed
    ErrorStructured:
      type: object
      description: >-
        Structured error. `detail` carries a machine-readable `error_code` plus
        a human-readable `message`.
      properties:
        detail:
          type: object
          properties:
            error_code:
              type: string
              example: CS-UORC01-008
            message:
              type: string
              example: Insufficient credits. Top up your balance to continue.

````