On-Chain Crypto Withdrawals
How do I withdraw crypto to an external wallet?
Overview
Withdraw crypto from a customer's trading account to an external wallet using a
crypto_transfer quote followed by a crypto transfer. The flow mirrors fiat funding but
uses different parameters and accounts for on-chain network fees.
Prerequisites
- A customer with a verified identity
- A
tradingaccount holding the crypto asset to withdraw - A registered external wallet for the destination address (see Add External Wallets)
Step 1: Create a crypto transfer quote
Create a quote of type crypto_transfer with side set to withdrawal. This example withdraws
0.25 ETH:
{
"product_type": "crypto_transfer",
"customer_guid": "customer_guid",
"asset": "ETH",
"side": "withdrawal",
"deliver_amount": 250000000000000000
}
Base unit precisionThe
deliver_amountis in base currency units. For ETH, the base unit is wei (18 decimals). The above amount represents 0.25 ETH. This precision is required to avoid rounding errors.
deliver_amountvsreceive_amount
deliver_amountfixes what you send; fees come out of what the recipient gets.receive_amountfixes what the recipient gets; you pay fees on top. See Create and execute a trade for the canonical explanation.
For crypto withdrawals, understand the related on-chain gas fees that may accompany the withdrawal. The
POST /api/quotes response includes two fields related to network fees:
{
...,
"network_fee": 2900000000000000,
"network_fee_asset": "ETH"
}The network_fee shown above is also in the base units of the currency. The above amount
represents 0.0029 ETH. Network fees are tracked as a partner liability in the bank's gas
account. To clear the liability, transfer from your fee account to the gas account before
withdrawing fees — see Platform accounts for
the full flow.
Step 2: Execute the transfer
Execute the transfer using POST /api/transfers with the quote GUID from Step 1. Set
transfer_type to "crypto" and provide the destination wallet in external_wallet_guid.
{
"quote_guid": "quote_guid",
"transfer_type": "crypto",
"external_wallet_guid": "external_wallet_guid",
"source_participants": [
{
"type": "customer",
"amount": 250000000000000000,
"guid": "customer_guid"
}
],
"destination_participants": [
{
"type": "customer",
"amount": 250000000000000000,
"guid": "customer_guid"
}
]
}The valid type enum values for source_participants and destination_participants are bank, customer, and
counterparty. Values such as trading, account, external_wallet, or external_wallet_account are not valid
and will result in validation errors.
Key points for crypto withdrawals:
- The
guidin each participant must match the chosentype(e.g., the customer GUID forcustomer). - The
amountfield is required in both participant objects and must match the quote amount in base units. - The
external_wallet_guidis set at the top level alongside the participants array; these are not mutually exclusive.
Step 3: Monitor the transfer
Crypto transfers process faster than fiat transfers, typically completing in a few minutes. Poll
GET /api/transfers/{transfer_guid} to monitor the transfer state until it reaches completed,
or register for webhooks. See
Transfer Process for the full
state lifecycle.
Once completed, verify the on-chain transaction using a blockchain explorer such as etherscan.io for Ethereum-based assets.
Network fee too low
Encountering the error code network_fee_too_low during a crypto transfer indicates that the base network
fee was not met when the transaction was submitted to the blockchain. This may occur due to network
volatility between the submission and the authorization/approval of the transfer. Retrying the
transfer usually resolves this issue.
Ethereum address format requirements
When withdrawing USDC or other assets to an external wallet on the Ethereum network, ensure the destination address meets the following requirements:
- Starts with
0x - Is exactly 42 characters long
- Contains only hexadecimal characters (0-9, a-f, A-F)
Addresses that do not meet these criteria may result in failed transfers. Double-check that you are using an Ethereum-compatible address and not one from a different blockchain.
Minimum receive amounts for crypto transfer withdrawals
For crypto_transfer withdrawal quotes, each asset and network may have a specific minimum
receive_amount enforced by the platform. For example, USDC_NPL on Polygon enforces a minimum
of 1,000,000 base units (1.00 USDC) in production. A quote below the minimum returns a
422 Invalid Quote Amount error. Enforce per-asset minimums in your application before
submitting withdrawal quotes.
Sandbox behavior
For sandbox-specific behavior of crypto withdrawals (mocked on-chain confirmations, devnet addresses, Solana rent handling), see Sandbox Transfers.
Updated 11 days ago
