Aliquot
Payments

Payouts

Paying settled balances out to a wallet — the 2FA step-up for dashboard sessions, API keys with a step-up, the flat network fee and the payout lifecycle.

Last updated Oct 27, 2026

A payout sends part or all of an account's available balance (GET /api/v1/crypto/balances?mode=) on one network and token to an external address, from the hot wallet.

curl -X POST "$API/api/v1/crypto/payouts" \
  -H "authorization: Bearer $KEY" -H 'content-type: application/json' -H 'idempotency-key: po-2026-10-27-halden' \
  -d '{ "account": "halden_type", "network": "POLYGON_AMOY", "token": "USDT",
        "amount": "50.00", "destination_address": "0x…" }'

Who may pay out

Payouts need crypto-payouts:create and are refused while a platform admin impersonates the user. On top of that, every payout is stepped up:

  • Dashboard (cookie session): each payout carries a fresh TOTP code (totp_code). The user must have two-factor authentication enabled (Settings → Security); the New payout dialog links there otherwise. Codes are single use, and 5 failed codes in 15 minutes lock step-ups (429 STEP_UP_LOCKED). A wrong or reused code is 403.
  • API keys skip the per-payout code, so the step-up moves to the moment the key is minted: creating a key with crypto-payouts:create (or crypto-payouts:manage, or *:*) requires a non-impersonated browser session with 2FA and a valid totp_code. Only such keys carry payoutStepUpAt; any other key answers 403 STEP_UP_REQUIRED. Keys minted before this rule lost payout capability. The operator CLI (mint:api-key) also sets it.

Amount and fee

A flat network fee per payout comes out of the amount (net_amount = amount − fee) and is booked as REVENUE:PAYOUT_NETWORK_FEE: CRYPTO_PAYOUT_FEE_POLYGON (default 0.10), CRYPTO_PAYOUT_FEE_BSC (0.15), CRYPTO_PAYOUT_FEE_BASE (0.10). The amount must exceed the fee. The destination must be a valid address that is not one of the gateway's own (contracts are allowed, unlike refunds).

Lifecycle

StatusMeaning
QUEUEDCreated: the amount is locked in the ledger (MERCHANT_LOCKED) in the same transaction, so a payout above the balance is 409 INSUFFICIENT_BALANCE and creates nothing.
BROADCASTSigned and sent by the worker once the hot wallet can cover net_amount and the gas (it waits for sweeps otherwise). The transaction is journaled before broadcast, so a crash re-sends the same bytes; after 180 s without a receipt it is replaced with the same nonce and fees +20 %.
COMPLETEDThe transaction reached the network's confirmation threshold; the lock is released into the payout (payout.completed).
FAILEDReverted or dropped: the lock goes back to the available balance and the gas is expensed (payout.failed).

The dashboard's Payouts page shows the balances on top, the history below (live confirmation count while BROADCAST), and New payout (source balance, amount, destination pre-filled with the account's settlement address, TOTP).

[!WARNING] When an invoice has no merchant, the organization's PLATFORM account is the seller: its net is credited to PARTNER_PAYABLE together with the markup, the one balance PLATFORM payouts draw from. Every payout therefore draws from the balance the dashboard shows as available.

On this page