# Idempotency and retries

> Retry POST requests safely with an Idempotency-Key. Stored 24 hours per store and mode.

Source: https://docs.tryyoursize.com/guides/idempotency/

Networks fail. To retry a `POST` without doing it twice, send an `Idempotency-Key` header with a unique value per logical request (a UUID v4 is ideal; 1–255 printable ASCII characters).

```bash
curl https://api.tryyoursize.com/v1/products \
  -H "Authorization: Bearer $TYS_SECRET_KEY" \
  -H "TYS-Version: 2026-10-25" \
  -H "Idempotency-Key: 6f1c1f0e-7a8b-4c1e-9d6f-0b3a2e5c4d11" \
  -H "Content-Type: application/json" \
  -d '{"external_id":"CREW-TSHIRT","name":"Crew T-shirt","category":"tshirt"}'
```

The SDKs take it as an option: `{ idempotencyKey }` (Node) or `idempotency_key=` (Python).

## How it behaves

| Situation | Answer |
|---|---|
| First request | Runs normally. The response is stored for **24 hours**, per store and mode (secret and restricted keys). |
| Retry with the same key and the same body | The stored response, with the header `Idempotent-Replayed: true`. |
| Retry while the first request is still running | `409` [`idempotency_key_in_use`](https://docs.tryyoursize.com/api/errors.md#idempotency_key_in_use): wait and retry. |
| Same key, different body | `422` [`idempotency_key_reused`](https://docs.tryyoursize.com/api/errors.md#idempotency_key_reused): use a new key for a new request. |
| Malformed key | `400` [`invalid_idempotency_key`](https://docs.tryyoursize.com/api/errors.md#invalid_idempotency_key). |
| The first response was a 5xx | Not stored: a retry runs again. |

## Naturally idempotent endpoints

`POST /v1/orders` is idempotent by your order ID and `POST /v1/returns` by (line, return ID): sending the same order again updates it. An `Idempotency-Key` still protects against duplicate work during a retry.

## When to retry

- **Retry** on network errors, timeouts, `409 idempotency_key_in_use`, `429` (after `Retry-After`) and `5xx`, with exponential backoff and the **same** key.
- **Do not retry** other `4xx` answers unchanged: fix the request first.
