# Record an order (idempotent by order ID)

```http
POST /v1/orders
```

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

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

From the brand's server with a secret key or a restricted key with `orders:write`. Re-sending the same `id` updates the order (200); a new one is 201. The A/B arm comes from `visitor_id` (recomputed by TryYourSize) or `experiment_arm`. No customer data is accepted.

## Authentication

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

## Request body

`application/json`: `OutcomeOrderInput`

An order from the brand's server. Re-sending the same id updates it (idempotent). No customer data: there is no customer, email, name or address field, and unknown fields are refused.

- `id` (`string`, required, max length 200): Your order ID.
- `ordered_at` (`string (date-time)`, required)
- `currency` (`string`, optional): ISO 4217, e.g. EUR.
- `visitor_id` (`string`, optional, max length 64): The SDK's anonymous visitor ID (`(await tys.experiment())?.visitorId`), saved with the cart. TryYourSize recomputes the A/B arm from it and stores only its hash. Never a customer ID.
- `experiment_arm` (`"treatment" | "holdout"`, optional): The arm, when you cannot send visitor_id.
- `lines` (`OutcomeLineInput[]`, required, max 200 items)
  - `id` (`string`, required, max length 200): Your order line ID (unique within the order).
  - `product` (`string`, required, max length 200): Your product ID (the one you pass to the SDK).
  - `variant` (`string`, optional, max length 200)
  - `size` (`string`, required, max length 40): The size bought, in your labels.
  - `quantity` (`integer`, required)
  - `unit_price_minor` (`integer (int64)`, optional): Price of one unit in minor units (5995 = 59.95). Optional; used for the refund value estimate.
  - `tys_shown` (`boolean`, optional): A TryYourSize element was shown for this purchase.
  - `recommended_size` (`string`, optional, max length 40): The size TryYourSize recommended (the SDK's recommendation event, or the _tys_size cart line property).
  - `attribution` (`"cart_attribute" | "sdk" | "api"`, optional): Where recommended_size came from.

## Responses

### 200

Updated (`OutcomeOrderResult`)

- `id` (`string (uuid)`, required)
- `external_id` (`string`, required)
- `created` (`boolean`, required): False when the order already existed and was updated.
- `experiment_arm` (`"treatment" | "holdout"`, optional)
- `lines` (`integer`, required)

### 201

Created (`OutcomeOrderResult`)

- `id` (`string (uuid)`, required)
- `external_id` (`string`, required)
- `created` (`boolean`, required): False when the order already existed and was updated.
- `experiment_arm` (`"treatment" | "holdout"`, optional)
- `lines` (`integer`, required)

### 400

Invalid request (`Error`)

### 401

Missing or invalid credentials (`Error`)

### 403

Not allowed (`Error`)

## Example

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