# The shopper's recommended size for up to 25 products

```http
POST /v1/recommendations
```

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

**Key scopes:** `fit_checks:read`. A secret key (`sk_`) has every scope; a restricted key (`rk_`) needs the scopes listed.

From the brand's server (or a headless storefront's backend) with a secret key, or a restricted key with `fit_checks:read`. Send the handle the browser SDK gave your page (`tys.recommendationHandle()`); the answer has sizes only, in your size labels, never measurements. Like a page view, it never starts a simulation: a body already simulated with the garment answers with the existing result, or with a size estimate when one is certain for this body; otherwise the status is `unavailable` until the shopper asks for the try-on. A delivered size counts as a fit check, like in the browser. The handle's mode must match the key's (a test handle with a live key is 403). A handle whose shopper deleted their account or disconnected the store is refused (401 `handle_invalid`).

## Authentication

Secret key (`sk_…`) or restricted key (`rk_…`) from your server: `Authorization: Bearer sk_…`.

## Parameters

- `Idempotency-Key` (header, `string`, optional): A unique value per logical request (a UUID v4 is ideal), 1-255 printable ASCII characters. With a secret or restricted key, the first response is stored for 24 hours per store and mode: a retry with the same key and the same body gets the stored response back (header `Idempotent-Replayed: true`); the same key with a different body is `422 idempotency_key_reused`; a retry while the first request still runs is `409 idempotency_key_in_use`. Responses with a 5xx status are not stored, so a retry runs again.

## Request body

`application/json`: `RecommendationsRequest`

- `handle` (`string`, required, max length 8192): A recommendation handle from the browser SDK (`tys.recommendationHandle()`).
- `products` (`string[]`, required, max 25 items): Product SKUs / style IDs (what you pass to the element as `product`).

## Responses

### 200

One answer per product, in the order asked (`RecommendationList`)

- `data` (`ServerRecommendation[]`, required)
  - `product` (`string`, required)
  - `status` (`"ready" | "computing" | "none" | "unavailable"`, required): `ready`: a size. `computing`: a simulation the shopper started is running (ask again later). `none`: simulated, no size can be worn. `unavailable`: no published garment for this product, not simulated on this body yet, or the store's plan has no fit checks left. A page view or this API never starts a simulation.
  - `size` (`string`, required): The recommended size in the store's label (the product's size map), or null.
  - `studio_size` (`string`, required): The same size as entered in TryYourSize Studio, or null.
  - `wearable_sizes` (`string[]`, required): Sizes that can be worn on this body, in the store's labels.
  - `method` (`"estimate" | "simulated"`, optional): How the size was determined: `estimate` (a size estimate certain for this body, no try-on of it yet) or `simulated` (from a try-on of this body). A coarse informational label: do not build logic on its values.
  - `tryon_id` (`string (uuid)`, optional): The try-on that produced the size, when there is one. Send it back with orders for attribution.
- `mode` (`"test" | "live"`, required)

### 400

Invalid request (`Error`)

### 401

Missing or invalid credentials (`Error`)

### 403

Not allowed (`Error`)

### 429

Too many requests; retry later (`Error`)

## Example

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

## In the SDKs

- Node.js: [`tys.recommendations.create()`](https://docs.tryyoursize.com/reference/node/recommendations-create.md)
- Python: [`tys.recommendations.create()`](https://docs.tryyoursize.com/reference/python/recommendations-create.md)
