# Idempotency

> How the Tradavity Public API Idempotency-Key header guarantees retry-safe writes.
> Source: https://help.tradavity.com/api-docs/idempotency
> Category: Core Concepts

---

Write requests (POST, PATCH, PUT, DELETE) accept an `Idempotency-Key` header so retries are safe:

```http
POST /api/v1/trades
Authorization: Bearer tvty_YOUR_KEY_HERE
Idempotency-Key: my-script-2026-05-10-trade-1
Content-Type: application/json

{ ... trade body ... }
```

If the same key is reused within 24 hours with the same body, the server returns the cached response (and sets `X-Idempotent-Replay: true`) without re-executing the write. Reusing the same key with a *different* body returns HTTP `409 idempotency_conflict`.

Concurrent identical requests are also safe: only one wins the “leader” slot and runs the side effect; the others poll briefly and return the leader’s response. So five parallel POSTs with the same Idempotency-Key produce one DB row plus four replays, never five rows.

**Replays still count against your rate limit.** Each call — fresh or replayed — decrements `X-RateLimit-Remaining` by one. The replay path is cheap (no side effect, returns the cached body) but it is a billable request. Build your retry logic to back off on transport errors rather than blindly re-sending the same key in a tight loop.

The key must be 1–64 characters of `[A-Za-z0-9_-]`. Use a UUID or a deterministic identifier from your client (e.g. `{user}-{operation}-{timestamp}`).

## Idempotency contract in detail

Every write endpoint accepts an `Idempotency-Key` header. The contract is:

- **Fresh key** → the side effect runs once. The full response is cached for 24 hours.
- **Same key, identical body** → `200/201/204` with the cached response. The header `X-Idempotent-Replay: true` is set. The side effect does **not** run again.
- **Same key, different body** → `409 idempotency_conflict`. Pick a fresh key.
- **Five concurrent identical requests** → one wins the “leader” slot and runs the side effect. The other four poll for up to 30 seconds, then return the leader’s cached response. Net result: exactly one row inserted, all five callers get `201`.
- Keys must be 1–64 characters of `[A-Za-z0-9_-]`. UUIDs are perfect. Deterministic strings like `{user}-{operation}-{2026-05-10}` also work.

The 24-hour window starts at the original request time. After that, the same key can be reused for a fresh write.

> **Always send Idempotency-Key on writes**
> The server caches responses by `(api_key, Idempotency-Key)` for 24 hours. A retry of the same request returns the cached response without re-executing the side effect. A retry with a *different* body returns `409 idempotency_conflict`. Without this header, a network retry can double-create rows.
