Confirm and replay financial operations
Sensitive customer actions require a short-lived confirmation intent. Every provider mutation also requires an idempotency key and returns an asynchronous operation.Create a confirmation intent
Create an intent with the action and normalized payload fingerprint. Transfer confirmation uses the quote identifier; mandate and card confirmation uses the same public fields as the later mutation.Submit an idempotent mutation
Send the confirmation and idempotency identifiers as headers:202 Accepted with an operation. Repeating the same key and body returns that operation. Reusing the key with another body returns a stable 409 with code idempotency_key_conflict.
Rely on the replay window
Each idempotency key is honoured for twenty-four hours from first acceptance. A replayed acceptance carries the response headerIdempotent-Replayed: true. The header is absent on a first acceptance and is never sent as false, so its presence alone distinguishes a replay. A replay returns the operation’s current state, not a snapshot of the original response — a transfer accepted yesterday may already read succeeded or failed — so follow a replay with GET /v1/operations/{operation_id} when you need the outcome.
A key presented after its window is refused with 409 and code idempotency_key_expired, and the request is never executed. The remedy is a fresh key for the same intent — never a second uncoordinated mutation. Expired records are removed on a schedule that touches no operation row, so the operations themselves remain readable indefinitely.
Client guidance: mint one UUID per user intent, send it on every transport retry of that intent, and keep it until the operation settles. Do not derive keys from payload content alone, and do not reuse a key for a new intent.
Which routes take a key
Every route that creates or transitions a financial or card resource requiresIdempotency-Key: beneficiary creation, transfers, mandate creation, revocation, execution, operator suspension, card creation, and the card freeze, unfreeze, and close transitions.
Quotes, confirmation intents, card reveal sessions, KYC sessions, and approval polls take no key: a quote is a re-readable estimate whose one-use confirmation prevents duplicate transfers, intents and reveal sessions are short-lived single-use objects, the hosted KYC session performs no provider write, and polls are reads with idempotent local effects.
Complete browser approval
A transfer or mandate operation can enterrequires_action with a trusted Perflo URL, expiry, and poll delay. Open the URL without an opener, then call POST /v1/operations/{operation_id}/approval/poll. Repeated polling cannot enqueue another execution.
Handle provider uncertainty
The worker commitssubmitting before each provider money or authority write. A timeout, reset, possible-acceptance server error, malformed accepted response, or restart while submitting produces indeterminate.
Never create another mutation to recover an indeterminate operation. Read GET /v1/operations/{operation_id} while the scheduler performs read-only reconciliation. Operator review remains required when provider evidence is missing or ambiguous.