Skip to main content
A withdrawal moves funds out of your Breet wallet. The Partners API supports two types:
  • Crypto withdrawals to an external wallet address — POST /payments/withdraw/address. Stablecoins (USDT, USDC) on Ethereum, Tron, BSC, Solana, TON, and Base, plus the UTXOs BTC, LTC, DOGE, and BCH. Debited from your USD balance.
  • Bank withdrawals to an NGN or GHS bank account — POST /payments/withdraw/bank/{id}. Debited from your local-currency balance.
Both types share the same lifecycle and webhook events. This page focuses on crypto withdrawals; bank withdrawals differ in destination and currency. The fee bearer setting applies to both. For automatic bank payouts tied to deposits, see Auto-settlement.

Withdrawal states

Each state change fires a webhook: withdrawal.pending, withdrawal.processing, withdrawal.completed, withdrawal.reversed, or withdrawal.rejected.
Rejected ≠ reversed. Both refund your balance, but rejected means Breet blocked the withdrawal before it touched the blockchain; reversed means the transaction came back with a failure after an attempt to broadcast it. Only withdrawal.completed means the funds are on-chain at the destination.

Withdrawal assets (mainnet)

Stablecoins — pick a network: UTXOs — single-chain, no network: BTC, LTC, DOGE, BCH. See UTXO withdrawals. Call GET /payments/supported-assets-info for what is currently enabled on your integration — a token missing from that response cannot be withdrawn. For testnet IDs and the full deposit/withdrawal asset catalog, see Supported assets.

Validating an address

POST /payments/wallet-addresses/validate checks an address against a token and network before you submit a withdrawal.
A valid address returns 200:
An invalid one returns 422.
This is a check on the address format only — that it is well-formed for that token and network. It does not confirm the address exists, is reachable, or is permitted. A withdrawal to an address that passes here can still be rejected. See Common failures.

Before you can withdraw

Happy path

1

You submit the request

Call POST /payments/withdraw/address:
Breet responds synchronously with the withdrawal id.
2

Breet validates and debits

Synchronous checks, in order:
  1. Credentials and integration active.
  2. IP in allowlist (if configured).
  3. PIN is correct. After enough wrong attempts the account is frozen, and you must reset the PIN to unfreeze it.
  4. amount within min/max.
  5. Address is valid for the network and not a Breet-managed address.
  6. Not a duplicate. The same amount to the same address within 1 minute is rejected. See Duplicate withdrawals.
  7. Sufficient balance — amount, or amount + fee if your fee bearer is business.
All pass → the amount is debited, withdrawal is created with status: pending, withdrawal.pending webhook is queued.Any fail → no record, no debit, no webhook. You receive an HTTP error. See Error handling.
3

Breet approves and broadcasts

Approval is mostly automatic. The withdrawal moves to processing, then the transaction is signed and broadcast on the chosen network. By default the recipient receives amount − fee on-chain (see Fees).Withdrawals flagged for internal review may stay in pending until Breet approves (typically within a few minutes).
4

Breet confirms completion

Once the withdrawal is successful, withdrawal.completed fires with the on-chain txHash.

Webhook sequence, by scenario

Webhook delivery is asynchronous and ordering isn’t guaranteed under variable endpoint latency. Trust the event and status fields on each payload, not the order they arrive in.

UTXO withdrawals

BTC, LTC, DOGE, and BCH use the same endpoint as stablecoins, with three differences. No network. Each UTXO runs on exactly one chain. Sending network alongside a UTXO is rejected with {token} does not support a network. feeLevel is required. low, medium, or high — it decides how much network fee is paid, and so how quickly the transaction confirms. Stablecoins ignore it. The network fee is dynamic. Stablecoins carry a flat fee per network; UTXOs are quoted per request against live network conditions. Estimate it first.

Pricing in USD or in crypto units

Send either amount (USD, up to 2 dp) or cryptoAmount (crypto units, up to 8 dp) — exactly one. Breet converts with the market rate at the time of the request and records it on the withdrawal as meta.cryptoAmountRate. Your USD balance is debited either way, and your integration’s min/max still applies to the USD value. A cryptoAmount outside the range is rejected with both bounds shown in crypto units and USD.

Estimating the network fee

Call POST /payments/estimate-network-fee with the UTXO token, the amount, and the destination:
You get back all three levels, in crypto units and USD:
Estimates are cached for 60 seconds and the endpoint is limited to 5 requests per minute.
An estimate is not a locked quote. The fee is re-estimated when the withdrawal is submitted, so the fee recorded on the withdrawal can differ from what you were quoted.

What the recipient gets

By default the fee is deducted from the amount you requested, the same as for stablecoins. withdrawalFeeBearer changes that. The withdrawal records both sides of the conversion: If the fee would consume the whole withdrawal, the request is rejected with the {token} network fee of $X leaves no payout for a $Y withdrawal — nothing is debited.

Fees and minimums

Stablecoin withdrawals carry a small flat fee per network, readable from GET /payments/supported-assets-info. UTXO withdrawals carry a dynamic network fee instead. Either way the fee is reported on the withdrawal and its webhooks as fee. By default the fee is deducted from the amount you request. Your balance is debited the full amount, and the recipient receives amount − fee on-chain. You can flip this with withdrawalFeeBearer. Example. You call with amount: 100, USDT on Tron, fee $1. Your balance is debited $100. The recipient receives $99 of USDT on Tron.

Who bears the fee

Every withdrawal carries a fee. The withdrawalFeeBearer setting on your integration decides who absorbs it — you or your end-user. It applies to all withdrawals: bank, stablecoin, and UTXO. You control this yourself. Open the Developer page in your partner dashboard, go to the Business tab, and set Withdrawal fee bearer to one of:
  • User — your end-user pays. The fee comes out of the payout, so the recipient gets less than you requested. This is the default.
  • Business — you pay. The fee is added to what we debit from your balance, so the recipient gets the full amount.
You can also change it with PUT /users/withdrawal-fee-bearer. Bank withdrawals carry a flat fee per payout, set per destination currency. Read the fee that currently applies to your integration from GET /users/fetch-integration as withdrawalFee:
Crypto withdrawals carry the network fee instead — flat per network for stablecoins, dynamic for UTXOs. The bearer setting works the same way on both. Example. A ₦50,000 payout with a ₦50 fee:
  • user — your balance is debited ₦50,000, the destination account is credited ₦49,950.
  • business — your balance is debited ₦50,050, the destination account is credited ₦50,000.
Breet charges the fee exactly once either way. The setting only decides who absorbs it, never how much it is. Crypto example. You call with amount: 100, USDT on Tron, fee $1:
  • user — your balance is debited $100, the recipient receives $99 of USDT.
  • business — your balance is debited $101, the recipient receives $100 of USDT.
Auto-settlement payouts follow this setting too.

Changing it

A new value applies only to withdrawals created after you save it. A withdrawal already in pending keeps the pricing it was created with. To check what is live now, read withdrawalFeeBearer from GET /users/fetch-integration. Every withdrawal also records the bearer that applied to it as meta.feeBearer, so you can reconcile a payout against the setting that was live when it was created.

Duplicate withdrawals

Breet rejects a repeat of the same USD amount to the same destination address within 1 minute:

Common failures

See Error handling for the full response shape.

Fetching withdrawals via the API

On every webhook, fetch the withdrawal by id before updating your system of record. Combined with IP and secret verification, this is defence in depth.

FAQ

BTC, LTC, DOGE, and BCH are supported — see UTXO withdrawals. Other native coins, including ETH and SOL, are not. To move those, sell them via a deposit first, then withdraw as a stablecoin.
Not via API. Contact support immediately after submitting if it’s critical. Once approved and broadcast, the withdrawal can only complete or reverse.
On-chain transactions are irreversible. Breet validates address format, not ownership. Always confirm the destination with your end-user before submitting.
Seconds/Minutes on Solana, Tron, and TON. Longer on EVM chains due to confirmation times. For UTXOs, the feeLevel you pick decides it — high confirms soonest, low can take much longer when the network is busy.
It’s an additional verification layer in case your API keys leak. Store the PIN alongside your secrets and rotate it from the dashboard if exposed.

Next steps