Skip to content
On this page

Developers › After the payment

Balance and payouts

How money reaches your bank account, and how to reconcile it when it does.

Verified 6 November 2026Explain this to your team →

View as Markdown

How funds move

A payment goes through three states after the card is charged, and each is a real balance you can read rather than a label on a screen.

StateWhat it means
pendingCaptured. Still inside your settlement delay, so it cannot be paid out yet.
availableThe delay has passed. This is what the next payout draws on.
paid outIncluded in a payout. It has left your balance for your bank account.

The settlement delay is yours to choose — two days by default — and it exists so that a card taken this morning and refunded this afternoon costs nothing to unwind. Money crosses from pending to available on the hour, once its delay has passed.

ts
const balance = await sp.balance.retrieve();

balance.available;          // [{ amount: 114000, currency: "bzd" }]  — the next payout draws on this
balance.pending;            // [{ amount:  47500, currency: "bzd" }]  — still inside the delay
balance.payouts_in_transit; // [{ amount:  80000, currency: "bzd" }]  — already sent, not yet confirmed
Every amount is an integer in the currency’s minor unit, and payouts are always in Belize dollars. You may price in US dollars; what leaves the pooled merchant account is BZD, because that is the currency the bank settles in.

Balance transactions

A balance_transaction is one movement of your balance. Payments, refunds, payouts and adjustments are four different resources with four different lifecycles; what they have in common is that each moved the balance by some amount, and this list is that. Its net column sums, across the whole list, to pending + available. That is the property to reconcile against.

ts
const page = await sp.balanceTransactions.list({ limit: 25 });

page.data[0];
// {
//   id: "btxn_9f4c1e2a7b8d4f0aa1c3e5d7b9f0a2c4",
//   type: "charge",
//   amount: 12000,   // the gross, signed in your favour
//   fee: 600,        // what we charged, signed
//   net: 11400,      // amount - fee, and the column that sums to your balance
//   status: "available",
//   source: "pi_3KqL8xQpR2sT7vW9yZ1aB4cD",
// }
A payment appears once. When its settlement delay passes, that same row’s status changes from pending to available — the release is not a second transaction, and totalling the list never double-counts anything.
typeWhat it issource
chargeA card payment. Positive.The payment intent, pi_…
refundMoney returned to a cardholder, including a refund made directly at the bank. Negative.The refund, re_… — its payment_intent leads back to the payment
payoutA payout leaving for your bank account. Negative.The payout, po_…
payout_reversalA payout that was cancelled or returned. Positive: the money came back.The payout, po_…
adjustmentA correction we made, with a reason recorded against it. Also the fee a bank kept for returning a payout.The adjustment, or the payout for a bank’s return fee
dispute / dispute_reversalA chargeback held against you, or given back.The dispute
application_fee / application_fee_refundOnly when a platform acts for you: the fee it took from a payment, or that fee given back.The fee, or the fee refund
connect_collection_transferOnly when a platform acts for you: the platform covering a negative balance that could not be recovered.The platform’s cover
Every amount on this list is in Belize dollars — currency is always bzd — because that is what your balance is held in. A charge’s amount is what the card was charged, the payment’s settlement_amount, not the amount it was priced at: a US$25.00 payment is a charge of 5000. A refund of it is likewise the BZD that went back, at the payment’s own rate, and its fee is negative when our fee was returned with it.

Payouts

A payout takes your whole available balance and sends it to your bank account. It is never an amount you choose: there is no POST /v1/payouts, and there will not be one, because an amount a caller supplies is an amount that can be asked for twice.

You choose the schedule in the dashboard under Settings → Payouts: daily, weekly on a day you pick, monthly on a date you pick, or only when you ask. A scheduled payout is cut at 09:00 Belize time on the day it is due, and skipped if your balance is below the minimum you set — the money is not lost, it rides into the next one.

ts
const payouts = await sp.payouts.list({ status: "paid" });

payouts.data[0];
// {
//   id: "po_7Kq2LxR9sT4vW8yZ1aB3cD5e",
//   amount: 114000,
//   currency: "bzd",
//   status: "paid",
//   destination: { bank_name: "Example Bank", account_last4: "4321" },
//   bank_reference: "2022835577",
// }
statusWhat it means
pendingCut. The transfer has not been made yet.
in_transitThe transfer has been initiated at the bank.
paidThe bank confirmed it. bank_reference is the bank's own reference for it.
canceledCalled off before the transfer. The money is back in your available balance.
failedThe bank refused it before it left. The money is back in your available balance.
returnedIt was paid, and then the bank sent it back. The money is back in your available balance, less any fee the bank kept.
A person makes each transfer, so a payout is not instant and we do not publish a time it will take. status is what it is actually doing, and bank_reference is what you can search for at your own bank once it says paid. The email we send your team when it is paid labels it as an estimate, never a promise. Estimated arrival: the same day for some banks, and the next business day for others.

In test mode, a payout goes to a simulated destination and needs no bank details. It moves to paid by itself within about 20 minutes, with a bank_reference starting SIMULATED-, and payout.paid fires as it would in live. No money moves.

To rehearse what happens when a payout doesn't arrive, make a test payout fail or come back with a test key:

bash
curl -X POST https://api.secureprocessing.app/v1/test_helpers/payouts/po_.../fail \
  -H "Authorization: Bearer sk_test_..."
  • fail: the bank refuses the transfer before it leaves. The payout becomes failed, its money is back in your available balance, and you get payout.failed. Only a pending or in_transit payout can fail.
  • return: the transfer left and came back. The payout becomes returned, its money is back in your available balance, and you get payout.failed and then payout.returned. A payout that hasn't been paid yet is paid first, so you get payout.paid before them.

Both take an optional failure_code, such as account_closed or invalid_account_number. A live key is refused.

You give us your bank details in your activation application, and can edit them there until you submit it — or again if we ask you for more information. After that you ask for a change in the dashboard under Settings → Payouts, and it is never made by itself: our staff call you back on the number already on file before they approve it, and the first payout to the new account waits for a person to check it. The account number is encrypted and only its last four digits appear on any screen or document of yours; the full number is decrypted only when our staff need it to make the transfer, and each time is recorded.

Reconciling a payout

Every payout can name exactly what it paid for, and the report is a CSV with every money column twice — in minor units for a script, and formatted for a person checking a bank statement.

bash
curl https://api.secureprocessing.app/v1/reports/payout_reconciliation/po_7Kq2LxR9sT4vW8yZ1aB3cD5e \
  -H "Authorization: Bearer sk_live_..." -o payout.csv

The same movements are available as objects, so you can reconcile in code rather than in a spreadsheet:

ts
import { autoPaginate } from "@secureprocessing/node";

// Every page, not just the first: a payout can cover more movements than one page holds.
let total = 0;
for await (const line of autoPaginate((page) =>
  sp.payouts.listTransactions("po_7Kq2LxR9sT4vW8yZ1aB3cD5e", page),
)) {
  total += line.net;
}

const payout = await sp.payouts.retrieve("po_7Kq2LxR9sT4vW8yZ1aB3cD5e");
total === payout.amount; // true

Over HTTP that is the balance transactions list filtered to one payout — there is no separate path. Like every list it returns ten rows unless you ask for up to 100, so follow has_more before you total it:

bash
curl "https://api.secureprocessing.app/v1/balance_transactions?payout=po_7Kq2LxR9sT4vW8yZ1aB3cD5e&limit=100" \
  -H "Authorization: Bearer sk_live_..."
That last line holds by construction, not by convention: a payout takes the whole available balance, so the movements it covers are exactly the ones between the previous payout and this one. If it ever does not hold, tell us — it means something we have not seen before.

A payout that was cancelled keeps its own report, naming what it would have covered, and the reversal that put the money back appears on the next payout’s report. Each movement belongs to exactly one payout, so the reports never double-count and never lose a line between them.

Events

Subscribe to these rather than polling. They are documented in full on the webhooks page.

EventWhen
balance.availableMoney finished its settlement delay. One event per release, not one per payment.
balance.adjustedWe moved your balance by hand — a correction, a write-off, or a debt. The reason is on the event.
payout.createdA payout was cut. Its amount has left your available balance.
payout.updatedThe transfer has been initiated.
payout.paidThe transfer left our account. bank_reference names it.
payout.canceledCalled off. The money is back in your available balance.
payout.failedThe bank refused or returned it. The money is back in your available balance.
payout.returnedIt left and the bank sent it back. The money is back in your available balance, less any fee the bank kept. Sent with payout.failed.