# Create a product

```http
POST /v1/products
```

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

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

The SKU / style ID (`external_id`) is unique per store (409). Send an `Idempotency-Key` to retry safely.

## 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`: `ProductInput`

- `external_id` (`string`, required)
- `name` (`string`, required)
- `category` (`"tshirt" | "shirt" | "sweater" | "jacket" | "dress" | "skirt" | "jeans" | "trousers" | "shorts" | "leggings" | "polo" | "hoodie"`, required): The garment type; it sets which POMs are needed.

## Responses

### 201

Created (`Product`)

- `id` (`string (uuid)`, required)
- `external_id` (`string`, required): The brand's SKU or style ID (unique per brand).
- `name` (`string`, required)
- `category` (`"tshirt" | "shirt" | "sweater" | "jacket" | "dress" | "skirt" | "jeans" | "trousers" | "shorts" | "leggings" | "polo" | "hoodie"`, required): The garment type; it sets which POMs are needed.
- `published_version` (`integer`, optional): Garment version shoppers are fitted against, if any.
- `draft_version` (`integer`, optional): Garment version being edited, if any.
- `created_at` (`string (date-time)`, required)
- `updated_at` (`string (date-time)`, required)
- `fit_group_id` (`string (uuid)`, optional): The fit group whose garment this product uses (absent until grouped).
- `brand_id` (`string (uuid)`, optional): The brand the product belongs to; every store of the brand sees it.
- `home_store_id` (`string (uuid)`, optional): The store the product was created in.
- `retired_at` (`string (date-time)`, optional): Set when the product is retired; shoppers no longer get a size for it.
- `available` (`boolean`, optional): Whether the store it was read through offers it (false in the brand list, see `stores`).

### 400

Invalid request (`Error`)

### 401

Missing or invalid credentials (`Error`)

### 403

Not allowed (`Error`)

### 409

Conflicts with the current state (duplicate SKU, editing a published version) (`Error`)

## Example

```bash
curl -X POST https://api.tryyoursize.com/v1/products \
  -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.products.create()`](https://docs.tryyoursize.com/reference/node/products-create.md)
- Python: [`tys.products.create()`](https://docs.tryyoursize.com/reference/python/products-create.md)
