---
title: "Update Template Assignments"
method: PATCH
path: "/api/hand-templates/{template_id}/assignments"
---

# Update Template Assignments

`PATCH /api/hand-templates/{template_id}/assignments`

## 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/{template_id}/assignments`
- Auth: HTTP bearer

Manually overwrite the cached VLM-derived nail → mask mapping.

Use case: the VLM occasionally mis-labels a finger; the user opens
the detail-view editor, swaps two mask IDs, hits Save. We re-render
`01_hand_assigned.png` with the new mapping + rewrite
`assignments.json` at the same S3 keys. The next try-on against
this template hydrates the new mapping via the existing cache path
and the warp uses the corrected assignments.

Validation:
- Template must be visible to the caller AND non-admin (admin rows
  are global; we don't let one user mutate the shared catalog).
- Cache must already be populated (`hand_preprocess` non-null).
- Submitted mask_ids must form a permutation of the currently-
  cached `assigned` mask_ids (no new masks, no missing ones).
- Submitted (hand, finger) pairs must be unique.

## Path parameters

- `template_id` string, uuid, required

## Request body

- HandTemplateAssignmentsUpdate: Body for `PATCH /api/hand-templates/{id}/assignments`. Replaces the cached VLM-derived mapping with the operator-edited one. The server re-renders `01_hand_assigned.png`, rewrites `assignments.json`, and the next try-on against this template consumes the new assignments via the existing preprocess-cache hydrate path. `finger_flips` carries the per-finger base↔tip overrides. It is optional with replace-semantics: when omitted (legacy clients) the stored flips are preserved; when present it fully replaces them. `custom_tip_dirs` carries the per-finger fine-tuned tip direction vectors (na editor drag). Same optional replace-semantics as `finger_flips`: omit to preserve stored dirs, send the full set (possibly empty) to overwrite. A finger with a custom dir ignores its `finger_flips` entry downstream.
  - `assignments` HandTemplateAssignmentEntry[], required
    - `hand` 'left' | 'right', required
    - `finger` 'thumb' | 'index' | 'middle' | 'ring' | 'pinky', required
    - `mask_id` integer, required
  - `finger_flips` HandTemplateFingerFlip[], nullable
    - `hand` 'left' | 'right', required
    - `finger` 'thumb' | 'index' | 'middle' | 'ring' | 'pinky', required
  - `custom_tip_dirs` HandTemplateCustomTipDir[], nullable
    - `hand` 'left' | 'right', required
    - `finger` 'thumb' | 'index' | 'middle' | 'ring' | 'pinky', required
    - `dx` number, required
    - `dy` number, required

## Response `200`

Successful Response

- HandTemplateDetailResponse: Single-template detail payload — extends the picker shape with the per-template preprocess cache. Returned by `GET /api/hand-templates/{id}`.
  - `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
  - `stage_status` object
  - `hand_preprocess` HandPreprocessArtifacts: Presigned URLs + parsed JSON for the per-template hand-preprocess cache populated by the worker. Surfaces in `GET /api/hand-templates/{id}`. The worker writes these artifacts under `apps/nail-art/templates/{template_id}/preprocess/` after the first try-on consumes a template; subsequent try-ons hit the cache and skip the SAM3 + VLM steps that produced them.
    - `bare` string, nullable
    - `sam3_masks` string[]
    - `labeled_overlay` string, nullable
    - `label_viz` string, nullable
    - `assignment_viz` string, nullable
    - `mask_centroids` array[], nullable
      - number[], nullable
    - `label_response` object, nullable
    - `fingertip_bboxes_viz` string, nullable
    - `assignments` object, 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)
