Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.houdiniswap.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Fixed rate swaps lock the exchange rate at the moment you request a quote. The user receives exactly the quoted amountOut regardless of market movement between quote time and swap execution — as long as the exchange is created before the rate lock expires.
Best For: Partners and users who want price certainty and are willing to plan around a short rate-lock window. Ideal for high-value swaps where slippage risk is unacceptable.
Fixed rate is only available for standard (CEX) swaps. It cannot be combined with private/anonymous swaps or DEX swaps. Attempting either will return a 422 error.

Key Features

Guaranteed Output

User receives exactly amountOut as quoted — no slippage, no surprises at settlement

Rate Lock Window

validUntil timestamp gives you a window to create the exchange before the rate expires

Refund on Failure

If the swap fails after the rate is locked, the refundAddress is used for any potential refund — though refund handling depends on the provider

Provider-Bound Rate

The rate is held by a specific CEX provider via rateId — no silent fallback to a different provider or rate

How It Works

1

Get Tokens

Fetch CEX-supported tokens and cache to your DB. Note each token’s id.
2

Get a Fixed Rate Quote

Call GET /quotes with fixed=true. The response includes a quoteId, guaranteed amountOut, and validUntil expiry.
3

Create the Exchange

Call POST /exchanges with the quoteId, addressTo, and a refundAddress. The refundAddress is required for fixed rate orders.
4

Send Deposit

Send exactly inAmount of the input token to the depositAddress returned in the order.
5

Monitor Status

Poll GET /orders/{houdiniId} until statusLabel is FINISHED. If the swap fails, status may become REFUNDED — refund handling depends on the provider.

Integration Guide

Step 1: Get Tokens

Token fetching is the same as for standard swaps — paginate through /v2/tokens?hasCex=true and cache the results. See Standard Swap — Step 1 for the full code example. Use each token’s id field (not symbol) in the /quotes request.

Step 2: Get a Fixed Rate Quote

Add fixed=true to your /quotes request. The API will automatically restrict results to standard (CEX) quotes only — you do not need to pass types=standard separately. Pass refundAddress at quote time so it is validated early. It must be a valid address on the source chain.
const params = new URLSearchParams({
  amount: '1',
  from: '6689b73ec90e45f3b3e51566',       // ETH token id from /tokens
  to:   '6689b73ec90e45f3b3e51558',       // USDC token id from /tokens
  fixed: 'true',                          // request fixed-rate quotes
  refundAddress: '0xYourRefundWallet',    // source-chain wallet for refunds
});

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();

// All returned quotes will be fixed-rate standard quotes
const quote = quotes[0];
console.log('Guaranteed out:', quote.amountOut);
console.log('Rate locked until:', quote.validUntil);
console.log('Quote ID:', quote.quoteId);  // needed for /exchanges

Fixed Rate Quote Response

{
  "quotes": [
    {
      "quoteId": "69af9e02f9c5affabcaccc14",
      "type": "standard",
      "swap": "cc",
      "swapName": "Coincraddle",
      "logoUrl": "https://api.houdiniswap.com/assets/logos/coincraddle.jpg",
      "amountIn": 1,
      "amountOut": 2456.78,
      "amountOutUsd": 2456.78,
      "min": 0.098169,
      "max": 4688.581529,
      "duration": 30,
      "fixed": true,
      "rateId": "abc123providerratelockid",
      "validUntil": "2025-12-25T06:28:00.000Z",
      "rewardsAvailable": true
    }
  ],
  "total": 3
}
Key fixed-rate quote fields:
FieldTypeDescription
quoteIdstringPass to /exchanges to create the order
fixedbooleantrue confirms this is a fixed-rate quote
rateIdstringProvider-internal rate lock identifier — carried automatically via quoteId
validUntilstring (ISO 8601)Hard deadline — create the exchange before this timestamp
amountOutnumberGuaranteed output amount
validUntil is a hard deadline with no grace period. Check Date.now() < new Date(quote.validUntil) before calling /exchanges. If you miss the window, re-fetch a new quote.

Step 3: Create the Exchange

Pass quoteId, addressTo, and refundAddress to POST /exchanges. The refundAddress is required for fixed rate orders — omitting it returns a 422 error.
// Always check the rate is still valid before submitting
if (Date.now() >= new Date(quote.validUntil).getTime()) {
  throw new Error('Rate expired — fetch a new quote');
}

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: '69af9e02f9c5affabcaccc14',       // from /quotes
    addressTo: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
    refundAddress: '0xYourRefundWallet'         // required for fixed rate
  })
});

const order = await response.json();
console.log('Order ID:', order.houdiniId);
console.log('Deposit to:', order.depositAddress);
console.log('Send:', order.inAmount, order.inSymbol);
console.log('Rate locked:', order.fixed, '— guaranteed out:', order.outAmount);

Exchange Response

{
  "houdiniId": "iBQMRX3xvXrFMGQi71ogo9",
  "created": "2025-12-25T06:13:46.673Z",
  "expires": "2025-12-25T06:43:46.673Z",
  "depositAddress": "0x7364a0b6c55004427a4a7c26355ce9c75ef56194",
  "receiverAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  "refundAddress": "0xYourRefundWallet",
  "fixed": true,
  "validUntil": "2025-12-25T06:28:00.000Z",
  "anonymous": false,
  "status": -1,
  "statusLabel": "NEW",
  "inAmount": 1,
  "inSymbol": "ETH",
  "outAmount": 2456.78,
  "outSymbol": "USDC",
  "eta": 3,
  "swapName": "Coincraddle"
}
Key response fields:
FieldTypeDescription
houdiniIdstringUnique order ID — use for status polling
depositAddressstringSend input funds here
inAmount / inSymbolnumber / stringExact amount and token to send
expiresstring (ISO 8601)Deposit deadline (typically 30 minutes)
fixedbooleanConfirms the order is rate-locked
validUntilstring (ISO 8601)Rate lock expiry echoed from the quote
refundAddressstringAddress used for refunds if the swap fails — whether a refund is issued depends on the provider
The rate is bound to a single provider via the rateId embedded in the quoteId. If that provider loses fixed-rate capability between quote and exchange time, you will receive FIXED_RATE_QUOTE_EXPIRED — there is no silent fallback to a different provider or rate.
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 advances automatically once the deposit is detected on-chain.
Send funds before the expires deadline. If funds arrive after the deadline, the fixed rate is no longer guaranteed and the order may not be processed. Please contact our customer support for assistance.

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 processing the swap at locked rate
// FINISHED    — swap complete, guaranteed amount sent
// FAILED      — swap failed
// REFUNDED    — swap failed; refund handling depends on provider

Status Progression

NEW / WAITING
  ↓ Deposit sent and detected
CONFIRMING
  ↓ Blockchain confirmations received
EXCHANGING
  ↓ CEX processes the swap at the locked rate
FINISHED    ← guaranteed amountOut delivered
  (or)
REFUNDED    ← swap failed; refund handling depends on provider
Poll every 30 seconds. Fixed rate swaps follow the same timeline as standard swaps (typically 3–30 minutes). For real-time updates without polling, use the WebSocket API.

Error Codes

CodeHTTPWhen
REFUND_ADDRESS_REQUIRED_FOR_FIXED_RATE422/exchanges called without refundAddress
ANONYMOUS_AND_FIXED_RATE_NOT_SUPPORTED422fixed=true combined with private/anonymous swap mode
DEX_AND_FIXED_RATE_NOT_SUPPORTED422fixed=true combined with a DEX quote type
FIXED_RATE_QUOTE_EXPIRED422validUntil has passed, or the provider lost fixed-rate capability after the quote was issued
ADDRESS_INVALID_FOR_CHAIN422refundAddress fails format validation for the source chain

Best Practices

Build in a buffer — don’t wait until the last second. Check Date.now() < new Date(quote.validUntil) immediately before calling /exchanges. If the window is too short, fetch a fresh quote rather than risk FIXED_RATE_QUOTE_EXPIRED.
The refund wallet is validated against source-chain address format rules (including Solana, XRP, and other non-EVM chains). Pass it at quote time so validation happens early — not when you create the exchange.
Fixed rate is tied to one provider. If that provider disables fixed rate or goes down between your quote and exchange calls, the order fails with FIXED_RATE_QUOTE_EXPIRED. Re-quoting will select a new provider if one is available.
Display amountOut and validUntil prominently in your UI before the user confirms. This sets clear expectations about the guaranteed output and how long they have to act.

Common Issues

Cause: The exchange was created after validUntil, or the provider lost fixed-rate capability between quote and exchange time.Solution: Fetch a new quote. If the error recurs, the provider may have temporarily disabled fixed rate — try again after a short delay or present the user with a floating-rate quote as a fallback.
Cause: refundAddress was not included in the /exchanges request body.Solution: Always include refundAddress when creating a fixed rate exchange. Collect and validate the address before the user submits.
Cause: The swap failed after the rate lock was accepted — for example, the CEX rejected the transaction.Solution: Refund handling depends on the provider. Some providers automatically return funds to refundAddress; others require the user to contact customer support. Inform the user of the failure and direct them to support if a refund is not issued automatically.

Next Steps

Standard Swaps

Fast single-hop CEX swaps without rate lock

Private Swaps

Multi-hop privacy swaps via CEX routing

Order Lifecycle

Understand all order statuses

Error Handling

Handle errors and edge cases