Overview
Private swaps route through multiple CEX hops to provide maximum privacy. Like standard swaps, they use CEX tokens from the /tokens endpoint. Optionally uses Monero (XMR) for enhanced anonymity. This breaks transaction trails across exchanges, providing enhanced anonymity without requiring wallet connections.
Best For : Users who prioritize privacy and are willing to accept longer completion times (15-45 minutes) for enhanced anonymity.
Key Features
Multi-Hop Routing Routes through 2 exchanges to break transaction trail
Optional XMR Privacy Layer Can use Monero for untraceable intermediate transactions
No Wallet Connection No browser wallet or approvals required
Maximum Anonymity No direct on-chain link between source and destination
How It Works
Private swaps follow this multi-hop flow:
Get Supported Assets
Fetch available tokens from /tokens
Request Private Quote
Get a quote with anonymous: true to request private routing
Create Swap Order
Submit swap with destination address
Multi-Hop Routing
Funds route through multiple CEXs (optionally via Monero)
Privacy Delivery
Final output sent to destination with broken trail
Integration Guide
Step 1: Get Supported Assets
Before requesting a quote, fetch the available tokens. Learn more about CEX tokens .
Performance Note : The /tokens endpoint can take several seconds to minute to respond due to the large token list.
Save tokens in your backend database
Load tokens on server startup or via scheduled job
Serve token list from your database to frontend
Refresh cache periodically (e.g., every 24 hours)
const tokens = await fetchFromHoudini ( '/tokens' );
console . log ( 'Available tokens:' , tokens . length );
# Get CEX tokens
curl -X GET "https://api-partner.houdiniswap.com/tokens" \
-H "Authorization: your_api_key:your_api_secret" \
-H "x-user-ip: 192.168.1.1" \
-H "x-user-agent: Mozilla/5.0..." \
-H "x-user-timezone: America/New_York"
Step 2: Request Private Quote
Request a quote with anonymous: true for maximum privacy. Use token symbols from the /tokens endpoint:
// Request a private quote
const quote = await fetchFromHoudini ( '/quote' , {
amount: '1' ,
from: 'ETH' , // Token symbol from /tokens
to: 'SOL' , // Token symbol from /tokens
anonymous: 'true' , // Enable private routing
useXmr: 'false' // System decides XMR usage
});
console . log ( 'Route type:' , quote . type ); // "private"
console . log ( 'Privacy hops:' , quote . path ); // "se:cl" (multi-hop)
console . log ( 'XMR amount:' , quote . xmrAmount ); // Amount routed via Monero
console . log ( 'ETA:' , quote . duration , 'minutes' );
curl -X GET "https://api-partner.houdiniswap.com/quote?amount=1&from=ETH&to=SOL&anonymous=true&useXmr=false" \
-H "Authorization: your_api_key:your_api_secret" \
-H "x-user-ip: 192.168.1.1" \
-H "x-user-agent: Mozilla/5.0..." \
-H "x-user-timezone: America/New_York"
Quote Response
{
"amountOut" : 23.6634 ,
"amountIn" : 1 ,
"type" : "private" ,
"duration" : 11 ,
"path" : "cl:qx" ,
"xmrAmount" : 38.231647970000004 ,
"inQuoteId" : "694cd4b5d924391f000561da" ,
"outQuoteId" : "694cd4b5d924391f000561e3" ,
"quoteId" : "694cd4b5d924391f000561e3" ,
"amountOutUsd" : 2893.323918 ,
"rewardsAvailable" : true
}
Key Private Route Fields:
type: "private" indicating multi-hop routing
path: Multi-hop CEX path (e.g., "cl:qx" = Changelly → Quickex)
xmrAmount: Amount routed through Monero privacy layer
inQuoteId / outQuoteId: Separate quotes for each hop
duration: Estimated time to complete the exchange, longer completion time (15-45 min) due to multi-hop
Step 3: Create Private Swap
Create the swap order using the /exchange endpoint:
// Create a private swap
const swapRequest = {
amount: 1 ,
from: 'ETH' ,
to: 'SOL' ,
addressTo: '1nc1nerator11111111111111111111111111111111' ,
receiverTag: '' ,
anonymous: true , // Enable private routing
ip: '192.168.1.1' ,
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' ,
timezone: 'America/New_York' ,
useXmr: false
};
const response = await fetch ( ` ${ API_BASE_URL } /exchange` , {
method: 'POST' ,
headers: {
'Authorization' : ` ${ API_KEY } : ${ API_SECRET } ` ,
'Content-Type' : 'application/json' ,
'x-user-ip' : swapRequest . ip ,
'x-user-agent' : swapRequest . userAgent ,
'x-user-timezone' : swapRequest . timezone
},
body: JSON . stringify ( swapRequest )
});
const swap = await response . json ();
console . log ( 'Private swap created:' , swap . houdiniId );
console . log ( 'Deposit to:' , swap . senderAddress );
curl -X POST "https://api-partner.houdiniswap.com/exchange" \
-H "Authorization: your_api_key:your_api_secret" \
-H "Content-Type: application/json" \
-H "x-user-ip: 192.168.1.1" \
-H "x-user-agent: Mozilla/5.0..." \
-H "x-user-timezone: America/New_York" \
-d '{
"amount": 1,
"from": "ETH",
"to": "SOL",
"addressTo": "1nc1nerator11111111111111111111111111111111",
"receiverTag": "",
"anonymous": true,
"ip": "192.168.1.1",
"userAgent": "Mozilla/5.0...",
"timezone": "America/New_York",
"useXmr": false
}'
Exchange Response
{
"houdiniId" : "bwc5iKVeeW5GiQpLHCm65w" ,
"created" : "2025-12-25T06:13:21.293Z" ,
"senderAddress" : "0xA2fC2BD472aB6FAF3176EBcBCaeeC7f95F563Ada" ,
"receiverAddress" : "1nc1nerator11111111111111111111111111111111" ,
"anonymous" : true ,
"status" : 0 ,
"inAmount" : 1 ,
"inSymbol" : "ETH" ,
"outAmount" : 23.66258493 ,
"outSymbol" : "SOL" ,
"eta" : 28 ,
"expires" : "2025-12-25T06:43:21.293Z" ,
"quote" : {
"path" : "se:cl" ,
"xmrAmount" : 10393.30176114 ,
"type" : "private"
},
"inStatus" : 0 ,
"outStatus" : 0
}
Critical : Send exactly inAmount of inSymbol to the senderAddress within the expiration time (typically 30 minutes).
Step 4: Monitor Swap Status
Poll the status endpoint to track the multi-hop progress:
// Check swap status
const status = await fetchFromHoudini ( '/status' , {
id: swap . houdiniId
});
console . log ( 'Overall status:' , status . status );
console . log ( 'Input leg:' , status . inStatus ); // First hop status
console . log ( 'Output leg:' , status . outStatus ); // Second hop status
curl -X GET "https://api-partner.houdiniswap.com/status?id=bwc5iKVeeW5GiQpLHCm65w" \
-H "Authorization: your_api_key:your_api_secret" \
-H "x-user-ip: 192.168.1.1" \
-H "x-user-agent: Mozilla/5.0..." \
-H "x-user-timezone: America/New_York"
Private Swap Status Progression
Private swaps have additional status stages for multi-hop routing:
0 (WAITING)
↓ User sends deposit
1 (CONFIRMING)
↓ Deposit confirmed
2 (EXCHANGING)
↓ First CEX hop processing
3 (ANONYMIZING)
↓ Routing through privacy layer (XMR)
↓ Second CEX hop processing
4 (COMPLETED)
Status Fields:
status: Overall swap status (0-8)
inStatus: First hop status
outStatus: Second hop status (private swaps only)
Polling : Check status every 30 seconds or more. Private swaps take 15-45 minutes due to multi-hop routing.
Complete Example
For a complete, runnable Node.js example:
Private Swap Example Complete private swap script with multi-hop status tracking
Best Practices
Clearly communicate the 15-45 minute completion time for private swaps. Users should understand they’re trading speed for privacy.
Explain how multi-hop routing provides privacy benefits. Help users understand what they’re getting.
Implement proper loading states and progress indicators. Private swaps take longer due to multiple hops.
Common Issues
Longer Than Expected Completion
Cause : Multi-hop routing through 2 exchanges takes longerSolution : This is normal for private swaps. Monitor inStatus and outStatus to see which hop is processing.
Question : “How private is this really?”Answer : Private swaps break the transaction trail by routing through multiple exchanges. When XMR routing is used, it adds an untraceable intermediate step. However, this is not absolute anonymity - compliance checks still apply.
Next Steps
DEX Swaps On-chain decentralized swaps
Order Lifecycle Understand swap status progression
Routing Types Learn about private vs standard routing