Documentation

Payouts

Request, approve, process, and reconcile payouts from wallets.

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.

POST/client/finance/payouts/requestJWT

Request a payout from the caller's own wallet. The wallet is auto-resolved from the authenticated customer; you don't pass a walletId.

FieldTypeDescription
amount*number

Gross amount to pay out, in the wallet's currency.

methodIdstring

ID of a saved payout method. Defaults to the customer's default method.

notesstring

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" }'
GET/client/finance/payoutsJWT

List the caller's payouts. Filter with ?status=pending|approved|processing|completed|failed|cancelled. Paginate with page and pageSize.

GET/client/finance/payouts/{payoutId}JWT

Single 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

GET/finance/payoutsJWT

Filter with recipientType, recipientId, walletId, status. Returns pageable results.

GET/finance/payouts/number/lookup?payoutNumber=PO-...JWT

Look up by the human-readable payoutNumber printed on receipts.

Lifecycle

POST/finance/wallets/{walletId}/request-payoutJWT

Same as the customer endpoint, but staff-initiated and walletId-scoped.

POST/finance/payouts/{payoutId}/approveJWT

Approve a pending payout. Body: { approvedBy: string, notes?: string }. Approval moves the payout to approved and reserves the funds.

POST/finance/payouts/{payoutId}/processJWT

Submit the payout to the configured external rail (PayPal/Venmo/bank ACH/etc., depending on the payout method). State moves to processing.

POST/finance/payouts/{payoutId}/completeJWT

Mark the payout as completed once the rail confirms settlement. Body: { externalReference?: string } — store the rail's transaction ID for reconciliation.

POST/finance/payouts/{payoutId}/failJWT

Mark failed and release the held funds back to the wallet's available balance. Body: { reason: string, code?: string }.

POST/finance/payouts/{payoutId}/cancelJWT

Cancel 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:

POST/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.

POST/finance/wallets/{walletId}/release/{holdIndex}JWT

Release a hold by its index. Released funds move from pending to available.

Balance lookup

GET/finance/wallets/{walletId}JWT

Returns the wallet record including balance.available, balance.pending, and balance.held. For per-wallet payout summary (totals + counts by status):

GET/finance/wallets/{walletId}/payout-summaryJWT

Batch payouts

Run payouts for many wallets at once — common for marketplaces that pay sellers weekly.

POST/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:

POST/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.

Idempotency

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

GET/finance/stats/payoutsJWT

Returns counts and amount totals grouped by status — useful for dashboards.