> ## Documentation Index
> Fetch the complete documentation index at: https://www.tryleap.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Leap's API is at https://api.tryleap.ai. Send the key in the x-api-key header or as Authorization: Bearer; keys start with leap_.
> Take model IDs and input schemas from GET /v1/models/{creator}/{name}, or from https://api.tryleap.ai/v1/public/models without a key. Never guess an input field: unknown fields are a 400.
> Model inputs take uploaded file IDs (file_...), never URLs. A kept character's ID (chr_..., POST /v1/characters) goes wherever an image file does and keeps the character the same across runs.
> To give a coding agent the whole API, install the Leap skill: curl -fsSL https://www.tryleap.ai/install.sh | sh
> To make media from ChatGPT, Claude or another MCP client without code, connect Leap's MCP server at https://app.tryleap.ai/api/mcp; see https://www.tryleap.ai/docs/mcp.
> The full OpenAPI 3.1 spec is at https://www.tryleap.ai/docs/openapi.json.

# Characters

> Keep a character once, then pass its ID wherever a model or recipe takes an image, so it comes out the same in every picture and clip.

A character is a name and one to four pictures your workspace keeps, with a short description of its look that Leap reads from them once. Put its ID (`chr_...`) anywhere a model or recipe takes an image file, and the run gets the pictures and the description. You don't upload the same reference again for every call, and the prompt you write can be about what changes.

Characters are in beta: the shape can still change without the notice stable endpoints get. They use your key's `generations` scopes, so any key that runs generations can keep them.

## Make a character

Upload the pictures ([files](https://www.tryleap.ai/docs/files.md)), then name them:

```bash theme={"theme":"css-variables"}
BASE=$(curl -s "https://api.tryleap.ai/v1/files?filename=hero-base.png" \
  -H "x-api-key: $LEAP_API_KEY" \
  -H "content-type: image/png" \
  --data-binary @hero-base.png | jq -r .id)

curl https://api.tryleap.ai/v1/characters \
  -H "x-api-key: $LEAP_API_KEY" \
  -H "content-type: application/json" \
  -d "{\"name\": \"Rook\", \"images\": [\"$BASE\"]}"
```

```json theme={"theme":"css-variables"}
{
  "id": "chr_7Hq2Lm9Xc4Vb1Nz8Rt5Kw3Ys",
  "object": "character",
  "beta": true,
  "name": "Rook",
  "images": [
    {
      "file": "file_5Tn8Xc2Lq7Vm4Hb9Rz1Kw6Pd",
      "url": "https://api.tryleap.ai/files/eyJrIjoibWVkaWEv...",
      "width": 1024,
      "height": 1536
    }
  ],
  "created_at": "2026-10-17T14:02:11.204Z",
  "updated_at": "2026-10-17T14:02:11.204Z"
}
```

One clear picture is enough. A turnaround or a second angle keeps the back and the sides closer. A picture you made with Leap works too: keep it as a file with `POST /v1/generations/{id}/outputs/{index}/file`, then pass that file's ID.

Making a character is free, and a workspace keeps up to 200. Characters made in the studio's library show up in `GET /v1/characters`, and the ones you make here show up in the studio, one tap from every photo slot.

## Use it in a run

Pass the character's ID in place of a file:

* In a list of images, such as `images`, it becomes all of its pictures, in order, beside any files you pass with it.
* In a single image input, such as `photo`, `character` or `first_frame`, it becomes its first picture.
* On a model, the prompt you send gets one more sentence that says which images show the character and what it looks like. Your own words come first and decide what changes.
* On a recipe that keeps characters, such as `leap/consistent-character`, the description goes into the recipe's own prompt.

```bash theme={"theme":"css-variables"}
curl https://api.tryleap.ai/v1/generations \
  -H "x-api-key: $LEAP_API_KEY" \
  -H "content-type: application/json" \
  -H "prefer: wait=60" \
  -d '{
    "model": "google/nano-banana-2",
    "input": {
      "prompt": "Dress her in a knight'\''s armor, same pose, same proportions, on a flat pure green background (#00FF00)",
      "images": ["chr_7Hq2Lm9Xc4Vb1Nz8Rt5Kw3Ys"],
      "aspect_ratio": "2:3"
    }
  }'
```

The generation's `input` shows the files the model got in the character's place, and you're charged for the run as usual. A character costs nothing on top.

## Game assets: one figure, many outfits

A common pipeline keeps one base figure and makes every outfit, expression and pose from it, each on a background you can cut out. `leap/consistent-character` does the cutting for you: with `background: "transparent"` it draws on a flat chroma screen and returns a PNG with that screen removed. It picks a magenta screen for a character that is green itself.

```ts TypeScript theme={"theme":"css-variables"}
import { readFile, writeFile } from "node:fs/promises";

const API = "https://api.tryleap.ai";
const KEY = process.env.LEAP_API_KEY!;

async function leap(path: string, body: unknown) {
  const response = await fetch(`${API}${path}`, {
    method: "POST",
    headers: {
      "x-api-key": KEY,
      "content-type": "application/json",
      prefer: "wait=60",
    },
    body: JSON.stringify(body),
  });
  const json = await response.json();
  if (!response.ok) throw new Error(`${json.error.code}: ${json.error.message}`);
  return json;
}

// 1. Upload the base figure once and keep it as a character.
const upload = await fetch(`${API}/v1/files?filename=hero-base.png`, {
  method: "POST",
  headers: { "x-api-key": KEY, "content-type": "image/png" },
  body: await readFile("hero-base.png"),
});
const base = await upload.json();
const hero = await leap("/v1/characters", { name: "Rook", images: [base.id] });

// 2. A turnaround to check the back and the sides, as one sheet.
await leap("/v1/generations", {
  model: "leap/consistent-character",
  input: { character: [hero.id], shot: "turnaround", background: "white" },
});

// 3. Every outfit from the same figure, cut out.
for (const outfit of ["a knight's armor", "a summer festival yukata", "a space suit"]) {
  const run = await leap("/v1/generations", {
    model: "leap/consistent-character",
    input: {
      character: [hero.id],
      shot: "outfit",
      details: outfit,
      background: "transparent",
      aspect_ratio: "2:3",
    },
  });
  const png = await fetch(run.output[0].url);
  await writeFile(`rook-${outfit.replaceAll(" ", "-")}.png`, Buffer.from(await png.arrayBuffer()));
}

// 4. Four expressions in one run, one per image.
await leap("/v1/generations", {
  model: "leap/consistent-character",
  input: { character: [hero.id], shot: "expressions", background: "transparent", n: 4 },
});
```

```bash cURL theme={"theme":"css-variables"}
curl https://api.tryleap.ai/v1/generations \
  -H "x-api-key: $LEAP_API_KEY" \
  -H "content-type: application/json" \
  -H "prefer: wait=60" \
  -d '{
    "model": "leap/consistent-character",
    "input": {
      "character": ["chr_7Hq2Lm9Xc4Vb1Nz8Rt5Kw3Ys"],
      "shot": "outfit",
      "details": "a knight'\''s armor",
      "background": "transparent",
      "aspect_ratio": "2:3"
    }
  }'
```

Use the recipe's [schema](https://www.tryleap.ai/docs/models.md#read-an-input-schema) for every shot it makes: `turnaround`, `angles` (front, three-quarter, side and back, each image the next), `expressions` (four faces, or the one you describe in `details`), `outfit`, `pose` and `scene`. Outfit, pose and scene need `details`.

Transparency works best on drawn characters: anime, cartoons, mascots and game art. A photo of a real person or a pet keeps its hair and fur edges better on `white` or `grey`.

## The whole set in one run

`leap/character-pack` makes 11 pictures of one character in one run, for $2.50: the same pictures one by one on `leap/consistent-character` cost $2.75. Each is its own take on the recipe's prompt and model, in this order in `output`:

| `output` | Picture | Shape |
| - | - | - |
| 0 | A turnaround: front, side and back on one sheet | 16:9 |
| 1 to 4 | Expressions: laughing, furious, sad, shocked | 1:1 |
| 5 to 8 | Outfits: casual, dressed up, sporty, a knight's costume | 2:3 |
| 9 and 10 | Poses: mid-jump, and sitting cross-legged, waving | 2:3 |

It takes `character` and `background`: `white` (the default), `grey` or `transparent`; the cut-out is cleanest on drawn and 3D characters. Leap's own runs took 27 to 71 seconds, so a run can still be going when `prefer: wait=60` answers: read it again until it's done, or pass a `webhook`.

```bash theme={"theme":"css-variables"}
curl https://api.tryleap.ai/v1/generations \
  -H "x-api-key: $LEAP_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "leap/character-pack",
    "input": {
      "character": ["chr_7Hq2Lm9Xc4Vb1Nz8Rt5Kw3Ys"],
      "background": "transparent"
    }
  }'
```

A failed run costs nothing. When the model turns down one picture, that picture is made on the fallback model and the rest keep theirs.

## In a video

A video model's `first_frame` takes a character's ID too, so the clip starts from its first picture. Two ways keep it the same while it moves:

* `leap/character-video@2` frames the character for the move first (a walk, a dance, a line to camera), then animates it with sound on Kling O3 Pro, \$0.35 a second. Pass the ID as `character`.
* `kling/kling-o3-reference` follows up to four reference images instead of a first frame, so a drawn character stays drawn, scene and all. Pass the ID in `images` and describe the scene in `prompt`.

```bash theme={"theme":"css-variables"}
curl https://api.tryleap.ai/v1/generations \
  -H "x-api-key: $LEAP_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "leap/character-video@2",
    "input": {
      "character": "chr_7Hq2Lm9Xc4Vb1Nz8Rt5Kw3Ys",
      "motion": "talk",
      "line": "Same face, every post.",
      "aspect_ratio": "9:16",
      "duration": 5
    }
  }'
```

## Keep it current

* `GET /v1/characters` lists them, newest first, with fresh links to their pictures.
* `PATCH /v1/characters/{id}` renames one, or gives it new pictures in place of all the old ones. Leap reads its look again; runs it already made stay as they ran.
* `DELETE /v1/characters/{id}` deletes it. Its pictures stay as files, and so do its runs.

A character's picture can't be deleted while the character holds it: `DELETE /v1/files/{id}` answers `409 file_in_use`. Give the character other pictures, or delete it, first.

## Over MCP

The MCP server's `generate` tool takes a character's ID wherever its input takes an image file, the same as the API. Copy the ID from the character's page in the studio, or list them with the API.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.