A payout moves money from a wallet's available balance to an external destination. Payouts are state-machined: a customer requests one, a staff user (or automation) approves and processes it, the rail confirms, and the payout completes or fails. Each step is a separate endpoint so you can hold, batch, audit, and reverse.
Customer endpoints
These are what a creator or seller dashboard calls. Auth is jwt resolved as a Customer principal.
/client/finance/payouts/requestJWTRequest a payout from the caller's own wallet. The wallet is auto-resolved from the authenticated customer; you don't pass a walletId.
| Field | Type | Description |
|---|---|---|
| amount* | number | Gross amount to pay out, in the wallet's currency. |
| methodId | string | ID of a saved payout method. Defaults to the customer's default method. |
| notes | string | Free-text note saved on the payout record. |
curl -X POST https://appengine.appmint.io/client/finance/payouts/request \
-H "orgid: $ORG" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{ "amount": 250.00, "notes": "March earnings" }'
/client/finance/payoutsJWTList the caller's payouts. Filter with ?status=pending|approved|processing|completed|failed|cancelled. Paginate with page and pageSize.
/client/finance/payouts/{payoutId}JWTSingle payout — only returned if recipient.id matches the authenticated customer.
Staff endpoints
Staff endpoints sit under /finance/* and require RoleType.User. They cover the full payout lifecycle.
Listing and lookup
/finance/payoutsJWTFilter with recipientType, recipientId, walletId, status. Returns pageable results.
/finance/payouts/number/lookup?payoutNumber=PO-...JWTLook up by the human-readable payoutNumber printed on receipts.
Lifecycle
/finance/wallets/{walletId}/request-payoutJWTSame as the customer endpoint, but staff-initiated and walletId-scoped.
/finance/payouts/{payoutId}/approveJWTApprove a pending payout. Body: { approvedBy: string, notes?: string }. Approval moves the payout to approved and reserves the funds.
/finance/payouts/{payoutId}/processJWTSubmit the payout to the configured external rail (PayPal/Venmo/bank ACH/etc., depending on the payout method). State moves to processing.
/finance/payouts/{payoutId}/completeJWTMark the payout as completed once the rail confirms settlement. Body: { externalReference?: string } — store the rail's transaction ID for reconciliation.
/finance/payouts/{payoutId}/failJWTMark failed and release the held funds back to the wallet's available balance. Body: { reason: string, code?: string }.
/finance/payouts/{payoutId}/cancelJWTCancel a payout that's still pending or approved. Body: { reason?: string }.
State machine
pending → approved → processing → completed
↓ ↓
cancelled failed
Once a payout is processing, you cannot cancel — only complete or fail. failed and cancelled both restore the held amount to available balance.
Hold periods
Earnings are typically credited as available immediately, but you can route specific transaction types through a hold. Use the wallet hold endpoints:
/finance/wallets/{walletId}/holdJWT{
"reason": "deposit",
"amount": 100.00,
"expiresAt": "2026-05-25T00:00:00Z",
"reference": "order-123",
"notes": "7-day clearing window"
}
reason is one of dispute | chargeback | security | deposit | pending_review | other. While held, funds count toward the pending balance and cannot be paid out.
/finance/wallets/{walletId}/release/{holdIndex}JWTRelease a hold by its index. Released funds move from pending to available.
Balance lookup
/finance/wallets/{walletId}JWTReturns the wallet record including balance.available, balance.pending, and balance.held. For per-wallet payout summary (totals + counts by status):
/finance/wallets/{walletId}/payout-summaryJWTBatch payouts
Run payouts for many wallets at once — common for marketplaces that pay sellers weekly.
/finance/batch/payoutsJWT{
"walletIds": ["wal_abc", "wal_def", "wal_ghi"],
"minAmount": 25.00
}
Wallets with available balance below minAmount are skipped. Each wallet's pending payout is created in pending state — call /approve and /process per payout (or chain them through automation).
Reversals
Payouts that have already completed cannot be undone via the payout API; they must be reversed by the underlying rail (e.g., a return ACH file). Once you receive a return, post a debit transaction to the wallet:
/finance/wallets/{walletId}/debitJWT{
"amount": 250.00,
"type": "chargeback",
"reference": "PO-...",
"description": "ACH return R01"
}
This restores the platform's books. The original payout record stays completed for audit.
Payout endpoints are not implicitly idempotent. If you re-run request you get a second payout. For automation, store the payout ID after creation and check before retrying.
Stats
/finance/stats/payoutsJWTReturns counts and amount totals grouped by status — useful for dashboards.