LidyaDocs

Idempotency

Networks fail. Servers reboot mid-request. To make our write endpoints safe to retry, every POST accepts an X-Idempotency-Key header.

How it works

When you include X-Idempotency-Key, Lidya:

  1. Hashes the request body.
  2. If we've seen this (api-key, endpoint, key) tuple in the last 24 hours with the same body hash, we return the cached response.
  3. If we've seen it with a different body, we return 409 idempotency_key_reuse — your code has a bug.
  4. Otherwise we process the request normally and cache the response.

Choosing a key

Use a uuid v4 per logical operation:

const key = crypto.randomUUID();
const charge = await createCharge({ idempotencyKey: key, ... });

If the network call fails, retry with the same key. We'll either return the original response (if the first attempt reached us) or process the new request idempotently.

What's not covered

GET requests are idempotent by definition and ignore the header.

The 24h cache is the soft window — for true exactly-once guarantees on long-running flows, anchor on the resource's merchantReference instead. merchantReference is unique per organization for the lifetime of the resource.

Replay rules

The cache is keyed by the canonicalized request body — whitespace, key order, and missing optional fields don't change the hash. But changing a numeric value (amount: 100 vs amount: 200) is a different request and you'll get the conflict response.