Moves money from one of your wallets to up to 100 destinations, with
the amounts you send. Each destination becomes a leg with its own
status, and names who is paid in one of five ways:
- a payee:
payeeId, from an earlier disbursement or
POST /payees; - a person:
emailAddressand/ormobileNumber, withnameif
they are new to PayKeeper andssnif you have it; - a company:
organizationNameand the contact'semailAddress
(withnamefor the contact andeinif you have them); - a company already on PayKeeper:
organizationId; - a wallet:
walletId, one of your own wallets (a holdback into a
reserve wallet, say), or a payee's wallet.
People and companies are found or created exactly as POST /payees
would, and the leg's payeeId says who they resolved to. The same
person or company named in a later disbursement is the same payee. A
leg to anyone who has not yet claimed their account carries their
onboardingUrl, ready for your own email. A company new to PayKeeper
is paid into a wallet PayKeeper holds for it until it onboards; when
it does, that money and every later payment reach its own wallet.
The wallet must be able to cover the total plus PayKeeper's fee (see
Fees), or nothing is created: ids, rules and the balance are checked
before any payee is found or created, and before any money moves. The
balance that counts is what is left after disbursements you have
already made that are still settling, so two disbursements can never
spend the same money. One disbursement from a wallet is created at a
time; a second sent meanwhile gets 409 wallet_busy, and can simply be
sent again. The legs and the fee are written together or not at all,
and none of them moves until all of them exist. If PayKeeper cannot
confirm the balance with its ledger just then, or cannot finish writing
in time, the answer is a 503 and nothing is created.
If a destination cannot be resolved (a 409 name_mismatch, say),
nothing is created: every destination is checked before any payee is
found or created for another. A request that fails after that, with a
503, pays nobody, but a payee it created on the way stays, and a
retry finds the same payee again.
A leg doesn't post only if the wallet can no longer cover it, or
PayKeeper cancels or rejects it; its failureCode says which, and its
money stays in the source wallet. To pay it again, send a new
disbursement with just that leg, under new externalIds. A leg never
waits for money: if money leaves the wallet after the disbursement was
accepted (a returned deposit, say) and a leg can no longer be covered,
that leg is canceled with failureCode: INSUFFICIENT_FUNDS, so it can
never pay out of money that arrives later.
Every disbursement is sent with an Idempotency-Key. A retry with the
same key and body never pays twice: it gets this disbursement back,
with Idempotent-Replayed: true, even if the first response was lost
after the disbursement was accepted.
The response is the disbursement as accepted, usually PROCESSING.
The payout and disbursement webhooks tell you the outcome, and
GET /disbursements/{disbursementId} is the record.
| Status | code | When |
|---|---|---|
| 400 | invalid_field | A field is the wrong type or too long, there are more than 100 destinations, an emailAddress is not an email address, an ein or ssn is not nine digits (or an impossible SSN, such as area 000), a company was given a mobileNumber or an ssn, or statementDescriptor has characters other than capitals, digits and spaces. |
| 400 | invalid_amount | A destination's amount is not a positive money value with its currency. |
| 400 | unsupported_field | The body has scheduledFor or waitForFunds. Neither is supported yet; a disbursement runs as soon as it is accepted. |
| 400 | missing_destination | A destination names nobody: no payeeId, walletId, person, company or organizationId. |
| 400 | missing_contact | A destination has an ssn but no emailAddress or mobileNumber to say whose it is. |
| 400 | missing_field | destinations is missing or empty, a company destination has no contact emailAddress, or an ein came without an organizationName (a person has an ssn, not an ein). |
| 400 | duplicate_external_id | Two destinations have the same externalId, or a destination has the disbursement's. |
| 400 | ambiguous_destination | A destination gives more than one of payeeId, walletId and a payee's details, or an organizationId with other payee fields. |
| 400 | external_reference_not_allowed | sourceWalletId, a walletId or a payeeId is an ext: reference. |
| 400 | payee_name_required | A destination names a person new to PayKeeper without a name. |
| 400 | invalid_body | The body is not a JSON object. |
| 400 | idempotency_key_required | There is no Idempotency-Key header. Nothing is created. |
| 400 | invalid_idempotency_key | The Idempotency-Key is longer than 255 characters, is not printable ASCII, or was sent twice. |
| 404 | wallet_not_found | sourceWalletId is not one of your wallets. |
| 404 | destination_not_found | A walletId is neither one of your payees' wallets nor one of your own. |
| 404 | payee_not_found | A payeeId is not one of your payees. |
| 404 | organization_not_found | An organizationId is not an organization on PayKeeper. |
| 409 | external_id_already_exists | You already have a disbursement (or another object) with this externalId. |
| 409 | leg_external_id_already_exists | A destination's externalId is used by a leg of an earlier disbursement, or by another of your objects. Nothing was created. |
| 409 | wallet_busy | Another disbursement from this wallet is being created. Send this one again in a moment. |
| 409 | payee_busy | Another request is setting up the same new person right now. Nothing was created; send it again after Retry-After seconds. |
| 409 | contact_mismatch | A destination's email address and mobile number belong to two different people. |
| 409 | ssn_mismatch | A destination gives a person a different ssn than you gave before. |
| 409 | name_mismatch | A destination's email address or mobile number belongs to someone else: the family name or first name in its name is not theirs. |
| 409 | ein_name_mismatch | A destination's ein belongs to a company with a different name. |
| 409 | idempotency_key_in_use | A request with this Idempotency-Key is still running. Send it again after Retry-After seconds. |
| 422 | insufficient_available_balance | The wallet cannot cover the total plus PayKeeper's fee, after what earlier disbursements still owe. |
| 422 | invalid_mobile_number | A destination's mobileNumber is not a valid mobile number. |
| 422 | payee_not_created | PayKeeper could not create a destination's person. |
| 422 | ssn_not_accepted | This environment cannot store an SSN yet. Leave ssn out. Checked before anything is created. |
| 422 | idempotency_key_reused | This Idempotency-Key was already used for a different request. Use a new key. |
| 503 | balance_unavailable | PayKeeper could not confirm the wallet's balance with its ledger just now. Nothing was created; send it again. |
| 503 | timed_out | The disbursement could not be written in time. Nothing was created; send it again. |
| 503 | upstream_busy | PayKeeper's banking provider asked it to slow down. Send it again after Retry-After seconds, with the same Idempotency-Key. |
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
