Skip to main content
A withdrawal allows a customer to transfer funds from a supported wallet to a user-selected destination wallet on a supported blockchain. There are 3 ways to integrate withdrawals:
  1. Widget (React embed) - Drop in a pre-built component.
  2. JS SDK - Build your own UI with headless hooks or @heliofi/withdraw-core.
  3. Raw API - Headless integration, full control over everything (this guide).
The headless integration consists of two phases:
  • Setup: Create a withdrawal config to define the source asset and obtain a withdrawalConfigId.
  • Runtime: List available routes, prepare the withdrawal, sign the transaction, submit it, and track its status.
This guide covers the withdrawal flow for supported blockchains.

1. Setup

Get an API Key

Creating a WithdrawalConfig requires API credentials, although the runtime withdrawal flow does not. Follow the instructions here to generate your API key pair. Your API key must include the WITHDRAWS_CREATE permission. Include your credentials on every authenticated request:

Find the Source Currency ID

A withdrawal config is keyed by currency IDs, not currency symbols. To find the correct currency ID, use the Get Withdrawal Currencies endpoint to list currencies eligible for withdrawals. Each currency includes an id, symbol, decimals, blockchain, and features array. A currency can only be used as a withdrawal source if its features array contains WITHDRAWAL_SOURCE. The following example filters the returned currencies to find the withdrawable USDC asset on the specified blockchain:
Use sourceCurrency.id as the currencyIds value when creating a withdrawal config and as the sourceCurrencyId when preparing a withdrawal.

Create the WithdrawalConfig

Create a withdrawal config using the Create Withdrawal Config endpoint: The response includes an id, which you’ll use as the withdrawalConfigId when preparing withdrawals. Create the config once and reuse it for subsequent withdrawals.

2. Amounts

Specify amounts in atomic units as a decimal-free string. For example, 1.5 USDC (6 decimals) is represented as "1500000". The required precision depends on the source asset’s decimals value. There is no maximum withdrawal amount. There is a minimum floor, returned per route as minimumAmountMinimalUnit (source-token atomic units) and minimumAmountUsd. The expected output can be read from destinationAmount / destinationAmountMin in the prepare response. These are firm, fee-adjusted quotes valid until summary.expiresAt.

3. List Routes

Call the List Withdrawal Routes endpoint to retrieve the available withdrawal destinations for your withdrawal config. Select the route whose toCurrency matches the destination currency the user wants to receive. Each route also includes the minimum supported withdrawal amount, which you can use to validate user input before preparing the withdrawal. Keep the following values for the next step:
  • sourceCurrencyId from your withdrawal config.
  • toCurrency.id from the selected route, which you’ll use as the toCurrencyId when preparing the withdrawal.
Optionally, you can call the Get Withdrawal Balances endpoint to retrieve the holder’s on-chain balance and display it in your application.

4. Prepare the Withdrawal

Call the Prepare Withdrawal endpoint with the holder’s wallet address, destination address, amount (in atomic units), and currency IDs. Display the summary object as your confirmation screen. If the user changes the destination, amount, or recipient, or if the quote expires, update the quote using the Update Withdrawal Detail endpoint rather than calling Prepare Withdrawal again.

5. Sign the Transaction

Inspect prepared.kind on the prepare (or re-quote) response to determine what the holder must sign:
  • raw — sign prepared.unsignedTx (Solana)
  • userop — sign the ERC-4337 user operation (prepared.userOp and related fields)
  • hypercore — sign prepared.typedData (Hyperliquid EIP-712)
Use the appropriate wallet or signing library for that chain. Do not modify the prepared payload before signing, including any existing signatures, fee payer, or transaction metadata.

6. Submit the Withdrawal

Call the Submit Withdrawal endpoint using the withdrawalDetailId returned by the Prepare Withdrawal endpoint. Pass the signed payload from the previous step as signedTx when submitting the withdrawal.

7. Poll status

Poll the Get Withdrawal Detail endpoint every few seconds until the withdrawal reaches a terminal state. Handle the following terminal statuses:

Webhooks

Register a webhook via the Create Withdrawal Webhook endpoint to receive withdrawal lifecycle events instead of polling Supported Events:
  • SUBMITTED
  • CONFIRMED
  • FAILED
  • REFUNDED_BY_PROVIDER
Verify webhook signatures using the same process described in Verifying Webhook Signatures in the Webhooks guide.