Payouts

Two ways money leaves, and they are different products with different keys:

Chain payoutWithdrawal
PaysAny address you name, usually your usersYour own address, verified with us in advance
FromYour payout wallet on that networkYour balance with us
Destination in the requestYesNo, never
SignedYesNo
Scopechain_payouts:writewithdrawals:write
Eventschain_payout.*withdrawal.*

Before either, estimate what it will cost.

Chain payouts

POST /v1/chain-payouts
Authorization: Bearer <your key>
Idempotency-Key: <uuid>
X-Bankcore-Request-Signature: v1,kid=...,ts=...,sig=...
Content-Type: application/json

{
  "amount": {"amount": "500", "currency": "USDT_TRC20"},
  "network": "tron",
  "destination": {"address": "T...", "memo": null},
  "reference": "payout-000123"
}
Field
amountThe amount the destination receives. currency must be one we pay on network, and the amount may not be finer than the asset's decimals
networktron, bsc, ethereum, base, bitcoin or stellar
destination.addressAn address of network
destination.memoStellar only. Absent or null on every other network
referenceYours. 1–120 printable ASCII, no space
tenantOptional. Your tenant slug; a mismatch with the key is 403 tenant_mismatch and nothing is recorded

Unknown fields are refused at every level. The request must be signed.

NetworkCurrencies paid
tronUSDT_TRC20
bscUSDT_BEP20
ethereumUSDT_ERC20, USDC_ERC20
baseUSDC_BASE
bitcoinBTC
stellarXLM

201 means accepted, not sent.

{
  "id": "3f1c2a9e-...",
  "status": "PENDING",
  "review": null,
  "amount": {"amount": "500", "currency": "USDT_TRC20"},
  "network": "tron",
  "destination": {"address": "T...", "memo": null},
  "from_address": "T...",
  "tx_hash": null,
  "failure_reason": null,
  "reference": "payout-000123",
  "unresolved": false,
  "created_at": "2026-09-26T09:02:11Z",
  "settled_at": null
}

Follow it with GET /v1/chain-payouts/{payout_id} or the chain_payout.* events.

status
PENDINGHeld, not yet signed. Waits while the wallet cannot pay, or for review
SUBMITTEDSigned and broadcast. Not a payment yet
SETTLEDA confirmed transaction proven to pay exactly amount to destination from from_address. tx_hash is set
FAILEDNever signed, or failed on chain. The hold is returned
UNKNOWNNot known yet, with unresolved: true. Never a refusal and never a success: do not retry
RECOVERY_REQUIREDIt may have left; we are establishing what happened. Treat it like UNKNOWN

Treat any status you do not recognise as unresolved, never as failed.

review is null, "required" or "released". "required" means the payout waits for a person on our side and polling does not move it; "released" means a person let it through. Branch on the value.

from_address is your payout wallet on that network, the same address GET /v1/whoami returns in payout_wallets. It is set before anything is signed; it does not mean sent.

Two capacities

A payout draws on two things: your balance with us, which the amount is held against, and your position in the payout wallet, which the coins leave from.

RefusalWhose to fix
422 insufficient_balanceYours: your balance does not cover it
503 wallet_shortYours: your position in the payout wallet does not cover it. Top it up (below)
503 network_not_enabledOurs: no payout wallet on that network yet, or payouts are switched off. Ask us
503 temporarily_haltedOurs: everything is stopped while a discrepancy is looked at

The three 503s are retriable in form. Only wallet_short is fixed by you sending money; do not spin on the other two.

Limits and review

Each tenant has its own payout policy: a cap per payout, a rolling 24-hour total, a rolling 24-hour total to addresses not paid before, and thresholds at or above which a payout is accepted and held for review. An address counts as known 24 hours after its first settled payout.

Above a cap the request is refused (amount_above_limit, daily_limit_exceeded with detail.limit) and nothing is held. At or above a review threshold it is accepted with review: "required". GET /v1/chain-payouts/estimate returns your current numbers. Tell us your real volumes and we set them once.

Funding your payout wallet

A transfer into your payout wallet credits your balance by itself and appears in your statement as ON_RAMP, with the transaction in GET /v1/register?kind=ON_RAMP. No event is sent: poll GET /v1/float.

  1. Send us the addresses you will send from, and wait for our confirmation that they are verified. A transfer from an address we have not verified, or one we recorded before verifying it, is not credited and waits for a person.
  2. Read the wallet address from GET /v1/whoami → payout_wallets. An empty map means your wallet does not exist yet: ask us rather than guess.
  3. Send only the currencies we pay on that network. Ask us before sending anything else.

Withdrawals to your verified address

Where the money goes is not a field on the request. It comes from your verified address for that currency, read again at the moment of sending, so the worst a stolen withdrawal key can do is move your money to your own address. You cannot add or change an address through the API; ask us.

GET /v1/destinations

One live address per currency, with verified and, if refused, rejected_reason.

POST /v1/withdrawals
Authorization: Bearer <your key>
Idempotency-Key: topup-2026-10-03

{"amount": {"amount": "100", "currency": "USDT_TRC20"}, "partner_reference": "topup-2026-10-03"}

The amount, fee included, leaves your balance when the withdrawal is created. Follow it with GET /v1/withdrawals/{withdrawal_id} or withdrawal.* events. On a settled withdrawal:

Field
amountWhat you asked for
customer_feeWhat we charged
network_feeWhat the network kept, as reported. null means not reported, not zero
tx_hashThe transaction. null when none was given, or when one batch carried more than one withdrawal

amount − customer_fee − network_fee is what arrives.

Refusal
422 no_verified_destinationNothing verified for that currency. detail.state: none_on_file, not_verified or rejected
422 daily_limit_exceededOver your rolling 24-hour withdrawal limit. detail has limit_usd, spent_usd, remaining_usd

GET /v1/withdrawals/limit answers the same three numbers before you ask.

Proving a payment

POST /v1/payments/proof

Asks whether one transaction paid a given amount to a given destination. Answers PROVEN, NOT_PROVEN or UNREADABLE; only PROVEN is grounds to act. It reads the chain and writes nothing. Scope: withdrawals:read.