---
title: "Upload Template"
method: POST
path: "/api/hand-templates/upload"
---

# Upload Template

`POST /api/hand-templates/upload`

## 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/upload`
- Auth: HTTP bearer

Promote a Platform-Storage file_id into a permanent template.

Caller uploads the hand photo via the regular `/api/uploads/presign`
path first (or via Platform Storage `uploadFile()`), gets a
`file_id`, then posts it here with the structured discriminators.

Returns 404 when the file_id is unknown to the SDK or owned by a
different user. Returns the freshly-persisted template row so the
frontend can drop it into the picker without re-fetching the list.

Standalone callers post a raw `hand_s3_key` (from
/api/uploads/standalone-presign) instead of a file_id — see
`_resolve_hand_image`.

## Request body

- HandTemplateUploadRequest: Body for `POST /api/hand-templates/upload`. Promotes an uploaded hand photo into a permanent template row with the user's chosen knobs. The client uploads via /api/uploads/standalone-presign and supplies the raw `hand_s3_key` (validated server-side to the caller's own prefix).
  - `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'
  - `hand_s3_key` string, nullable

## Response `201`

Successful Response

- HandTemplateResponse: One row from the picker. Used by `GET /api/hand-templates` and every `POST` that returns a single template.
  - `id` string, uuid, required
  - `slug` string, required
  - `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', required
  - `prop_slug` string, nullable
  - `hand_url` string, required
  - `preview_url` string, nullable
  - `source` 'admin' | 'upload' | 'ai_gen', required
  - `is_active` boolean, required
  - `gen_prompt` string, nullable
  - `owner_user_id` string, uuid, nullable
  - `preprocess_ready` boolean
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

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