Skip to main content

Idempotency

Written by Support

Every POST, PATCH, and DELETE requires an Idempotency-Key header.

Idempotency-Key: order-create-2026-04-30-abc123

Format: 1–64 chars, [A-Za-z0-9_-:.].

Use a stable, unique value per logical operation (e.g., a UUID generated client-side).

Where replay actually happens

Replay works only on https://api.dzbuild.app/v1. The response is cached for 24 hours and replays come back with Idempotency-Replay: 1.

On the dzbuild.com/api/v1 internal alias the header is validated but no replay cache is ever populated — two identical POST /v1/orders with the same key create two orders. One more reason to integrate against api.dzbuild.app only.

The cache is scoped to your key_id plus the Idempotency-Key: the same value sent under a different API key does not deduplicate.

POST /v1/signups and POST /v1/events still require the header, but they are accepted asynchronously and their responses are never stored — no replay cache protects those two routes.

⚠️ Warning — Idempotency protects against retries, not races

The replay entry is recorded only after your response has already been returned, so two genuinely simultaneous duplicate requests can still both execute. Serialize duplicate-prone writes on your side.

Keys are not bound to the request body

We match on the key alone — we never compare payloads. Reusing a key with a different body replays the first response instead of returning an error, silently, for 24 hours. So generate one key per logical operation (a fresh UUID), never one per endpoint, per session or per day.

Errors are cached too

A 4xx returned for a write is stored and replayed for 24 hours. After fixing a validation error, generate a new Idempotency-Key or you will just get the old error back. Errors returned before the request is processed — 401, 403, 429, or a malformed Idempotency-Key — are never stored. 5xx responses are not cached and may be retried with the same key. See Errors.

Telling a replay apart from a fresh call

Branch on Idempotency-Replay: 1 — a replay means no new side effect occurred, so skip any local post-processing you would run after a genuine write.

Don't confuse it with X-Cache: HIT|MISS, which is a separate, GET-only signal from the read cache.

Did this answer your question?