Overview
Standard swaps route through a single centralized exchange (CEX) for fast execution. In API v2, all swap types — standard, private, and DEX — share the same /quotes and /exchanges endpoints. Pass types=standard to get only standard quotes, or filter the response by type: "standard". Tokens are identified by their ID (not symbol), and orders are created by passing a quoteId.
Best For : Users who prioritize speed and want the fastest completion times (typically 3-30 minutes) with straightforward single-hop routing.
Need to guarantee the output amount? Add fixed=true and a refundAddress to your quote request to lock the rate. See the Fixed Rate Swap Guide for the full flow.
How It Works
Get Tokens
Bulk fetch CEX-supported tokens and cache to your DB, or search by name/symbol. Note each token’s id.
Get Quotes
Call GET /quotes with token IDs. The response returns quotes from all available providers — select the one with type: "standard".
Create Order
Call POST /exchanges with the selected quoteId and the user’s destination address.
Send Deposit
Send exactly inAmount of the input token to the depositAddress returned in the order.
Monitor Status
Poll GET /orders/{houdiniId} until statusLabel is FINISHED.
Integration Guide
Step 1: Get Tokens
There are two approaches for getting tokens. Choose the one that fits your integration:
Bulk Fetch + Cache
Token Search
Fetch all CEX-supported tokens once and store them in your backend database. This is the best approach for production integrations — it keeps your UI fast and avoids hammering the API. Cache the token list in your backend database. Load on server startup or via a scheduled job, and refresh periodically (e.g., every 24 hours). Never call /tokens on every user request.
// Paginate through all CEX tokens and store in your DB
async function fetchAllCexTokens () {
let page = 1 ;
let allTokens = [];
while ( true ) {
const response = await fetch (
`https://api-partner.houdiniswap.com/v2/tokens?hasCex=true&pageSize=20&page= ${ page } ` ,
{
headers: { 'Authorization' : ` ${ API_KEY } : ${ API_SECRET } ` }
}
);
const { tokens , totalPages } = await response . json ();
allTokens = allTokens . concat ( tokens );
if ( page >= totalPages ) break ;
page ++ ;
}
return allTokens ; // save to your DB
}
curl -X GET "https://api-partner.houdiniswap.com/v2/tokens?hasCex=true&pageSize=20&page=1" \
-H "Authorization: your_api_key:your_api_secret"
Search for specific tokens by name or symbol on demand. Useful for lightweight integrations or when you want to let users search without prefetching everything. // Search tokens as user types
async function searchTokens ( query ) {
const params = new URLSearchParams ({
term: query , // e.g. "bitcoin" or "ETH"
hasCex: 'true' ,
pageSize: '20' ,
page: '1'
});
const response = await fetch (
`https://api-partner.houdiniswap.com/v2/tokens? ${ params } ` ,
{
headers: { 'Authorization' : ` ${ API_KEY } : ${ API_SECRET } ` }
}
);
const { tokens } = await response . json ();
return tokens ; // use token `id` in /quotes requests
}
curl -X GET "https://api-partner.houdiniswap.com/v2/tokens?term=bitcoin&hasCex=true&pageSize=20&page=1" \
-H "Authorization: your_api_key:your_api_secret"
Step 2: Get Quotes
Call GET /quotes using token IDs (not symbols). The response includes quotes from all available providers across all swap types.
const params = new URLSearchParams ({
amount: '1' ,
from: '6689b73ec90e45f3b3e51566' , // ETH token id from /tokens
to: '6689b73ec90e45f3b3e51558' , // USDC token id from /tokens
types: 'standard' , // only return standard quotes
});
const response = await fetch (
`https://api-partner.houdiniswap.com/v2/quotes? ${ params } ` ,
{
headers: {
'Authorization' : ` ${ API_KEY } : ${ API_SECRET } ` ,
'x-user-ip' : userIp ,
'x-user-agent' : userAgent ,
'x-user-timezone' : userTimezone
}
}
);
const { quotes } = await response . json ();
// Pick a standard (single-hop CEX) quote
const standardQuote = quotes . find ( q => q . type === 'standard' );
console . log ( 'Provider:' , standardQuote . swapName );
console . log ( 'Amount out:' , standardQuote . amountOut );
console . log ( 'ETA:' , standardQuote . duration , 'minutes' );
console . log ( 'Quote ID:' , standardQuote . quoteId ); // needed for next step
curl -X GET "https://api-partner.houdiniswap.com/v2/quotes?amount=1&from=6689b73ec90e45f3b3e51566&to=6689b73ec90e45f3b3e51558&types=standard" \
-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"
Quotes Response
{
"quotes" : [
{
"quoteId" : "69af9e02f9c5affabcaccc14" ,
"type" : "standard" ,
"swap" : "cc" ,
"swapName" : "Coincraddle" ,
"logoUrl" : "https://api.houdiniswap.com/assets/logos/coincraddle.jpg" ,
"amountIn" : 1 ,
"amountOut" : 23.56 ,
"amountOutUsd" : 2019.09 ,
"min" : 0.098169 ,
"max" : 4688.581529 ,
"duration" : 30 ,
"rewardsAvailable" : true
}
],
"total" : 5
}
Key Fields:
quoteId: Pass this to /exchanges to create the order
type: "standard" for single-hop CEX routing
swap / swapName: CEX provider code and human-readable name
amountOut: Output amount
duration: Estimated completion time in minutes
min / max: Valid input amount range
Step 3: Create Order
Pass the quoteId and destination address to POST /exchanges:
const response = await fetch ( 'https://api-partner.houdiniswap.com/v2/exchanges' , {
method: 'POST' ,
headers: {
'Authorization' : ` ${ API_KEY } : ${ API_SECRET } ` ,
'Content-Type' : 'application/json' ,
'x-user-ip' : userIp ,
'x-user-agent' : userAgent ,
'x-user-timezone' : userTimezone
},
body: JSON . stringify ({
quoteId: '694cd4ef6ca7023b5e00a288' , // from /quotes
addressTo: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'
})
});
const order = await response . json ();
console . log ( 'Order ID:' , order . houdiniId );
console . log ( 'Deposit to:' , order . depositAddress );
console . log ( 'Send amount:' , order . inAmount , order . inSymbol );
console . log ( 'Expires:' , order . expires );
curl -X POST "https://api-partner.houdiniswap.com/v2/exchanges" \
-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 '{
"quoteId": "694cd4ef6ca7023b5e00a288",
"addressTo": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
}'
Order Response
{
"houdiniId" : "iBQMRX3xvXrFMGQi71ogo9" ,
"created" : "2025-12-25T06:13:46.673Z" ,
"expires" : "2025-12-25T06:43:46.673Z" ,
"depositAddress" : "0x7364a0b6c55004427a4a7c26355ce9c75ef56194" ,
"receiverAddress" : "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" ,
"anonymous" : false ,
"status" : -1 ,
"statusLabel" : "NEW" ,
"inAmount" : 1 ,
"inSymbol" : "ETH" ,
"inStatus" : 0 ,
"inStatusLabel" : "NEW" ,
"outAmount" : 2456.78 ,
"outSymbol" : "USDC" ,
"outStatus" : 0 ,
"outStatusLabel" : "NEW" ,
"eta" : 3 ,
"inAmountUsd" : 2937 ,
"swapName" : "Changelly" ,
"inToken" : {
"id" : "6689b73ec90e45f3b3e51566" ,
"symbol" : "ETH" ,
"name" : "Ethereum" ,
"decimals" : 18 ,
"chain" : "ethereum"
},
"outToken" : {
"id" : "6689b73ec90e45f3b3e51558" ,
"symbol" : "USDC" ,
"name" : "USD Coin" ,
"decimals" : 6 ,
"chain" : "ethereum"
}
}
Key Response Fields:
houdiniId: Unique order identifier — use for status polling
depositAddress: Send input funds here
inAmount / inSymbol: Exact amount and token to send
expires: Deposit deadline (typically 30 minutes)
statusLabel: Human-readable order status
eta: Estimated completion time in minutes
Send exactly inAmount of inSymbol to depositAddress before expires.
Step 4: Send Deposit
After creating the order, send the input tokens to depositAddress. The status will advance automatically once the deposit is detected on-chain.
Step 5: Monitor Order Status
Poll GET /orders/{houdiniId} to track progress, or subscribe via the WebSocket API for real-time updates:
const response = await fetch (
`https://api-partner.houdiniswap.com/v2/orders/ ${ order . houdiniId } ` ,
{
headers: {
'Authorization' : ` ${ API_KEY } : ${ API_SECRET } ` ,
'x-user-ip' : userIp ,
'x-user-agent' : userAgent ,
'x-user-timezone' : userTimezone
}
}
);
const status = await response . json ();
console . log ( 'Status:' , status . statusLabel );
// WAITING — awaiting deposit
// CONFIRMING — deposit detected, awaiting confirmations
// EXCHANGING — CEX is processing the swap
// FINISHED — swap complete, funds sent
// FAILED — swap failed
// EXPIRED — deposit not received in time
// REFUNDED — funds returned to sender
curl -X GET "https://api-partner.houdiniswap.com/v2/orders/iBQMRX3xvXrFMGQi71ogo9" \
-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"
Status Progression
NEW / WAITING
↓ Deposit sent and detected
CONFIRMING
↓ Blockchain confirmations received
EXCHANGING
↓ CEX processes the swap
FINISHED
Poll every 30 seconds. Standard swaps typically complete in 3–30 minutes. For real-time updates without polling, use the WebSocket API .
Best Practices
Bulk fetch + cache : Paginate through /v2/tokens?hasCex=true on server startup and store in your DB. Refresh every 24 hours.
Search : Use ?term=<query> for on-demand token lookup — good for lightweight integrations.
Never call /tokens on every user request in production.
Poll /orders/{houdiniId} every 30 seconds
Store houdiniId for future reference and support lookups
Handle all statusLabel values: FINISHED, FAILED, EXPIRED, REFUNDED
Re-fetch quotes if quote is expired before calling /exchanges
Validate addressTo format before submitting
Implement retry logic with backoff for API calls
Never expose API keys in frontend code
Use backend-only API integration
Validate all addresses before submitting
Store order records for audit trail
Common Issues
Swap Taking Longer Than Expected
Causes : Network congestion, CEX processing delays, slow block confirmations.Solution : Continue monitoring. Most swaps complete within 2× the estimated time.
Issue : User sent an incorrect amount to the deposit address.Solution : A partial refund may be processed. Contact support with the houdiniId.
Cause : Deposit was not received before the expires timestamp.Solution : Fetch a new quote and create a new order.
Status Stuck at CONFIRMING
Solution : Wait for blockchain confirmations. Check the deposit transaction on a block explorer and verify the correct amount was sent.
Example Repositories
See full working integrations on GitHub:
Next.js Example Full Next.js integration showing standard, private, and DEX swap flows
Node.js Example Backend Node.js integration with token fetching, quoting, and order tracking
Next Steps
Private Swaps Multi-hop privacy swaps
DEX Swaps On-chain decentralized swaps
Order Lifecycle Understand all order statuses
Error Handling Handle errors and edge cases