Skip to main content

Overview

Split lets partners create many independent swap orders in one API call. The orders share one multiId. Each order is priced and executed on its own, and you track them all with one status call. You can fund the orders one by one, or fund the whole group at once with a batch transaction on Solana or EVM.
Split was previously called Multi-Swap. The API keeps the original names: endpoints live under /exchanges/multi and orders are grouped by multiId.
Best For: Platforms paying out to many recipients, batch airdrop tools, or any use case that needs several swaps from the same source token at once.
Split supports standard (CEX) and private routing only — DEX orders are not supported. You post each order with from/to/amount/addressTo. No quoteId is needed.
Fixed rate works per order: set fixed: true and include a refundAddress. Reverse quotes work too: add amountType: "receive" to a fixed order to pay the receiver an exact amount. See Fixed Rate & Reverse Quote.

Key Features

Up to 50 Orders per Call

Create up to 50 orders in one request, all linked by a shared multiId

Standard & Private Routing

Choose standard (CEX) or private routing per order

One Status Call

Track every order in the group with GET /exchanges/multi/{multiId}

Batch Funding on Solana and EVM

Pay every deposit address with one signed transaction on Solana, Ethereum, Base or BNB Smart Chain

How It Works

1

Get Tokens

Fetch tokens with hasCex=true. Add hasBundler=true if you want to fund the group with a batch transaction.
2

Create a Split

Call POST /exchanges/multi with an array of orders. To show rates first, call Get split quotes — it is optional.
3

Wait for Deposit Addresses

Orders are prepared in the background. Poll GET /exchanges/multi/{multiId} until every order has a depositAddress.
4

Fund the Orders

Fund all orders with one batch transaction (Solana or EVM), or send to each deposit address yourself.
5

Monitor Status

Keep polling GET /exchanges/multi/{multiId} until every order is finished.

Choose How to Fund

Integration Guide

Step 1: Get Tokens

Use token IDs (not symbols) when building your orders. Fetch and cache the token list from /tokens with hasCex=true. To fund the group with a batch transaction, also pass hasBundler=true — it returns only tokens the bundler can pay with.
Cache the token list in your backend database. Never call /tokens on every user request — load on server startup or via a scheduled job and refresh every 24 hours.

Step 2: Create a Split

Call POST /exchanges/multi with an orders array (1 to 50 orders). Each order is independent — different token pairs, amounts, and destination addresses can share one batch. Set anonymous: true on any order to use private routing for that order.
Planning to fund with a batch transaction? Every order must send the same source token on the same chain.

Create Split Response

Key Response Fields:
  • multiId: Shared identifier for the group — use it for status and batch funding
  • orders[]: One entry per order you sent, in the same order
  • orders[].order: The created order (see Order Lifecycle)
  • orders[].error: Why this order was not created. The rest of the group is unaffected
  • statusLabel: Starts as NEW. The order is prepared in the background
Orders usually come back without a depositAddress. They are prepared in the background. Poll the Split status (Step 3) until every order has its depositAddress before you send funds.
If every order fails, the call returns an error instead of a 200, and nothing is created.

Order Fields Reference

You can also send these at the top level of the request, next to orders:

Step 3: Wait for Deposit Addresses

Poll GET /exchanges/multi/{multiId} to get every order in the group at once. Before funding, wait until every order has a depositAddress. An order that failed during setup shows FAILED, never gets one, and is left out of the batch.

Split Status Response

Key Fields:
  • orders[].depositAddress: Where this order’s funds go. Missing until the order is ready
  • orders[].inAmount: The exact amount to send to this order. For fixed and reverse orders, read the final inAmount and outAmount here once the order has a depositAddress
  • orders[].expires: Fund the order before this time
  • bundleStatus, txHash, failureReason: EVM batch only — see “Track the batch” under Step 4
Orders older than 48 hours come back as a short entry with only houdiniId and status: 8 (deleted).

Step 4: Fund the Orders

Pick one way to fund the group. Each order needs exactly its inAmount of the source token at its depositAddress.

Get the transactions

Call GET /exchanges/multi/{multiId}/tx with the wallet that will pay. The response has unsigned transactions that pay every deposit address. Sign them and broadcast them yourself. There is nothing to submit back to Houdini.One transaction pays up to:A larger group comes back as several entries in transactions. Sign and broadcast every one. Most wallets can sign them all with one approval (signAllTransactions).
Signing on a server with a keypair instead of a wallet? Call tx.sign(keypair) on each transaction, then send it the same way. For v0, decode with VersionedTransaction.deserialize(...) instead.

Solana Batch Response

  • chain: Always "sol" on this endpoint
  • txVersion: The format you got back
  • transactions[].houdiniIds: The orders this transaction pays
  • transactions[].txData.data: The unsigned transaction, base64 encoded
Each transaction carries a recent blockhash, so it is only valid for about a minute. Sign and broadcast it right away. If it expires, call the endpoint again — but pass houdiniIds for the unfunded orders only, so you never pay an order twice.
Only orders still waiting for a deposit are included. The call is rejected while any order is still initializing — wait for Step 3, then try again.

Step 5: Monitor Split Status

Keep polling GET /exchanges/multi/{multiId}. Orders in the same group move at different speeds, so track each one’s statusLabel on its own.
JavaScript
Poll every 30 seconds. For a full list of statuses and transitions, see the Order Lifecycle guide.

Best Practices

POST /exchanges/multi can succeed for some orders and fail for others. Check each item in orders[] for an error field. Handle failed orders on their own — the rest of the group still runs.
Orders get their depositAddress in the background. Both batch endpoints refuse to build while any order is still initializing. Wait until every order shows WAITING with a depositAddress.
An order stays WAITING until its deposit is detected, so a second batch call can include orders you just paid. On Solana, pass houdiniIds for the unfunded orders only. On EVM, a batch can only be submitted once — after submit, track bundleStatus instead of building again.
The wallet you pass as sender owns the smart account and must sign. While a build is live (10 minutes), building with a different wallet is rejected. Check saCurrentBalance before asking the user to fund — a previous batch may have left funds there.
Never expose API keys in frontend code. Validate all addressTo values before submission. Store multiId and each houdiniId for audit trails and support lookups.

Common Issues

Cause: Individual orders can fail (unsupported pair, amount out of range, invalid address) while the rest of the group succeeds.Solution: Check each orders[].error. Create the failed orders again in a new Split with corrected values.
Cause: Some orders do not have a deposit address yet.Solution: Poll GET /exchanges/multi/{multiId} every 5–10 seconds until every order has a depositAddress, then build again.
Cause: A batch needs every order to send the same token on one supported chain (Solana, Ethereum, Base or BNB Smart Chain), and the token must support the bundler.Solution: Pick tokens with hasBundler=true, or fund the orders manually.
Cause: The hash was signed as text instead of raw bytes, or by a different wallet than sender.Solution: Sign with message: { raw: userOpHash } (viem) or getBytes(userOpHash) (ethers), from the sender wallet.
Cause: The signed userOpHash came from the build made before funding. For ERC-20 sources that hash cannot be submitted.Solution: Call Retry failed orders within 30 minutes, then sign and submit the new hash. Next time, build again after the funding transaction confirms.
Cause: The balance can take a few seconds to show. Or the network fee went up since the build.Solution: Build again after a few seconds. If it stays above "0", send only the new depositNeeded (native) or tokenAmount (ERC-20).
Cause: The deposit window passed before funds were sent.Solution: Create the expired orders again in a new Split, and fund them right after their deposit addresses are ready. If an EVM batch had already funded the smart account, use Recover stuck assets to get the funds back.
Cause: Private routing adds an ANONYMIZING step.Solution: This is expected. Track statusLabel per order — private orders usually finish in 15–45 minutes.

Next Steps

Standard Swap

Single-order CEX swaps

Private Swap

Multi-hop private swaps

Order Lifecycle

Understand all order statuses

Error Handling

Handle errors and edge cases