API versionv2 next

API v2 is not live yet: it launches in early 2027, and until then these pages are its spec. Switch to v1 (live)

Idempotency

A request that moves money must happen once, even when the connection breaks before you have the answer. Send it with an Idempotency-Key, and send it again with the same key: we do it once, and answer each time with the first result.

When to retry, with which key, and what to do with a request that stays in doubt is in the note Retries and idempotency.

Which requests

Request Takes a key
Capture, refund, void Yes
Charge subscriber Yes
Create payment link, create and renew subscriber No: a second link does no harm, as no one has its URL.
Delete payment link, delete subscriber No: deleting twice does no harm.
Seq No: it changes nothing.

The key

Idempotency-Key: xM3h1STdPREZVWXVNeTBqNzkwUTZUaHdCRWp4ZldGWHdKWjBX

The key is any string of printable ASCII, which you make up for one request, and which no other request of yours has. A random value of 128 bits or more, in hex or base64, is a good key, as is a UUID. Spaces at its ends are trimmed. The whole request line and headers must fit in 4 KiB, which bounds its length.

Make the key when you decide to make the request, and store it with what the request is for, such as the order and the capture of it, before you send it. Then a retry, even one from another process after a crash, sends the same key.

What we do with it

  1. The first request with a key runs, and we store its whole answer, status, headers, and body, whether it succeeded or failed.
  2. A request with the same key, sent while the first still runs, waits for it to finish.
  3. A request with the same key, sent later, is not run: we answer with the stored answer, and the header Idempotency-Status: OK, which says that it is a replay.

We keep a key for 24 hours after its first request. A request with the key after that runs anew.

A failure is stored like a success. A key protects a request whose answer you never got; once you have an answer, even an error, the key has done its job, and a retry with it gets that answer again. To try a failed request again, make a new key.

We don't compare a replay with the first request: a key reused for another request gets the first request's answer, and the second request is never run. Use each key for one request only.

Errors

Error Meaning
400 invalid idempotency key The header is empty, or there is more than one Idempotency-Key header.
500 idempotency error: {why} We could not store or read the answer for the key, and did not run the request. This answer, unlike others, is not stored under the key: try again, with the same key.

Without a key

A request without a key runs every time you send it. Two charges of a subscriber sent without a key, where one was meant, both go through. For a capture, a refund, or a void, the "index" stops the second, which fails with 409 index mismatch, but then you can't tell from it whether the first went through, and have to synchronize to know. Always send a key.