Idempotency-Key header. A write without one gets 400 IDEMPOTENCY_KEY_REQUIRED. Each operation’s reference page shows whether it takes one.
How it behaves
A key can be at most 255 characters. Its answer is replayed for 7 days per tenant. After that, a key that posted an entry or created a hold is still refused, with
IDEMPOTENCY_KEY_REUSED, so a very late retry never posts twice.
A refusal is replayed too
The stored outcome includes refusals. If a payout gotINSUFFICIENT_FUNDS, sending the same key again gives INSUFFICIENT_FUNDS again, even after the customer has topped up. To try again as a new attempt, use a new key.
If the failure was on PanoQore’s side, such as a 500 or a dropped connection, nothing was stored, and retrying with the same key is the right thing to do.
Choosing a key
Generate it before the call and store it with your own transaction, so a retry after your process restarts uses the same one. A value derived from your own record, likeinstalment:42:paid, works well.
Operations without the header
POST /v1/partners/{partner}/creditsis idempotent on the partner’s transaction id. A repeat answers withresult: DUPLICATEand credits nothing. See Named accounts.- Webhook endpoint calls do not use the header.
POST /v1/fee-schedules/previewchanges nothing, so it does not need one.
Duplicates across keys
Idempotency-Key protects a retry, not your business rule. By default externalRef is not unique: two entries can share it.
If your retries can’t share a key, for example when each attempt from a queue gets its own, set uniqueExternalRef: true on the entry. Only one live entry can then hold that reference, whatever the key, even when attempts race. A second gets 409 EXTERNAL_REF_EXISTS, and you can read the first by its reference. Voiding an entry frees the reference. A reversal doesn’t, because the original still happened.
To find an entry by its reference: