Idempotency-Key header works at the HTTP layer on every write route listed below. The clientRequestId body field works at the trade level on POST /v1/trades. Use either, or both.
Idempotency-Key header
A-Z a-z 0-9 _ - : . (400 IDEMPOTENCY_KEY_TOO_LONG or 400 IDEMPOTENCY_KEY_FORMAT_INVALID otherwise).
Honoured on: POST /v1/trades, POST /v1/trades/{id}/confirm, POST /v1/redemptions, POST /v1/markets/{id}/disputes and POST /v1/webhooks/events/{eventId}/redeliver. Keys are scoped per user and per route.
Behaviour:
- First request: runs normally. A
2xxresponse is stored under the key for 24 hours. - Same key, same request: the stored response is returned with its original status and body, plus the header
Idempotent-Replay: true. Nothing runs again. - Same key, different request:
409 IDEMPOTENCY_KEY_CONFLICT. “Same request” means the same method, URL and JSON body. - Same key while the first request is still running:
409 IDEMPOTENCY_REQUEST_IN_PROGRESS. Retry a few seconds later with the same key to get the original response. - Errors are not stored. A
4xxor5xxreleases the key, so you can fix the request and retry with the same key. - After 24 hours the key is forgotten, and a request with it runs as new.
Idempotent-Replay header rather than _meta.idempotent to detect an HTTP-level replay.
clientRequestId body field
clientRequestId is stored on the trade itself (1 to 128 characters from A-Z a-z 0-9 _ - : .):
- First request with a given value: the trade is created (
201). - Same value, same body: the existing trade is returned with
200and_meta.idempotent: true. No new trade. - Same value, different body:
409 CLIENT_REQUEST_ID_CONFLICT.
Using both
They layer cleanly. The header absorbs transient HTTP retries;clientRequestId guarantees one trade per logical order for as long as the trade exists. The TypeScript SDK sends an Idempotency-Key on every POST automatically.
High-value trades
A trade at or above your key’s high-value threshold returns202 with a one-time confirmation token. Retrying the create with the same Idempotency-Key returns that same stored 202, with the same token, and creates nothing. The token itself is single-use: a second confirm returns 409 CONFIRMATION_TOKEN_USED. If you lose the confirm response, read the trade with GET /v1/trades/{id}.
Conflict response
Routes without Idempotency-Key
POST /v1/auth/api-keys/me/webhook-secret/rotaterotates on every call, guarded by a 60-second cooldown (429 WEBHOOK_SECRET_ROTATION_COOLDOWN). Don’t retry it blindly: see Secret rotation.
Next
Pagination
Cursor pagination on every list endpoint.
ETags
Conditional requests for cheap polling.