- Widget (React embed) - Drop in a pre-built component.
- JS SDK - Build your own UI with headless hooks or
@heliofi/withdraw-core. - Raw API - Headless integration, full control over everything (this guide).
Widget & SDK
Use our npm packages to embed the withdrawal widget or build a custom UI. Setup (API keys, withdrawal configs) and the HTTP API flow are covered in this guide.SDK documentation is hosted on npm:
- @heliofi/withdraw-react - drop-in React component and headless hooks
- @heliofi/withdraw-core - framework-agnostic TypeScript SDK
- 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.
1. Setup
Get an API Key
Creating aWithdrawalConfig 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 anid, 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:
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 anid, 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. Always derive the value from the source currency’sdecimals field (returned by Get Withdrawal Currencies):
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 whosetoCurrency 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:
sourceCurrencyIdfrom your withdrawal config.toCurrency.idfrom the selected route, which you’ll use as thetoCurrencyIdwhen preparing the withdrawal.
maxWithdrawableAmount is present (HyperCore), show it as the limit instead of balance. Prepare rejects amounts above it.
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 thesummary 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
Inspectprepared.kind on the prepare (or re-quote) response to determine what the holder must sign:
raw— signprepared.unsignedTx(Solana)userop— sign the ERC-4337 user operation (prepared.userOpand related fields)hypercore_eip3009— signprepared.sendAssetTypedDataandprepared.transferAuthorizationTypedData(HyperCore, see HyperCore withdrawals)hypercore— signprepared.typedData(HyperCore, legacy single-signature route)
6. Submit the Withdrawal
Call the Submit Withdrawal endpoint using thewithdrawalDetailId 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:HyperCore withdrawals
HyperCore uses the same endpoints as other chains. Only the balance limit, the signing step and the status fields are different.Max withdrawable
ShowmaxWithdrawableAmount as the limit, not balance. It excludes open-order holds and a 0.01 USDC buffer.
amount is in HyperCore USDC atomic units (8 decimals). HyperEVM USDC has 6 decimals, so use amounts with at most 6 decimals. The last two digits are truncated.
Sign both messages
Whenprepared.kind is hypercore_eip3009, the prepare response contains two EIP-712 messages:
eth_signTypedData_v4) with the ownerAddress wallet. Then join the signatures: the sendAsset signature first, then the authorization signature without its 0x.
- The two domains use different chain IDs: 42161 (HyperCore signing domain) and 999 (HyperEVM USDC). Some browser wallets won’t sign when the domain chain ID differs from the active network, so the customer may need to switch networks between signatures.
uint256values arrive as decimal strings. Raw JSON-RPC accepts them as they are, but viem expectsbigint, so convert those fields first.- Signatures with
v = 0/1are normalized. A signature that can’t be relayed is rejected with400before any funds move.
{ token, signedTx } before summary.expiresAt (2 minutes after prepare). Sending the same submit again is safe and returns the same result.
Track the withdrawal
Poll Get Withdrawal Detail untilstate leaves SUBMITTED / BRIDGING. When leg 1 lands, txHash is the HyperCore ledger hash.
Re-sign an expired authorization
This is rare. If leg 2 isn’t relayed before its authorization expires,requiresReauthorization becomes true. The USDC stays safe on the customer’s own HyperEVM address. Fetch a fresh authorization, have the customer sign it, and submit the signature. The relay then continues by itself.
