- A crypto payout detail is a wallet address on a specific network.
- A fiat payout detail is a bank account, IBAN or SWIFT.
POST /api/v2/payouts and wondered where crypto_payout_detail_id and fiat_payout_detail_id come from, this is the page.
Payout destinations are configured in the dashboard, not through the public API. The
/api/v2/crypto_payout_details and /api/v2/fiat_payout_details endpoints accept a logged-in dashboard session only; an API key or OAuth token gets 401. Add destinations at app.southpay.io under Settings → Payouts, then read the ids from the payout screen or from a payout schedule you create.This is deliberate. A credential that can create payouts cannot also redirect where they go.Using one in a payout
POST /api/v2/payouts takes asset_id, amount_atomic, and exactly one destination. The three forms are mutually exclusive.
Idempotency-Key is required; without it you get 422. See Idempotency. Payout keys are not scoped to your store, so make them globally unique.
Sending none of the three returns 422 destination_required.
destination_address skips the saved-destination system entirely and pays a raw address you supply per request. It is convenient and it is unaudited: nothing validates that the address belongs to you, and nothing records who chose it. Prefer a saved crypto_payout_detail_id for anything recurring.payout_schedule key.
Crypto payout details
A saved wallet address, pinned to one network.
The network on the destination must match the network of the asset you are paying out. Paying
ETH_USDC to a polygon address returns 422 with a message naming both networks. SouthPay does not bridge between chains during a payout.
Two constraints will surprise you eventually:
- Address and network are immutable once the detail has processed a payout. Editing either returns a validation error. Archive it and create a new one instead.
- A detail referenced by an active payout schedule cannot be archived. Deactivate or repoint the schedule first.
Fiat payout details
A bank account. SouthPay converts a stablecoin balance to fiat and sends it by transfer.
IBANs are checksum-validated, and the currency must be plausible for the IBAN’s country: a
DE IBAN accepts EUR only, a GB IBAN accepts GBP or EUR, a US account accepts USD. US routing numbers are checksum-validated too. Getting any of this wrong returns 422 with a {"errors": [...]} list.
As with crypto details, core fields freeze once the account has processed a payout, and the currently selected account cannot be archived until you deselect it.
What a fiat payout requires
Three conditions, each with its own failure:- Your store must be KYC verified. Otherwise
403{"error": "Store KYC verification required"}. - The asset must be USDT or USDC. Nothing else is eligible for the fiat off-ramp. Anything else returns
422. - The amount must clear the minimum: 10 USDT (
amount_atomic≥10000000) or 0.1 USDC (amount_atomic≥100000). Below it,422naming the minimum.
POST /api/v2/payouts/quote. It returns estimated_fiat_cents, estimated_fee_cents, exchange_rate, minimum_atomic, meets_minimum and an expires_at. Checking meets_minimum is cheaper than handling the rejection.
The ten fiat currencies above are the ones a bank account can be denominated in, and the same ten you can price a payment intent in. A payout schedule’s
minimum_fiat_currency is narrower: only USD, EUR, GBP, HKD, SGD and JPY. Anything else falls back to USD.Selected destinations
Both kinds carry a “selected” flag: one selected crypto address per network, one selected fiat account per currency. Selecting a new one deselects the previous one for that network or currency. Selection is what the dashboard and automatic payouts use as the default target. It has no effect on an API payout that names an id explicitly. If you passcrypto_payout_detail_id, that is where the money goes, selected or not.

