Payouts
A payout sends money from your available balance to a bank account you name, as Stripe’s payouts do. In Argentina that is a CVU, a CBU or an alias.
How a payout works
Section titled “How a payout works”- You create a payout with
POST /payouts. Its amount and the payout fee of your agreement are held from your available balance at once, and the payout ispending. You get the webhook eventpayout.created. - We send it from one of our accounts. While it is being sent it is
processing. - It ends
paidonce the recipient’s bank took it, orfailed; then you getpayout.paidorpayout.failed. A failed payout’s amount and fee are back in your available balance, andfailure_codesays why.
Rarely we cannot tell at once whether a transfer went through: the payout is then requires_review, you get payout.requires_review, and our team checks it with the bank. It ends paid or failed, and nothing is sent twice.
A payout belongs to the merchant account whose key made it: another account’s key does not see it, and an Idempotency-Key is the account’s.
Live mode is not open yet. A live key’s POST /payouts is 409 payouts_not_available, and nothing is held: make test payouts with your test key meanwhile. Live payouts open with an announcement in the Changelog.
Its life
Section titled “Its life”| Status | |
|---|---|
pending |
Created: the amount and fee are held. Not sent yet; you may cancel it. |
processing |
Being sent. |
paid |
The recipient’s bank took it. The fee is taken. |
failed |
Not sent, or refused by the bank: failure_code says why. The amount and fee are back in your available balance. |
requires_review |
Our team is checking whether it went through. It ends paid or failed. |
canceled |
You canceled it while it was pending. The amount and fee are back in your available balance. |
New statuses may be added: treat one you do not know as not paid.
Making one
Section titled “Making one”curl https://api.63-180-91-99.sslip.io/payouts \-H "Authorization: Bearer sk_test_ar_…" \-H "Idempotency-Key: 3f2b8c1e-7d4a-4b9e-9a6c-2e1d5f4c3b2a" \-H "Content-Type: application/json" \-d '{ "amount": 2500000, "currency": "ARS", "destination": { "type": "cvu", "cvu": "0000003100000000000017" }, "recipient": { "tax_id": { "type": "ar_cuit", "value": "20-12345678-6" } }, "description": "Withdrawal 4821", "metadata": { "user_id": "u_4821" }}'-
amountis what the recipient’s account receives, in the currency’s smallest unit (centavos). The payout fee is held beside it: more than you have available is400 balance_insufficient, and nothing is made. -
destinationis the account: itstypeand that field alone.cvu: 22 digits, starting000, with their check digits.cbu: 22 digits with their check digits.alias: 6 to 20 letters, digits, dots and dashes, read in lower case.
A destination that is not one of its type is
400 parameter_invalidwithparam: destination; a type your market’s payouts do not take,param: destination.type. -
recipient.tax_idis optional: the account’s holder, as a payment’scustomer.tax_id(ar_cuit,ar_cuilorar_dni). When you send it, the account’s holder is checked against it before anything is sent, and a payout to another holder fails withrecipient_tax_id_mismatch. -
Send an
Idempotency-Key. The same key again answers the same payout,Idempotent-Replayed: true, and holds nothing more; the key with other parameters is400 idempotency_error.
The answer is 201 with the payout:
{"id": "po_ar_01JB4R7X9K2M5N8P3Q6S9T1V4W","object": "payout","status": "pending","market": "AR","amount": 2500000,"currency": "ARS","fee": 25000,"destination": { "type": "cvu", "alias": null, "last4": "0017" },"recipient": { "tax_id": { "type": "ar_cuit", "value": "20-•••••678-6" } },"failure_code": null,"description": "Withdrawal 4821","metadata": { "user_id": "u_4821" },"created": 1761213600,"ended_at": null,"livemode": false,"version": 1}A payout answers its destination back by the account number’s last four digits, or the alias, and the recipient’s tax id masked.
Canceling one
Section titled “Canceling one”POST /payouts/{id}/cancel cancels a payout that is still pending: its amount and fee are back in your available balance, and you get payout.canceled. One that is being sent or has ended is 409 payout_not_cancelable. Canceling a canceled payout answers it as it is.
Why a payout fails
Section titled “Why a payout fails”failure_code |
|
|---|---|
recipient_account_not_found |
No account has that CVU, CBU or alias. |
recipient_tax_id_mismatch |
The account’s holder is not the recipient.tax_id you sent. |
transfer_rejected |
The bank refused the transfer. |
More codes may be added.
Test mode
Section titled “Test mode”A test key makes test payouts from your test balance, as live ones are made, and none is ever sent anywhere. Instead, the last two digits of the amount (in minor units: centavos) decide what happens to it, the way magic UTRs do a test payment’s. Each change is the one a live payout gets on that path: its status, its balance lines and its webhook events.
| Amount ends in | What happens |
|---|---|
01 (e.g. 2500001) |
processing, then paid at once. |
02 |
processing, then failed at once: recipient_account_not_found. |
03 |
processing, then failed at once: recipient_tax_id_mismatch. |
04 |
processing, then failed at once: transfer_rejected. |
05 |
processing, then requires_review at once, then paid 5 seconds after it was made. |
06 |
Stays pending until you cancel it. |
| Anything else | processing at once, then paid 5 seconds after it was made. |
“At once” means within a second or two: read the payout again, or wait for its events. A failed test payout’s amount and fee are back in your test balance, as a live one’s are. A test payout that cannot be sent in the test environment stays pending, or, once on its way, fails with transfer_rejected. Live mode has no magic amounts.
Endpoints
GET/payoutsListPayoutsPOST/payoutsCreatePayoutGET/payouts/{id}GetPayoutPOST/payouts/{id}/cancelCancelPayout
Loading the reference…