Skip to main content
Networks fail. Processes crash. When a create call times out — a payment, a hosted payment page payment, or a refund — you cannot tell whether the operation happened. Idempotency keys make the answer not matter: retry safely, and you will never charge (or refund) a customer twice.

How it works

Every POST request requires an Idempotency-Key header — a string of your choice, up to 255 characters:
curl -X POST https://api.flowlix.dev/v1/payments/hpp \
  -H "Authorization: Bearer api_test_sk_abc123def456" \
  -H "Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
A key is unique per API key and operation (payment create, hosted payment create, refund create). On a retry, the request body is compared with the original request:
SituationResult
First request with a keyProcessed normally
Retry: same key, same bodyThe original response is replayed — no new object is created
Retry: same key, different body (any field)409 Conflict with error.type: "idempotency_error"
Retry while the first request is still in flight409 Conflict — wait briefly and retry
Missing Idempotency-Key header400 invalid_request_error (parameter_missing)
Additional rules:
  • Only successful (2xx) responses are cached. If a request failed with an error, retrying with the same key executes it again.
  • Keys expire after 24 hours. After expiry, a reused key behaves like a brand-new one.
  • Keys are scoped to your API key (and therefore to its test/live mode) and to the operation type: the same key value sent to POST /v1/payments and POST /v1/refunds identifies two independent operations.

Choosing keys

One-shot operations

For a payment created from a checkout button press, a random UUIDv4 generated per attempt is fine. Store it with the attempt so a retry after a crash reuses the same key.

Business operations

For operations tied to a business fact — “refund order 1234 once” — derive the key deterministically, e.g. refund-ord_1234-1. Then any process, host, or job retrying the operation collapses to a single refund.

Retry recipe

  1. Generate the key before sending the request and persist it alongside your order/operation record.
  2. On timeout or 5xx: retry with the same key and the exact same body, using exponential backoff (for example 1s, 2s, 4s, …).
  3. On 409 idempotency_error: your retry’s body differs from the original, or the original is still processing. Re-send the original body unchanged; if you intend a different operation, use a new key.
  4. Never reuse a key for a logically different request — a new payment attempt gets a new key.
merchant_reference does not deduplicate requests — two creates with the same merchant_reference and different idempotency keys produce two payments. Idempotency is provided only by the Idempotency-Key header.