# Publish a complete draft

```http
POST /v1/garments/{garment_id}/publish
```

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

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

The version shoppers are fitted against from now on, for every product of its fit group. The same checks as Studio: every required point of measure for every size, fabric, the fit approval when the store requires it, every shop size mapped, and the plan's styles (402). Test answers drafts, live answers published versions only.

## Authentication

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

## Parameters

- `garment_id` (path, `string (uuid)`, required): A garment *version* (garment_versions.id). A fit group (garments table) is `fit_group_id`.
- `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.

## Responses

### 200

Published (`GarmentVersion`)

- `id` (`string (uuid)`, required)
- `product_id` (`string (uuid)`, required)
- `version` (`integer`, required)
- `status` (`"draft" | "published" | "retired"`, required)
- `category` (`"tshirt" | "shirt" | "sweater" | "jacket" | "dress" | "skirt" | "jeans" | "trousers" | "shorts" | "leggings" | "polo" | "hoodie"`, required): The garment type; it sets which POMs are needed.
- `fit_intent` (`"skinny" | "slim" | "regular" | "relaxed" | "oversized"`, required): The designer's intended silhouette; sets the ease targets the fit judgement compares against.
- `sizes` (`string[]`, required)
- `poms` (`POMTable`, required): Garment measurements per size: size label → POM code → millimetres. Widths are flat half-measurements. See GET /v1/studio/garment_dictionary for codes and plausible ranges.
- `grading` (`GradingRule`, optional): How the POM table was derived: the base size's values plus, per POM, the increment (mm) between each pair of consecutive sizes (len = number of sizes - 1). The table stays the source of truth.
  - `base_size` (`string`, required)
  - `increments_mm` (`object`, required)
- `fabric` (`Fabric`, required): What the tech pack / mill sheet says.
  - `name` (`string`, optional)
  - `construction` (`"jersey" | "rib" | "interlock" | "fleece" | "pique" | "plain_weave" | "twill" | "denim" | "satin" | "other"`, optional)
  - `composition` (`FiberShare[]`, required)
    - `fiber` (`"cotton" | "polyester" | "elastane" | "viscose" | "modal" | "lyocell" | "wool" | "linen" | "polyamide" | "silk" | "acrylic" | "other"`, required)
    - `pct` (`number (double)`, required)
  - `weight_gsm` (`number (double)`, optional): Areal density, g/m².
  - `stretch_warp_pct` (`number (double)`, optional): Stretch along the warp (lengthwise), percent.
  - `stretch_weft_pct` (`number (double)`, optional): Stretch along the weft (crosswise), percent.
  - `notes` (`string`, optional)
- `import_id` (`string (uuid)`, optional)
- `issues` (`GarmentIssue[]`, required): What still blocks publishing (errors) or deserves a look (warnings).
  - `severity` (`"error" | "warning"`, required)
  - `code` (`string`, required): e.g. out_of_range, not_graded, missing_pom, composition_total
  - `field` (`string`, required): category | fit_intent | sizes | poms | grading | import | fabric.<field>
  - `size` (`string`, optional)
  - `pom` (`string`, optional)
  - `params` (`IssueParams`, optional): The values in `message`, for clients that word the finding in their own language (keys depend on `code`, e.g. value_mm, min_mm, max_mm, prev_size, fiber, max). Numbers are plain decimals ("." separator); lengths in mm.
  - `message` (`string`, required): English text; clients in other languages can word it from code, size, pom and params.
- `created_at` (`string (date-time)`, required)
- `updated_at` (`string (date-time)`, required)
- `published_at` (`string (date-time)`, optional)
- `season` (`string`, optional)
- `tolerances_mm` (`TolerancesMM`, optional): Spec-sheet tolerance per POM code, ± mm (e.g. {"chest_width": 10}). Optional; the flat preview uses ±5 mm when a POM has none.
- `spec_source` (`SpecSource`, optional): Where the POM table came from, kept for audit. Set by Studio's paste/import.
  - `kind` (`"manual" | "paste" | "xlsx" | "csv" | "pdf" | "workbook" | "clo" | "browzwear"`, required)
  - `filename` (`string`, optional, max length 255)
- `fit_group_id` (`string (uuid)`, optional): The fit group (garments row) this version belongs to (absent until grouped).

### 401

Missing or invalid credentials (`Error`)

### 403

Not allowed (`Error`)

### 404

Not found (`Error`)

### 409

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

### 422

Values to fix (each issue points at the field, size and POM) (`GarmentRejected`)

## Example

```bash
curl -X POST https://api.tryyoursize.com/v1/garments/<garment_id>/publish \
  -H "Authorization: Bearer $TRYYOURSIZE_SECRET_KEY" \
  -H "TYS-Version: 2026-10-25"
```

## In the SDKs

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