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

> Upload a reference image to create a reusable character

Upload a reference image and we'll turn it into a reusable character. Processing happens in the background, and it **costs 1 credit**.

Use `model` to pick which model to preprocess for (`V3_Preview` or `V4_Preview`, default `V3_Preview`). One thing to know: a character only works with the model it was built for — so if you want to use the same image with both, just create two separate characters.

<Warning>
  **Model binding:** A character preprocessed with `V4_Preview` can only be used in `V4_Preview` renders, and vice versa. Check `has_v4_encoding` / `has_v3_encoding` in the status response to confirm which model is ready.
</Warning>

<Note>
  You'll get the best results from clear, well-lit, front-facing photos at a decent resolution.
</Note>

## Parameters

Send as `multipart/form-data`. Provide the image either as a file (`image`) **or** a URL (`image_url`).

| Parameter   | Type   | Required | Description                                                                                     |
| ----------- | ------ | :------: | ----------------------------------------------------------------------------------------------- |
| `name`      | string |     ✅    | Display name for the character.                                                                 |
| `image`     | file   |          | Reference image file (PNG, JPG, WebP). Use this or `image_url`.                                 |
| `image_url` | string |          | URL to a character image; the server fetches it. Use instead of `image`.                        |
| `model`     | string |          | `V3_Preview` (default) or `V4_Preview`. The character can only be rendered with the same model. |

## Response

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "job_id": "char_550e8400e29b",
  "status": "pending",
  "credits_reserved": 1.0,
  "message": "Character preprocessing initiated. Check status for updates."
}
```

| Field              | Description                                                                                                                |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `id`               | Character UUID. Poll [Get Character](/api-reference/characters/get) with it, then use it as `character_id` when rendering. |
| `status`           | Starts at `pending`. Preprocessing runs in the background.                                                                 |
| `credits_reserved` | Credits held for this character (1). Settled on success, refunded on failure.                                              |

## Example

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

  url = "https://apis.viggle.ai/api/characters/preprocess"
  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
  }
  files = {
      "image": ("character.png", open("character.png", "rb"), "image/png"),
  }
  data = {
      "name": "My Character",
      "model": "V3_Preview",  # or "V4_Preview"
  }

  response = requests.post(url, headers=headers, files=files, data=data)
  response.raise_for_status()
  result = response.json()

  print(f"Character ID: {result['id']}")
  print(f"Status: {result['status']}")
  ```

  ```javascript JavaScript theme={null}
  const form = new FormData();
  form.append("image", new Blob([await fetch("character.png").then(r => r.blob())]), "character.png");
  form.append("name", "My Character");
  form.append("model", "V3_Preview"); // or "V4_Preview"

  const response = await fetch("https://apis.viggle.ai/api/characters/preprocess", {
    method: "POST",
    headers: {
      "Authorization": "Bearer YOUR_API_KEY",
    },
    body: form,
  });

  const result = await response.json();

  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  console.log(`Character ID: ${result.id}`);
  console.log(`Status: ${result.status}`);
  ```

  ```bash cURL theme={null}
  curl -X POST https://apis.viggle.ai/api/characters/preprocess \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "image=@character.png" \
    -F "name=My Character" \
    -F "model=V3_Preview"
  ```
</CodeGroup>

## Next Steps

After creating a character, poll [Get Character](/api-reference/characters/get) every 5 seconds until `status` is `ready` and `has_v4_encoding` (or `has_v3_encoding`) is `true`. Then you can use it in [render jobs](/api-reference/render/create).


## OpenAPI

````yaml POST /api/characters/preprocess
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/characters/preprocess:
    post:
      tags:
        - Characters
      summary: Create Character
      description: >-
        Upload a reference image to create a reusable character. Processing runs
        in background. Costs 1 credit. The character is preprocessed for the
        specified model only. Poll GET /api/characters/{id} until status is
        ready.
      operationId: createCharacter
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: Display name for the character
                  example: My Character
                image:
                  type: string
                  format: binary
                  description: >-
                    Reference image file (PNG, JPG, WebP). Use this or
                    image_url.
                image_url:
                  type: string
                  format: uri
                  description: >-
                    URL to a character image. Server fetches it. Use instead of
                    image file upload.
                  example: https://example.com/character.png
                model:
                  type: string
                  enum:
                    - V4_Preview
                    - V3_Preview
                  default: V3_Preview
                  description: >-
                    Model to preprocess the character for. The character can
                    only be used in renders with the same model. Defaults to
                    V3_Preview.
      responses:
        '200':
          description: Character creation started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CharacterCreated'
        '400':
          description: Invalid image type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorStructured'
              example:
                detail:
                  error_code: CS-UORC01-002
                  message: Invalid image. Upload a PNG, JPG, or WebP file.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
      security:
        - bearerAuth: []
components:
  schemas:
    CharacterCreated:
      type: object
      properties:
        id:
          type: string
          example: 550e8400-e29b-41d4-a716-446655440000
          description: Character UUID
        job_id:
          type: string
          example: char_550e8400e29b
        status:
          type: string
          example: pending
        credits_reserved:
          type: number
          example: 1
        message:
          type: string
          example: Character preprocessing initiated. Check status for updates.
    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.
    Error:
      type: object
      description: >-
        Simple error. `detail` is a human-readable message (used for auth
        errors).
      properties:
        detail:
          type: string
          example: 'API key required. Use Authorization: Bearer sk-xxx'
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            detail: >-
              Invalid or missing API key. Pass it as Authorization: Bearer
              sk-...
    InsufficientCredits:
      description: Insufficient credits
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorStructured'
          example:
            detail:
              error_code: CS-UORC01-008
              message: Insufficient credits. Top up your balance to continue.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key passed as Bearer token

````