Skip to Content

Idempotency

POST /v1/scans and POST /v1/exports do real, billable work — a duplicated request is a duplicated scan or export. The Idempotency-Key header makes retries safe: the first request with a given key executes; any replay of the same key with the same body returns the original response instead of running again.

curl https://api.regsn.app/v1/scans \ -H "Authorization: Bearer $REGSN_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 5f2b7c1e-0a44-4c5b-9d3e-8a1f2b3c4d5e" \ -d '{ "jurisdictions": ["UK"], "areas": ["Payments"], "horizon": 6 }'

Rules

PropertyValue
HeaderIdempotency-Key
Format1–255 printable ASCII characters (a UUID is the sensible choice)
EndpointsPOST /v1/scans, POST /v1/exports (ignored elsewhere)
ScopePer API key and per endpoint — the same string used on /v1/scans and on /v1/exports names two unrelated records
Window24 hours
CachedSuccessful (2xx) responses only
OptionalYes — omit the header and the request executes normally

The request body is fingerprinted (top-level key order does not matter). Replay behaviour depends on what matches:

SituationResult
Same key, same body, original succeededOriginal response replayed, with header Idempotency-Replayed: true
Same key, same body, original still running409 · idempotency_in_progress — wait and retry the same key
Same key, different body409 · idempotency_key_in_use — use a fresh key for a new request
Same key, original failed (non-2xx)Not cached — the retry executes normally
Malformed header422 · invalid_idempotency_key

Failures are not cached — by design. If your scan hit 402 budget_exhausted or a 503, retrying with the same key re-executes rather than replaying the error. You only ever “lock in” a success.

Replay in practice

# First call: executes, returns 202 curl -s -D - https://api.regsn.app/v1/exports \ -H "Authorization: Bearer $REGSN_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: export-a1b2-pdf-v1" \ -d '{ "snapshot_id": "a1b2…", "provider": "internal-pdf", "artifact_type": "pdf" }' # Identical retry (e.g. after a client timeout): same 202 body, no new job # Response now includes: # Idempotency-Replayed: true

Check for the Idempotency-Replayed: true header when it matters whether work actually ran.

Recommendations

  • Generate one UUID per logical operation and reuse it across retries of that operation — not per HTTP attempt.
  • Deterministic keys (e.g. nightly-scan-2026-07-20) are useful for cron-style jobs: a rerun of the same tick can never double-scan. Keep the 24-hour window in mind for schedules longer than a day.
  • Both SDKs auto-generate a UUID key for every POST when you do not pass one, so their internal retries are always safe. Pass your own key when retries span process restarts.

See also

  • Errors — the 409/422 codes above, in context.
  • Rate limits — pair Retry-After waits with the same key.
Last updated on