Using an idempotency key
AnIdempotency-Key header is mandatory on every POST request. A request without one is rejected with an error.
A key must be between 10 and 256 characters long (inclusive) and may contain only letters, numbers, dashes (-), underscores (_), and colons (:). A request whose key is too short, too long, or includes any other character is rejected with an error.
Choose a key that stays the same across retries of the same action. The best key is a meaningful identifier from your own database, such as the ID of the payout or invoice the transfer settles. Reusing that identifier when you retry is what lets us recognize the retry and return the original result. You can pass a random version 4 UUID instead, but a new random key on each attempt provides no idempotency at all, because there is nothing for us to match against.
How it works
The first request made with a given key is processed normally, and we store the key against the resource it created. Any later request that reuses the same key returns that resource without running the action again. A replayed request returns the latest state of the resource, not a snapshot of the original response. If the resource has changed since the first call (for example, a transfer that has moved frompending to completed), the replay reflects that current state rather than what was returned the first time.
A response served this way includes an Idempotency-Replayed: true header so you can tell it apart from a freshly processed request.
Keys are stored permanently, so a replay works no matter how much time has passed.
Retries
The reason to send an idempotency key is to retry safely when you can’t tell whether we received the first request — a dropped connection or a timeout. When the outcome is unknown, retry with the same key. We resolve it one of three ways:- The first request succeeded: we return the modified object’s latest state and set
Idempotency-Replayed: truein the header. - The first request is still in progress: you get
409 Conflict. Wait a moment and retry the same key. - The first request failed: you get
500, with a message that something went wrong on the previous request for this key.
500. Use a new idempotency key to make a fresh attempt.
One action per key
A key is bound to the endpoint it was first used on. Reusing it on a different endpoint returns422 Unprocessable Entity. Within the same endpoint we do not compare request bodies, so reusing a key returns the original resource even if you send a different body. Always use a distinct key for each distinct action so a changed request is never mistaken for a retry.
Idempotency keys are mandatory
EveryPOST request requires an Idempotency-Key, and a request sent without one is rejected with an error. The endpoints where this protects you from costly duplicates include:
- Move money externally: avoid sending the same ACH transfer twice
- Move money internally: avoid duplicate internal transfers
- Create external account: avoid saving the same recipient twice
GET requests are already idempotent and do not take the header.