Idempotency
Opt-in safe retries with the Idempotency-Key header — 24-hour replay cache, conflict detection, and the privacy trade-off made explicit.
Safe retries
Network timeouts leave you not knowing whether a conversion happened — and whether retrying will bill you twice. Send an Idempotency-Key header on any POST and retries become safe:
curl -sS -X POST "https://api.transmute.403fin.io/v1/convert?to=camt.053" \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Idempotency-Key: stmt-2026-07-05-batch17" \
-H "Content-Type: text/plain" \
--data-binary @statement.mt940
The first request executes normally and its response is cached for 24 hours. A retry with the same key and the same body gets the cached response verbatim, marked:
Idempotency-Replayed: true
Replays are never billed and never consume quota. They do pass through rate limiting, so a burst of retries still counts against your request rate.
The rules
| Rule | Behavior |
|---|---|
| Key format | 1–255 characters; anything else is a 400 |
| Cache scope | Per API key + idempotency key + SHA-256 of the body |
| Same key, different body | idempotency-conflict 409 — pick a new key |
| Cache lifetime | 24 hours |
| Large responses | Responses over 1 MiB are not cached (the request still succeeds) |
File uploads (multipart/form-data) | Not supported — the header is refused with invalid-input 400, because the multipart boundary changes on every request. Use the JSON or raw form for idempotent retries |
Choose keys that identify the logical operation — a statement id, a file hash, a job id — not random values (a random key per attempt defeats the purpose).
The privacy trade-off, stated plainly
transmute keeps message bodies in request memory. The replay cache is one of the two documented places data is held for a limited time (the other is batch jobs), and it applies to every POST you send with the header, not only convert:
- What is kept: the full response (status, content type and a body of up to 1 MiB) and a SHA-256 of the request body. For convert, normalize, validate, verify, diff, anonymize and enrich, the body is the result, so it contains message data. For
POST /v1/webhooksit includes the one-time signing secret. - For how long: 24 hours from the first request. Entries cannot be deleted early.
- Where: in the API's process memory, or in Redis when a deployment configures one.
- Never kept: the raw request body. Only its hash is stored, for conflict detection.
If that retention is unacceptable for your data, omit the header. Idempotency is opt-in, and nothing else about the API changes.