# Idempotency And Concurrency

> Idempotency-Key for retry-safe creates and If-Match for concurrency-safe updates — when to use which and what each guarantees.

Source: https://business-api-docs.youhodler.com/docs/concepts/idempotency-and-concurrency

Two cross-cutting headers govern safe writes against the public API:
`Idempotency-Key` for retry-safe creation, and `If-Match` for safe
concurrent updates. They solve different problems and apply at different
moments — read them as separate tools, not as alternatives.

Use them on every write that matters: a stuck network, a retried
deployment, or two concurrent operators must never produce duplicate
operations or silently overwrite each other.

> **Practical rule:** Send `Idempotency-Key` on every `POST` that creates a resource or triggers an operation. Send `If-Match` on every `PATCH` and on lifecycle transitions that depend on the resource's current state.

## Idempotency

`Idempotency-Key` makes a write safely retryable. The platform stores the
result of the first call against a key and returns the same result for
any retry that uses the same key.

Read the contract this way:

- A key is a caller-chosen opaque string, scoped per endpoint
- Same key with the same body → returns the original result
- Same key with a different body → conflict (`409`)
- Keys have a finite retention window; after expiry the key can be reused

This lets you retry a `POST` after a network error without risking a
duplicate operation.

## Concurrency Control

Resources that can change state expose an `etag`. Writes that depend on
the current state pass the `etag` back as `If-Match`.

Read the contract this way:

- Every read returns the current `etag` on the resource
- A `PATCH` or lifecycle transition with `If-Match: "<etag>"` succeeds
only if the resource still matches that version
- A mismatched `If-Match` returns `412 Precondition Failed`
- The caller is expected to re-read, re-evaluate, and retry

This prevents two concurrent operators from overwriting each other and
turns optimistic concurrency into a first-class part of the API contract.

## When To Use Which

- **Create or trigger** a resource → `Idempotency-Key`
- **Update** an existing resource (`PATCH`) → `If-Match`
- **Lifecycle transition** that depends on current state (e.g. suspend,
reactivate, close) → `If-Match`
- **Cancel** an in-flight operation → `If-Match` against the operation's
current `etag`

The two headers can be used together on a single request when both apply.

## How This Appears In The API

**Request URL — POST**
```http
POST /clients
```
**Request Headers — required**
```json
Authorization: Bearer <token>
Idempotency-Key: 9b9c2c5e-6c2a-4b3e-9b8e-7a5c2f1d3e4a
Content-Type: application/json
```
**Request URL — PATCH**
```http
PATCH /clients/44444444-4444-4444-8444-444444444444
```
**Request Headers — required**
```json
Authorization: Bearer <token>
If-Match: "v3:01HZ9X..."
Content-Type: application/json
```
