# See a product on the shopper's body

```http
POST /v1/tryon
```

Source: https://docs.tryyoursize.com/api/reference/operations/starttryon/

**Key:** publishable (`pk_test_…` / `pk_live_…`), from an origin registered for the key.

Shows every size of the product's published garment on the body and recommends a size (from a few seconds to about 2 minutes). A body already shown with this garment version answers 200 at once; otherwise 202 and a job to poll. Every answer carries a new `viewer_token`, the only way (with the shopper's session) to read the job. With a shopper session (`Authorization: Bearer tys_sess_…`) the try-on is linked to the shopper and, in live mode, delivering a done result records the store connection and the size the store receives.

## Authentication

Publishable key (`pk_test_…` / `pk_live_…`), from an origin registered for the key.

## Parameters

- `view` (query, `"full" | "summary"`, optional): `full` (default) answers with the whole `result` (meshes for every size, MBs). `summary` leaves `result` out and answers `summary` instead (the recommended size and the sizes that can be worn, a few bytes): for the size-guide button and the store's recommended-size event, which never need the meshes.
- `start` (query, `boolean`, optional): `false` answers only with an existing result and never queues a simulation: a done or running try-on of this body, or 404 ("not simulated yet"). With `view=summary`, a miss may answer 200 with a size estimate instead (`status: done`, empty `id`, `summary.method: estimate`). Page views (the size-guide and inline elements) use it; a full simulation starts only on an explicit shopper action ("See it on you").

## Request body

`application/json`: `TryOnRequest`

The product and the shopper's body as on screen: the same body as `/v1/bodies/preview`, with the preview's `body_state` (required; opaque).

- `product` (`string`, required, max length 120): The product's SKU / style ID in the store (what the shop passes to the element).
- `basics` (`BodyBasics`, required)
  - `sex` (`"female" | "male"`, required)
  - `age_years` (`integer`, required)
  - `height_mm` (`number (double)`, required)
  - `weight_kg` (`number (double)`, required)
- `measurements` (`Measurement[]`, optional, max 64 items)
  - `code` (`"neck_girth" | "shoulder_width" | "arm_length" | "armscye_girth" | "upper_arm_girth" | "wrist_girth" | "chest_girth" | "underbust_girth" | "bust_point_to_bust_point" | "shoulder_to_bust_point" | "back_length" | "waist_girth" | "front_waist_arc" | "high_hip_girth" | "abdomen_girth" | "hip_girth" | "front_hip_arc" | "thigh_girth" | "knee_girth" | "calf_girth" | "ankle_girth" | "inseam" | "outseam" | "crotch_length"`, required): Body measurement from set v1.
  - `value_mm` (`number (double)`, required): Measured value in millimetres.
  - `source` (`"tape_self" | "tape_helper" | "flat_garment" | "estimated"`, required)
- `body_state` (`number (double)[]`, required, max 64 items): The `body_state` of the body preview on screen.

## Responses

### 200

Done (an existing result) (`TryOnJob`)

- `id` (`string`, required): The try-on's id (uuid). Empty only for a size estimate (POST ?start=false&view=summary answered with no try-on of this body); there is nothing to poll.
- `viewer_token` (`string`, optional): Only in the answer to POST /v1/tryon: the window's proof that it may read this try-on. Send it as `Authorization: Bearer tys_view_…` to GET /v1/tryon/{tryon_id}. Stored hashed; never sent again.
- `status` (`"queued" | "running" | "done" | "failed"`, required)
- `progress` (`object`, required)
  - `sizes_done` (`integer`, required)
  - `sizes_total` (`integer`, required)
- `result` (`object`, optional): Present when `status` is `done`, and while it runs: the sizes computed so far, each with `method` (simulated) and `state` (preview: shown early, may still change; settled; refining: still being computed, no mesh yet; simulated). The try-on result for the window: body mesh and body_state (no basics, no tape measurements), garment with its fabric and estimated POMs, recommended size and per-size meshes, pressure kPa, ease mm and zones. Binary arrays are base64 little-endian; per-vertex values are rounded to display precision.
- `summary` (`object`, optional): Present when `status` is `done` and the request asked for `view=summary`: what a store may receive (sizes only, never measurements). Size labels are the garment's (Studio) sizes; map them with `shop_sizes` from GET /v1/products/{product}/tryon.
  - `recommended_size` (`string`, optional): The recommended size; absent when no size can be worn.
  - `no_size_fits` (`boolean`, required)
  - `wearable_sizes` (`string[]`, required): Sizes that can be worn on this body (judged on this body), smallest to largest.
  - `method` (`"estimate" | "simulated"`, optional): How the size was determined: `estimate` (a size estimate, no try-on of this body yet) or `simulated` (from the try-on of this body). A coarse informational label: do not build logic on its values.
- `recommendation` (`object`, optional): The size answer with its method. On the first answer of a try-on it may already be there (`method: estimate`) while the 3D view is computed; once done it is the try-on's own size. An estimate is final (`ready` or `none`) only when it is certain for this body; otherwise the status is `computing`, no size is named, and the try-on's 3D view gives it.
  - `recommended_size` (`string`, optional)
  - `method` (`"estimate" | "simulated"`, required): Same as `summary.method`. A coarse informational label; do not build logic on its values.
  - `status` (`"ready" | "none" | "computing" | "unavailable"`, required)
  - `wearable_sizes` (`string[]`, optional)
- `error` (`object`, optional): Present when `status` is `failed`.
  - `code` (`string`, required): INVALID_BODY, UNSUPPORTED_CATEGORY, MISSING_POM, INVALID_POM, INVALID_FABRIC, NO_SIZES, UNAVAILABLE or ENGINE_ERROR.
  - `message` (`string`, required)

### 202

Queued or running; poll GET /v1/tryon/{tryon_id} (`TryOnJob`)

- `id` (`string`, required): The try-on's id (uuid). Empty only for a size estimate (POST ?start=false&view=summary answered with no try-on of this body); there is nothing to poll.
- `viewer_token` (`string`, optional): Only in the answer to POST /v1/tryon: the window's proof that it may read this try-on. Send it as `Authorization: Bearer tys_view_…` to GET /v1/tryon/{tryon_id}. Stored hashed; never sent again.
- `status` (`"queued" | "running" | "done" | "failed"`, required)
- `progress` (`object`, required)
  - `sizes_done` (`integer`, required)
  - `sizes_total` (`integer`, required)
- `result` (`object`, optional): Present when `status` is `done`, and while it runs: the sizes computed so far, each with `method` (simulated) and `state` (preview: shown early, may still change; settled; refining: still being computed, no mesh yet; simulated). The try-on result for the window: body mesh and body_state (no basics, no tape measurements), garment with its fabric and estimated POMs, recommended size and per-size meshes, pressure kPa, ease mm and zones. Binary arrays are base64 little-endian; per-vertex values are rounded to display precision.
- `summary` (`object`, optional): Present when `status` is `done` and the request asked for `view=summary`: what a store may receive (sizes only, never measurements). Size labels are the garment's (Studio) sizes; map them with `shop_sizes` from GET /v1/products/{product}/tryon.
  - `recommended_size` (`string`, optional): The recommended size; absent when no size can be worn.
  - `no_size_fits` (`boolean`, required)
  - `wearable_sizes` (`string[]`, required): Sizes that can be worn on this body (judged on this body), smallest to largest.
  - `method` (`"estimate" | "simulated"`, optional): How the size was determined: `estimate` (a size estimate, no try-on of this body yet) or `simulated` (from the try-on of this body). A coarse informational label: do not build logic on its values.
- `recommendation` (`object`, optional): The size answer with its method. On the first answer of a try-on it may already be there (`method: estimate`) while the 3D view is computed; once done it is the try-on's own size. An estimate is final (`ready` or `none`) only when it is certain for this body; otherwise the status is `computing`, no size is named, and the try-on's 3D view gives it.
  - `recommended_size` (`string`, optional)
  - `method` (`"estimate" | "simulated"`, required): Same as `summary.method`. A coarse informational label; do not build logic on its values.
  - `status` (`"ready" | "none" | "computing" | "unavailable"`, required)
  - `wearable_sizes` (`string[]`, optional)
- `error` (`object`, optional): Present when `status` is `failed`.
  - `code` (`string`, required): INVALID_BODY, UNSUPPORTED_CATEGORY, MISSING_POM, INVALID_POM, INVALID_FABRIC, NO_SIZES, UNAVAILABLE or ENGINE_ERROR.
  - `message` (`string`, required)

### 400

Invalid request (`Error`)

### 401

Missing or invalid credentials (`Error`)

### 403

Not allowed (`Error`)

### 404

No published garment for the product, or (start=false) this body was not simulated yet (`Error`)

### 422

The content is rejected (e.g. a body that cannot be rebuilt) (`Error`)

### 503

A dependency is temporarily unavailable; retry later (`Error`)

## Example

```bash
curl -X POST https://api.tryyoursize.com/v1/tryon \
  -H "Authorization: Bearer pk_test_…" \
  -H "TYS-Version: 2026-10-25" \
  -H "Content-Type: application/json" \
  -d @body.json
```
