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

# Chess videos

> Render a narrated analysis of a Lichess game: check the live chess options, create a project, render, poll, and collect the video.

Send a Lichess round id and the two players, and Sigmora writes a fact-checked
analysis, verifies the board positions, narrates it and renders the video.

## How it works

1. `GET /v1/video/options` lists the current chess formats, audiences, duration
   bounds and whether board verification is available.
2. `POST /v1/projects` creates a project with `videoPath: "chess-video"`, unless
   you already have one.
3. `POST /v1/video/render` submits the game with `domain: "chess"`.
4. `GET /v1/jobs/{jobId}` is polled until the job is terminal.
5. A finished job carries the video plus evidence of its quality checks:
   `artifacts.scriptReview` (the script review) and `artifacts.runJson` (the
   signed run manifest).

## Render a game

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  curl -X POST https://api.sigmora.org/v1/video/render \
    -H "Authorization: Bearer $SIGMORA_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: chess-game-001" \
    -d '{
      "projectId": "prj_9x2a4c",
      "domain": "chess",
      "videoId": "LICHESS_ROUND_ID",
      "chessWhite": "player-white",
      "chessBlack": "player-black",
      "chessFormat": "full-game-analysis",
      "chessAudience": "intermediate",
      "chessRequireVisionAudit": true,
      "targetMinutes": 10,
      "quality": "h"
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  import os
  import requests

  render = requests.post(
      "https://api.sigmora.org/v1/video/render",
      headers={
          "Authorization": f"Bearer {os.environ['SIGMORA_API_KEY']}",
          "Idempotency-Key": "chess-game-001",
      },
      json={
          "projectId": "prj_9x2a4c",
          "domain": "chess",
          "videoId": "LICHESS_ROUND_ID",
          "chessWhite": "player-white",
          "chessBlack": "player-black",
          "chessFormat": "full-game-analysis",
          "chessAudience": "intermediate",
          "chessRequireVisionAudit": True,
          "targetMinutes": 10,
          "quality": "h",
      },
      timeout=60,
  ).json()
  print(render["jobId"])
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  const render = await fetch("https://api.sigmora.org/v1/video/render", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SIGMORA_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": "chess-game-001",
    },
    body: JSON.stringify({
      projectId: "prj_9x2a4c",
      domain: "chess",
      videoId: "LICHESS_ROUND_ID",
      chessWhite: "player-white",
      chessBlack: "player-black",
      chessFormat: "full-game-analysis",
      chessAudience: "intermediate",
      chessRequireVisionAudit: true,
      targetMinutes: 10,
      quality: "h",
    }),
  }).then((r) => r.json());
  console.log(render.jobId);
  ```
</CodeGroup>

| Field | Description |
| - | - |
| `videoId` | **Required.** The Lichess round or game id — only the id. |
| `chessWhite`, `chessBlack` | **Required.** The two player selectors. |
| `chessFormat` | `full-game-analysis` (default), `tactical-breakdown`, `opening-story` or `endgame-lesson`. |
| `chessAudience` | `beginner`, `intermediate` (default) or `advanced`. |
| `chessRequireVisionAudit` | Verify board images before narration. Defaults to `true`. |
| `targetMinutes` | Runtime target, 6–20 minutes for chess. Defaults to 10. It guides the writing and never trims the game. |

<Warning>
  Send only the Lichess id as `videoId`, with the players in `chessWhite` and
  `chessBlack`. The combined `round:white:black` form is rejected.
</Warning>

## Script review

Before narration, the script is reviewed against the game for factual accuracy,
source fidelity, audience fit, spoken delivery, visual editability and pacing.
`job.artifacts.scriptReview` is a URL to that review. If the review blocks the
script, the job ends as `qa_failed` before any narration or render cost — read
the review, adjust the request, and submit again.

## Complete example client

Download the runnable Node.js client,
[`chess-video.mjs`](https://sigmora.org/kit/chess-video.mjs).
It checks your choices against the live options, creates or reuses a project,
derives a stable idempotency key, polls safely, validates the quality evidence,
downloads the video, review and run manifest, and prints a receipt.

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
curl -fsSLO https://sigmora.org/kit/chess-video.mjs
SIGMORA_API_KEY=sk_live_... \
LICHESS_ROUND_ID=... \
CHESS_WHITE=... \
CHESS_BLACK=... \
node chess-video.mjs
```

Set `SIGMORA_PROJECT_ID` to reuse an existing project. If the process stops after
submitting, nothing is lost: run it again with the same project, or resume
polling `GET /v1/jobs/{jobId}`. The deterministic idempotency key means the same
game is never charged twice.

For unattended production, send `callbackUrl` and `callbackSecret` with the
render and keep polling as the fallback. See [Webhooks](/webhooks).

## Other video types

Lessons, how-to videos, stories, UGC and catalogue entries follow the same steps;
only the source and the type-specific fields change. Read
`GET /v1/video/options` instead of hard-coding values, and use
`GET /v1/video/catalog/{domain}` to find catalogue ids.


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