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

# Create Character (from Image)

> Create a reusable Character from an image, optionally extracting a 3D vsplat.

Creates a reusable Character asset. The request is asynchronous; poll the Character until `status` is `ready` before using its ID in a Render.

`type` selects what gets produced from the source image: `render` (default) creates only the render-ready 2D Character, `vsplat` creates only the 3D Gaussian splat, and `all` produces both and is billed for both. Once the vsplat extraction is `ready`, fetch its download URL from [Export 3D Character (for 3D/game engines)](/v1/api-reference/characters/export).

<Note>
  **Pricing** (1 credit = \$0.01): `type=render` costs **1 credit** flat. `type=vsplat` costs **30 credits** flat by default, or **25 credits** flat with `enhance=false` — enhance only affects the vsplat extraction and replaces the 25-credit price rather than adding to it. `type=all` is billed for both: **31 credits**, or **26 credits** with `enhance=false`. See [Pricing and retention](/v1/pricing).
</Note>

## Request parameters

Send `multipart/form-data`.

| Parameter | Type | Required | Default | Description |
| - | - | :-: | - | - |
| `image` | file | One of | — | Character source image uploaded directly. PNG, JPEG, and WebP are accepted; supply exactly one source field. |
| `image_url` | string | One of | — | Publicly reachable HTTP(S) URL of the character source image. Supply this instead of `image` and keep it accessible while ingestion starts. |
| `ref_url` | string | One of | — | Backward-compatible alias for `image_url`. Do not send both URL fields. |
| `name` | string | No | `""` | Optional display label returned by detail and list operations. It helps identify the Character but does not affect generation. |
| `model` | string | No | Service default | 2D preprocessing model used by `type=render` or `all`: `V3`, `v3`, `V3_Preview`, `V4`, `v4`, `V4_Preview`, or `V4_BaseSG`. It does not select the 3D extraction model. |
| `type` | string | No | `render` | Outputs to create: `render` produces the reusable 2D Character (**1 credit**), `vsplat` produces only the 3D Gaussian-splat asset (**30 credits**, or **25** with `enhance=false`), and `all` produces both and is billed for both (**31 or 26 credits**). |
| `enhance` | boolean | No | `true` | Whether to run the higher-fidelity vsplat extraction pass. Only takes effect when `type` is `vsplat` or `all` — it has no effect and isn't billed when `type=render`. Enabled by default at **30 credits flat**; set to `false` for the cheaper standard extraction at **25 credits**. |

Provide exactly one of `image`, `image_url`, or `ref_url`. Prefer `image_url` in new integrations.

The following fields apply only when `type` is `vsplat` or `all`.

| Parameter | Type | Required | Default | Description |
| - | - | :-: | - | - |
| `variant` | string | No | `optimized` | VSPLAT encoding variant: `optimized` or `original`. `quality` applies only to `optimized`. |
| `model_precision` | number | No | — | Optional model-level extraction precision in `(0, 1]`. Applies upstream, at the pkl extraction stage, before encoding. |
| `quality` | number | No | `0.70` | Target fraction of Gaussian splats retained after pruning, in `(0, 1]`. |
| `filter_low_quality` | boolean | No | `true` | Master switch for importance-ranked Gaussian pruning. `prune_preset` and `prune_budget` are used only when enabled. |
| `prune_preset` | string | No | `balanced` | Gaussian-splat pruning strategy: `geometric`, `draft`, `balanced`, `quality`, `compact`, or `compact_hq`. |
| `prune_budget` | number | No | — | Optional maximum Gaussian count used as an extract-time pruning budget; must be greater than 0. |
| `joint_set` | string | No | `body` | Rig the vsplat is skinned to: `full`, `expression`, or `body`. Doesn't affect price. |
| `use_sparse_W` | boolean | No | `false` | Store skinning weights as a sparse matrix in the extracted asset. |
| `scale_parts` | JSON string | No | — | JSON object of body-part or bone scale factors, for example `{"legs":1.1}`. Requires `joint_set=full`. |
| `render_thumbnail` | boolean | No | `false` | Whether to generate the standard Character preview thumbnail with the vsplat extraction. The service selects the render source and pose internally. |
| `task_id` | string | No | — | Caller-generated idempotency ID for `type=vsplat`. Use a unique, stable value when retrying the same work; for `type=all`, the service keys the companion extraction with the created Character ID. |

<Note>
  **`joint_set` rigs.** `full` keeps all 441 joints, including the complete facial rig, so the Character can play back facial-expression animation. `expression` keeps a 119-joint body-plus-facial-expression rig. `body` keeps the 86-joint body-only rig, dropping every facial joint — the Character can't animate its face at all. Reducing the joint set only changes the joint list and the columns of the skinning matrix `W` — the splat count itself is untouched, so a `body` character still has a full-detail face, it just can't animate it. If you omit `joint_set`, the V1 API resolves it to `body` (the extraction service's own internal default is `full`, but V1 always fills in `body` first). This parameter belongs only to Character extraction; Motion creation has no `joint_set` field.

  Motion export is a separate choice: `metahuman_url` carries the 441-joint rig and `metahuman_body_url` the 86-joint body rig. The API does not currently return a dedicated 119-joint Motion export for `expression`. `mixamo_url` is a generic 50-joint rig intended for retargeting onto another character mesh. See [Export 3D Motion](/v1/api-reference/motions/export).
</Note>

<Note>
  This is the complete public request contract. Workflow storage paths, output
  URIs, named multiview inputs, body-shape prediction, and thumbnail rendering
  details are selected or generated by the service.
</Note>

## Response parameters

Returns `200 OK` with a Character object.

| Field | Type | Always present | Description |
| - | - | :-: | - |
| `id` | string | Yes | Public Character ID, for example `char_550e8400-e29b-41d4-a716-446655440000`. Store it exactly as returned. |
| `status` | string | Yes | Initial status is normally `queued`. Terminal values are `ready` and `failed`. On an `all` Character, `status` only reaches `ready` once both the 2D render and the vsplat extraction have; if either fails, `status` is `failed` while `vsplat.status` shows which one it was. |
| `name` | string | Yes | The supplied label, or an empty string. |
| `progress` | integer or null | Yes | Progress from 0 to 100 when available. |
| `capabilities` | string\[] | Yes | Empty until ready; ready Characters include `video_render`. |
| `created_at` | string or null | Yes | ISO 8601 timestamp with a UTC offset, for example `2026-07-31T09:15:22+00:00`. |
| `completed_at` | string or null | Yes | ISO 8601 completion timestamp; `null` before completion. |
| `error` | object or null | Yes | Structured error when `status` is `failed`; otherwise `null`. |
| `type` | string | Yes | Echoes the requested `type`: `render`, `vsplat`, or `all`. |
| `vsplat` | object or null | Yes | `null` for a `render`-only Character. Otherwise `{status, error}` — the vsplat extraction's own status. Never carries a download URL; use [Export 3D Character (for 3D/game engines)](/v1/api-reference/characters/export) for that. |
| `glb` | null | Yes | Always `null` for a Character. |

```json theme={null}
{
  "id": "char_550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "name": "Presenter",
  "progress": 0,
  "capabilities": [],
  "created_at": "2026-07-31T09:15:22+00:00",
  "completed_at": null,
  "error": null,
  "type": "render",
  "vsplat": null,
  "glb": null
}
```

## Examples

<CodeGroup>
  ```go Go theme={null}
  body := &bytes.Buffer{}
  writer := multipart.NewWriter(body)
  part, _ := writer.CreateFormFile("image", "character.png")
  file, _ := os.Open("character.png")
  defer file.Close()
  io.Copy(part, file)
  writer.WriteField("name", "Presenter")
  writer.Close()

  req, _ := http.NewRequest("POST", "https://apis.viggle.ai/v1/characters", body)
  req.Header.Set("Authorization", "Bearer "+os.Getenv("VIGGLE_API_KEY"))
  req.Header.Set("Content-Type", writer.FormDataContentType())
  resp, err := http.DefaultClient.Do(req)
  if err != nil { panic(err) }
  defer resp.Body.Close()
  ```

  ```javascript JavaScript theme={null}
  const form = new FormData();
  form.append("image", imageFile);
  form.append("name", "Presenter");

  const response = await fetch("https://apis.viggle.ai/v1/characters", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}` },
    body: form,
  });
  const character = await response.json();
  ```

  ```python Python theme={null}
  import os
  import requests

  with open("character.png", "rb") as image:
      response = requests.post(
          "https://apis.viggle.ai/v1/characters",
          headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}"},
          files={"image": image},
          data={"name": "Presenter"},
      )
  response.raise_for_status()
  character = response.json()
  ```

  ```bash cURL theme={null}
  curl -X POST "https://apis.viggle.ai/v1/characters" \
    -H "Authorization: Bearer $VIGGLE_API_KEY" \
    -F "image=@character.png" \
    -F "name=Presenter"
  ```
</CodeGroup>

To also extract a 3D vsplat, add `-F "type=vsplat"` (or `all` to keep the render too):

```bash cURL theme={null}
curl -X POST "https://apis.viggle.ai/v1/characters" \
  -H "Authorization: Bearer $VIGGLE_API_KEY" \
  -F "image=@character.png" \
  -F "type=all" \
  -F "model_precision=0.8" \
  -F "prune_preset=quality" \
  -F "render_thumbnail=true"
```

The vsplat extraction runs the higher-fidelity `enhance` pass by default (30 credits flat). To use the cheaper standard extraction instead, add `-F "enhance=false"` alongside `type=vsplat` or `type=all` (25 credits flat):

```bash cURL theme={null}
curl -X POST "https://apis.viggle.ai/v1/characters" \
  -H "Authorization: Bearer $VIGGLE_API_KEY" \
  -F "image=@character.png" \
  -F "type=vsplat" \
  -F "enhance=false"
```

The default `joint_set` is `body`. To keep facial-expression joints (or the full 441-joint rig), add `-F "joint_set=expression"` (or `full`):

```bash cURL theme={null}
curl -X POST "https://apis.viggle.ai/v1/characters" \
  -H "Authorization: Bearer $VIGGLE_API_KEY" \
  -F "image=@character.png" \
  -F "type=vsplat" \
  -F "joint_set=expression"
```

## Next step

Use [Get Character](/v1/api-reference/characters/get) to poll the returned ID until it is ready, then [Export 3D Character (for 3D/game engines)](/v1/api-reference/characters/export) to download the vsplat if requested.


## OpenAPI

````yaml openapi.yaml POST /v1/characters
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/characters:
    parameters:
      - $ref: '#/components/parameters/RequestId'
      - $ref: '#/components/parameters/SourceChannel'
    post:
      tags:
        - Characters
      summary: Create a reusable character asset
      description: |
        Supply the source image either as an uploaded file or as `image_url`.
        The response is the freshly queued asset; poll
        `GET /v1/characters/{character_id}` until `status` is `ready`.

        `type` selects what gets produced from that same image: `render`
        (default, unchanged from before `type` existed) is the render-ready
        2D character and costs 1 credit; `vsplat` additionally extracts a 3D
        Gaussian splat and costs 25 credits (30 with `enhance`); `all`
        produces both and is billed for both — 26 credits, or 31 with
        `enhance`. Once the vsplat extraction is `ready`, fetch its download
        URL from `GET /v1/characters/{character_id}/export`.

        `enhance` runs an additional AI enhancement pass over the vsplat
        extraction. It only takes effect when `type` is `vsplat` or `all` —
        it has no effect and is not billed when `type=render`. It raises the
        vsplat cost from 25 to 30 credits flat, replacing the base vsplat
        price rather than adding to it.
      operationId: v1CreateCharacter
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/CreateCharacterForm'
      responses:
        '200':
          description: Character queued.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Asset'
        '400':
          $ref: '#/components/responses/ResourceBadRequest'
        '401':
          $ref: '#/components/responses/ResourceUnauthorized'
        '402':
          $ref: '#/components/responses/ResourcePaymentRequired'
        '404':
          $ref: '#/components/responses/ResourceNotFound'
        '409':
          $ref: '#/components/responses/ResourceConflict'
        '500':
          $ref: '#/components/responses/ResourceInternalServerError'
        '502':
          $ref: '#/components/responses/ResourceBadGateway'
        '503':
          $ref: '#/components/responses/ResourceServiceUnavailable'
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:
    CreateCharacterForm:
      description: |
        Supply the source image as exactly one of `image`, `image_url`, or
        the backward-compatible `ref_url` alias.
        `type` selects what gets produced from it — see `createCharacter`.
        The fields below `type` apply only when it is `vsplat` or `all`.
        This is the complete public contract; workflow paths, output URIs,
        multiview details, thumbnail cameras and pose, render source, and
        rest mode are service-managed.
      type: object
      properties:
        image:
          type: string
          format: binary
          description: >-
            Character source image uploaded directly. Supply exactly one of
            `image` or `image_url`; supported formats are validated by the
            service.
        image_url:
          type: string
          format: uri
          description: >-
            Publicly reachable URL of the character source image. Supply this
            instead of `image`, and keep it accessible while the request is
            processed.
        ref_url:
          type: string
          format: uri
          deprecated: true
          description: Backward-compatible alias for `image_url`. Do not send both fields.
        name:
          type: string
          description: >-
            Optional display name for the Character. An omitted value defaults
            to an empty string.
          default: ''
        model:
          type: string
          enum:
            - V3
            - v3
            - V3_Preview
            - V4
            - v4
            - V4_Preview
            - V4_BaseSG
          description: >-
            Optional 2D preprocessing model used by `type=render` or `all`. It
            does not select the 3D extraction model. Omit to use the service
            default.
        type:
          type: string
          description: >-
            Outputs to produce: `render` for the reusable 2D Character (1
            credit), `vsplat` for only the 3D extraction (30 credits by default,
            25 with `enhance=false`), or `all` for both (billed for both — 31 or
            26 credits).
          enum:
            - render
            - vsplat
            - all
          default: render
        variant:
          type: string
          enum:
            - optimized
            - original
          default: optimized
          description: VSPLAT encoding variant. `quality` applies only to `optimized`.
        enhance:
          description: |
            Whether to run the higher-fidelity vsplat extraction pass.
            Enabled by default, at a flat 30 credits; set to `false` for the
            cheaper standard extraction at 25 credits. Only takes effect when
            `type` is `vsplat` or `all` — it has no effect and is not billed
            when `type=render`.
          type: boolean
          default: true
        joint_set:
          type: string
          enum:
            - expression
            - body
            - full
          default: body
          description: |
            Rig the vsplat is skinned to. `full` keeps all 441 joints;
            `expression` keeps the 119-joint body-plus-facial-expression rig;
            `body` keeps the 86-joint body-only rig, dropping every facial
            joint. Reducing the joint set changes only `joints` and the
            columns of the skinning matrix `W` — the splat count itself is
            untouched, so a `body` character still has a full-detail face,
            it just can't animate it. Applies only when `type` is `vsplat`
            or `all`, and does not affect price. Omit to get `body`, the
            V1 default (the extraction service's own internal default is
            `full`, but the V1 facade always resolves an omitted value to
            `body` before the request reaches it). This field configures
            Character extraction only; Motion extraction does not accept
            `joint_set`.
        model_precision:
          type: number
          description: >-
            Optional model-level precision parameter for vsplat extraction,
            greater than 0 and at most 1. Applies only to `type=vsplat` or
            `all`.
          minimum: 0
          exclusiveMinimum: true
          maximum: 1
        quality:
          type: number
          minimum: 0
          exclusiveMinimum: true
          maximum: 1
          default: 0.7
          description: >-
            Target fraction of Gaussian splats retained after pruning. Applies
            only to `type=vsplat` or `all`.
        filter_low_quality:
          type: boolean
          default: true
          description: >-
            Master switch for importance-ranked Gaussian pruning. `prune_preset`
            and `prune_budget` are used only when this is true.
        prune_preset:
          type: string
          enum:
            - geometric
            - draft
            - balanced
            - quality
            - compact
            - compact_hq
          default: balanced
          description: >-
            Gaussian-splat pruning strategy; used only when
            `filter_low_quality=true`.
        prune_budget:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: >-
            Optional maximum Gaussian count budget for extract-time pruning.
            Applies only to `type=vsplat` or `all`.
        use_sparse_W:
          type: boolean
          default: false
          description: Store skinning weights as a sparse matrix in the extracted asset.
        scale_parts:
          type: string
          description: >-
            JSON object of body-part or bone scale factors, for example
            `{"legs":1.1}`. Requires `joint_set=full`.
        render_thumbnail:
          description: |
            Whether to generate the standard Character thumbnail. The service
            chooses the render source and pose internally.
          type: boolean
          default: false
        task_id:
          description: |
            Client-supplied idempotency key for `type=vsplat`. For `type=all`,
            the service keys the companion extraction with the Character ID.
            Use a unique, stable non-empty value when retrying the same
            creation request; reusing it for separate work causes a conflict.
          type: string
          minLength: 1
    Asset:
      description: >
        A character or motion asset. Both resources share one wire shape.


        `progress` is null in list responses. `error` is always null, including

        on a `failed` asset: read `status` to detect failure.


        `type` reflects what was requested at creation. For characters it is

        `render`, `vsplat`, or `all`; for motions it is `render`, `glb`,

        or `all`. Assets created before `type` existed report `render`.

        `vsplat` and `glb` carry that extraction's own status — never

        download URLs, which come from `GET
        /v1/characters/{character_id}/export`

        or `GET /v1/motions/{motion_id}/export` instead — and are null unless

        `type` requested that extraction. On an `all` asset, the top-level

        `status` only reaches `ready` once both the 2D render and the 3D

        extraction have; if either fails, the top-level `status` is `failed`

        while the sub-object's own `status` still shows which one it was.
      type: object
      additionalProperties: false
      required:
        - id
        - status
        - name
        - progress
        - capabilities
        - created_at
        - completed_at
        - error
        - type
        - vsplat
        - glb
      properties:
        id:
          type: string
          description: >-
            Public asset identifier. Character IDs normally begin with `char_`;
            Motion IDs normally begin with `mot_`.
          minLength: 1
        status:
          description: >-
            Overall lifecycle of the asset. Use an asset for rendering or export
            only after the required capability becomes `ready`.
          allOf:
            - $ref: '#/components/schemas/ResourceStatus'
        name:
          type: string
          description: >-
            Display name supplied at creation or derived during import; it may
            be empty when a workflow does not accept a name.
        progress:
          type: integer
          description: >-
            Best-effort processing percentage from 0 through 100 on detail
            responses; null in list responses or when unavailable.
          nullable: true
          minimum: 0
          maximum: 100
        capabilities:
          description: |
            What the asset can be used for. `video_render` appears once the
            asset is ready.
          type: array
          items:
            type: string
        created_at:
          description: >-
            ISO 8601 timestamp with a UTC offset, for example
            `2026-07-31T09:15:22+00:00`.
          type: string
          nullable: true
        completed_at:
          type: string
          description: >-
            ISO 8601 timestamp with a UTC offset when all requested processing
            reached a terminal state; null while work is active.
          nullable: true
        error:
          type: object
          description: >-
            Reserved top-level failure detail. It is currently always null;
            detect failure from `status` and inspect extraction sub-objects when
            applicable.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ResourceError'
        type:
          type: string
          description: >-
            Work requested when the asset was created. `render` produces the 2D
            render-ready asset, `vsplat`/`glb` requests 3D output, and `all`
            requests both supported outputs.
          enum:
            - render
            - vsplat
            - glb
            - all
          default: render
        vsplat:
          description: |
            Character vsplat extraction status. Null for motions, and for
            characters whose `type` is `render`. The request parameters
            (`model_precision`, etc.) submitted at creation are not echoed
            back here — this is status only.
          nullable: true
          type: object
          additionalProperties: false
          required:
            - status
            - error
          properties:
            status:
              description: >-
                Lifecycle of the character's vsplat extraction, independent of
                the top-level asset status.
              allOf:
                - $ref: '#/components/schemas/ResourceStatus'
            error:
              type: object
              description: >-
                Structured vsplat extraction failure when its status is
                `failed`; otherwise null.
              nullable: true
              allOf:
                - $ref: '#/components/schemas/ResourceError'
        glb:
          description: |
            Motion 3D animation extraction/generation status. Null for
            characters, and for motions whose `type` is `render`.
          nullable: true
          type: object
          additionalProperties: false
          required:
            - status
            - skeletons
            - error
          properties:
            status:
              description: >-
                Lifecycle of the motion's 3D animation extraction or generation,
                independent of the top-level asset status.
              allOf:
                - $ref: '#/components/schemas/ResourceStatus'
            skeletons:
              description: |
                Skeleton variants ready to export via
                `GET /v1/motions/{motion_id}/export?download_type=`.
                Empty until `status` is `ready`; both variants are
                generated up front, so this is either empty or
                `[mixamo, metahuman]`.
              type: array
              items:
                type: string
                enum:
                  - mixamo
                  - metahuman
            error:
              type: object
              description: >-
                Structured 3D animation failure when its status is `failed`;
                otherwise null.
              nullable: true
              allOf:
                - $ref: '#/components/schemas/ResourceError'
    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
    ResourceError:
      description: |
        The failure attached to an asynchronous resource. `code` is a stable,
        lower_snake_case string and deliberately not an enum: the extraction
        and render workers own this vocabulary and add to it over time, and a
        failure with no published mapping surfaces as `processing_failed`.

        Published codes: `worker_stopped`, `motion_model_mismatch`,
        `image_required`, `motion_video_required`, `unsupported_video_format`,
        `video_too_long`, `video_too_large`, `video_resolution_too_high`,
        `video_unreadable`, `invalid_background_mode`,
        `video_dimensions_must_be_even`, `result_expired`,
        `video_inaccessible`, `no_humans_detected`, `all_workers_busy`,
        `task_failed`, `unexpected_error`, `processing_failed`.
      type: object
      additionalProperties: false
      required:
        - code
        - message
        - request_id
      properties:
        code:
          type: string
          description: >-
            Stable, lower_snake_case asynchronous failure code. The vocabulary
            is open, so clients must tolerate new values.
          minLength: 1
        message:
          type: string
          description: Human-readable explanation of the asynchronous processing failure.
        request_id:
          type: string
          description: >-
            Correlation identifier from the worker or originating request; null
            when unavailable.
          nullable: true
    ResourceErrorResponse:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          description: Top-level synchronous resource-operation error payload.
          allOf:
            - $ref: '#/components/schemas/ResourceHttpError'
    ResourceHttpError:
      description: |
        The failure envelope of a synchronous resource request. Every code is
        produced by one mapping in the API service, so the set is closed; a
        failure with no published mapping surfaces as `processing_failed`.

        The asynchronous `error` object on a resource carries the wider,
        deliberately open vocabulary of `ResourceError` instead.
      type: object
      additionalProperties: false
      required:
        - code
        - message
        - request_id
      properties:
        code:
          type: string
          description: >-
            Closed, lower_snake_case error code for a synchronous resource
            request; use it for programmatic handling.
          enum:
            - authentication_required
            - invalid_api_key
            - insufficient_credits
            - invalid_request
            - motion_not_ready
            - character_not_found
            - motion_not_found
            - not_found
            - id_already_exists
            - rate_limited
            - service_unavailable
            - task_failed
            - internal_error
            - processing_failed
        message:
          type: string
          description: Human-readable explanation of the synchronous request failure.
        request_id:
          description: |
            Always null on a synchronous failure. Correlate with the
            `X-Request-Id` response header instead.
          type: string
          nullable: true
  headers:
    RequestId:
      description: Stable request identifier for support and tracing.
      schema:
        type: string
  responses:
    ResourceBadRequest:
      description: |
        Invalid request. The resource operations answer every request-shape
        rejection with `400`; they never answer `422`.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourceUnauthorized:
      description: Missing, invalid, or expired API key.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourcePaymentRequired:
      description: Insufficient credits.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourceNotFound:
      description: |
        The resource does not exist, or it is not owned by the calling
        principal. The two cases are deliberately indistinguishable.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourceConflict:
      description: The client-supplied task ID is already in use.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourceInternalServerError:
      description: Unexpected server error.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourceBadGateway:
      description: The extraction backend is unavailable or the extraction failed.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResourceErrorResponse'
    ResourceServiceUnavailable:
      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/ResourceErrorResponse'
  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.