API
View as Markdown

Idempotency

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

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 body200/201/204 with the cached response. The header X-Idempotent-Replay: true is set. The side effect does not run again.
  • Same key, different body409 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.