---
title: "Generate Thumbnail Route"
method: POST
path: "/api/thumbnails/generate"
---

# Generate Thumbnail Route

`POST /api/thumbnails/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/thumbnails/generate`
- Auth: HTTP bearer

Charge + enqueue one NB2-edit catalog thumbnail (async, SQS worker).

Sequence: resolve reference → fingerprint → series_id lookup → create
job + hand_result rows → charge 1 studio credit → enqueue → return a
`running` JobCreateResponse. The worker (`_process_thumbnail_gen`) runs
NB2 (nano-pro fallback) + uploads, and the frontend polls `getJob`.
Was synchronous; moved async to remove the multi-second request hold +
bring it onto the same charge/refund path as try-on.

## Request body

- ThumbnailGenerateRequest: POST `/api/thumbnails/generate` body. Single reference image of the nail design (a raw `s3_key` uploaded via `/api/uploads/standalone-presign`), plus a handful of optional knobs the user can tune in the form. Reasonable defaults are baked in so the simplest call is just `{"reference_s3_key": "..."}`.
  - `reference_s3_key` string, nullable
  - `nail_set_label` string, nullable
  - `lighting` 'studio' | 'soft' | 'natural' | 'dramatic', nullable
  - `angle` 'top' | 'three_quarter' | 'macro', nullable
  - `spacing_mm` number, nullable
  - `refinement` string, nullable
  - `collection_tag` string, nullable
  - `aspect_ratio` 'auto' | '21:9' | '16:9' | '3:2' | '4:3' | '5:4' | '1:1' | '4:5' | '3:4' | '2:3' | '9:16' | '4:1' | '1:4' | '8:1' | '1:8', nullable

## Response `201`

Successful Response

- JobCreateResponse
  - `id` string, uuid, required
  - `series_id` string, uuid, required
  - `status` 'draft' | 'pending' | 'running' | 'succeeded' | 'failed', required
  - `nail_set_s3_key` string, required
  - `hands` HandResultResponse[], required
    - `id` string, uuid, required
    - `hand_idx` integer, required
    - `status` 'charging' | 'running' | 'succeeded' | 'failed' | 'refunded', required
    - `hand_s3_key` string, required
    - `hand_template_id` string, uuid, nullable
    - `hand_url` string, nullable
    - `bare_s3_key` string, nullable
    - `warp_s3_key` string, nullable
    - `final_s3_key` string, nullable
    - `final_url` string, nullable
    - `candidate_s3_keys` string[], nullable
    - `candidate_urls` string[], nullable
    - `candidate_video_urls` string[], nullable
    - `cents_charged` integer, nullable
    - `error_message` string, nullable
    - `created_at` string, date-time, required
    - `finished_at` string, date-time, nullable
  - `total_cents_charged` integer, required
  - `created_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)
