---
title: "Generate Template"
method: POST
path: "/api/hand-templates/generate"
---

# Generate Template

`POST /api/hand-templates/generate`

## Request

- Base URL: `https://api.tintin-x.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.tintin-x.com/api/hand-templates/generate`
- Auth: HTTP bearer

Fire 3 Fal NB2 text-to-image candidates for an in-app hand template.

Sequence: compose prompt → charge $0.20 via Platform SDK → spawn N
parallel NB2 calls + anatomy stub → upload candidates to S3 → persist
draft row with the candidate list → return presigned candidate URLs.

Refund on Fal/Platform-Storage failure mid-flight: if ALL N
candidates fail to produce bytes, we refund the charge and return
502. Partial failures (1-2 candidates succeed) keep the charge —
the user can still finalize one of the surviving candidates.

Latency: ~10-30s wall (dominated by NB2). Sync response; no SQS.
The frontend renders a "Generating…" state while the request hangs.

## Request body

- HandTemplateGenerateRequest: Body for `POST /api/hand-templates/generate`. Drives the structured form. The optional `refinement` field is the only free-text knob, capped at 120 chars; the rest are enumerated. The server composes a deterministic prompt from these inputs (the template lives in the worker / atom code) and fires N parallel Fal NB2 candidates. Each candidate is anatomy-validated before surfacing — see §4.7 in the design doc.
  - `label` string, required
  - `pose` 'single_hand' | 'two_hands_layered' | 'fist_flat_dual' | 'holding_prop', required
  - `skin_tone` 'fair' | 'light' | 'medium' | 'tan' | 'deep', required
  - `aspect_ratio` '1:1' | '4:5' | '3:4' | '16:9', required
  - `background` 'white' | 'gradient' | 'extended'
  - `refinement` string, nullable

## Response `201`

Successful Response

- HandTemplateGenerateResponse: Returned by `POST /generate`. Frontend renders the candidates + waits for the user to call `POST /{id}/finalize` with a picked index. The draft row stays in storage but is invisible from the picker until finalize promotes it.
  - `draft_template_id` string, uuid, required
  - `candidates` HandTemplateCandidate[], required
    - `index` integer, required
    - `candidate_url` string, required
    - `passed_anatomy` boolean, required
  - `composed_prompt` string, required
  - `cents_charged` integer, required
  - `charge_id` string, uuid, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/tintin-x/apis/tintin-api.md) · [All operations](https://skmtc.dev/tintin-x/apis/tintin-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tintin-x/apis/tintin-api/revisions/8839a8d0a66c?raw)
