GuidesRecipesAPI ReferenceChangelog
Guides

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 trading account 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 precision

The deliver_amount is 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_amount vs receive_amount

deliver_amount fixes what you send; fees come out of what the recipient gets. receive_amount fixes 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 guid in each participant must match the chosen type (e.g., the customer GUID for customer).
  • The amount field is required in both participant objects and must match the quote amount in base units.
  • The external_wallet_guid is 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.