Skip to main content
  • Tokens: Use token id values to request quotes via /quotes for all swap types (standard, private, DEX).
  • Networks: Use network data for UI display (logos, names, explorer links) and address validation.

Tokens

Token Identifiers

In API v2, both CEX and DEX tokens are fetched from the same /tokens endpoint. Every token has a single id field (MongoDB ObjectId format) used in all quote requests.
  • CEX Tokens — filter with hasCex=true (used for standard and private swaps)
  • DEX Tokens — filter with hasDex=true (used for on-chain DEX swaps)

Token Fields

FieldTypeDescriptionExample
idstringRequired for /quotes — Unique token identifier"6689b73ec90e45f3b3e51566"
symbolstringToken ticker symbol"ETH"
namestringFull token name"Ethereum"
addressstringToken contract address"0x0000...0000"
chainstringBlockchain network shortName"ethereum"
decimalsnumberToken decimals18
iconstringToken logo URL"https://api.houdiniswap.com/assets/..."
hasDexbooleanAvailable for DEX swapstrue
hasCexbooleanAvailable for CEX swapstrue
enabledbooleanWhether token is available for swapstrue
pricenumberCurrent USD price2937

Trading Limits

"minMax": {
  "cex":     { "min": 0.0253712625, "max": 16.914175 },
  "dex":     { "min": 0.005,        "max": 50 },
  "private": { "min": 0.0845708751, "max": 16.914175 }
}
  • cex: min/max for standard CEX swaps
  • dex: min/max for DEX swaps
  • private: min/max for private/anonymous swaps
Always use the id field (ObjectId format) when passing tokens to /quotes. Passing symbols will not work.

Fetching Tokens

There are two approaches — choose the one that fits your integration: Paginate through all tokens and store in your database. Refresh every 24 hours.
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
}

Token Search (On-Demand)

Search by name or symbol using the term parameter.
async function searchTokens(query, type = 'hasCex') {
  const params = new URLSearchParams({
    term: query,       // e.g. "ethereum" or "ETH"
    [type]: '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
}
Query Parameters:
ParameterDescription
hasCexFilter to CEX-supported tokens
hasDexFilter to DEX-supported tokens
termSearch by name, symbol, or address
chainFilter by chain shortName (e.g. "ethereum")
pagePage number (default: 1)
pageSizeResults per page (max: 100, default: 20)
Example Response:
{
  "tokens": [
    {
      "id": "6689b73ec90e45f3b3e51566",
      "symbol": "ETH",
      "name": "Ethereum",
      "address": "0x0000000000000000000000000000000000000000",
      "chain": "ethereum",
      "decimals": 18,
      "icon": "https://api.houdiniswap.com/assets/tokens/ETH.png",
      "hasCex": true,
      "hasDex": true,
      "enabled": true,
      "price": 2937,
      "minMax": {
        "cex":     { "min": 0.0253712625, "max": 16.914175 },
        "dex":     { "min": 0.005,        "max": 50 },
        "private": { "min": 0.0845708751, "max": 16.914175 }
      }
    }
  ],
  "total": 1,
  "totalPages": 1
}

Using Token IDs in Quotes

Pass the id from the token response as from and to parameters in /quotes:
// ETH token id from /tokens response
const ethId = '6689b73ec90e45f3b3e51566';
// SOL token id from /tokens response
const solId = '6689b73ec90e45f3b3e51577';

const params = new URLSearchParams({
  amount: '1',
  from: ethId,
  to: solId,
  types: 'standard'  // or 'private', 'dex'
});

const response = await fetch(
  `https://api-partner.houdiniswap.com/v2/quotes?${params}`,
  {
    headers: { 'Authorization': `${API_KEY}:${API_SECRET}` }
  }
);

const { quotes } = await response.json();

Networks (Chains)

Chain Identifiers

Houdini exposes supported blockchain networks via the /chains endpoint. Use shortName to filter tokens by chain and for address validation.
FieldTypeDescriptionExample
idstringUnique chain identifier"507f1f77bcf86cd799439011"
namestringFull network name"Ethereum Mainnet"
shortNamestringShort name — use for chain filtering"ethereum"
chainIdnumberEVM chain ID (EVM chains only)1
kindstringNetwork type"evm"
memoNeededbooleanWhether a memo/tag is requiredfalse
explorerUrlstringTransaction explorer URL template"https://etherscan.io/tx/{txHash}"
addressUrlstringAddress explorer URL template"https://etherscan.io/address/{address}"
addressValidationstringRegex for validating wallet addresses"^(0x)[0-9A-Za-z]{40}$"

Fetching Chains

const response = await fetch(
  'https://api-partner.houdiniswap.com/v2/chains',
  {
    headers: { 'Authorization': `${API_KEY}:${API_SECRET}` }
  }
);

const { chains } = await response.json();
const enabledChains = chains.filter(c => c.enabled ?? true);
Query Parameters:
ParameterDescription
hasCexFilter to chains supporting CEX swaps
hasDexFilter to chains supporting DEX swaps
kindFilter by type: "evm", "solana", "bitcoin", etc.
nameSearch by name or shortName
page / pageSizePagination
Example Response:
{
  "chains": [
    {
      "id": "507f1f77bcf86cd799439011",
      "name": "Ethereum Mainnet",
      "shortName": "ethereum",
      "chainId": 1,
      "kind": "evm",
      "memoNeeded": false,
      "explorerUrl": "https://etherscan.io/tx/{txHash}",
      "addressUrl": "https://etherscan.io/address/{address}",
      "addressValidation": "^(0x)[0-9A-Za-z]{40}$",
      "tokenAddressValidation": "^(0x)[0-9A-Za-z]{40}$"
    }
  ],
  "total": 1,
  "totalPages": 1
}

Using Networks

Validate Addresses

Use the addressValidation regex to validate user input before submitting:
function validateAddress(chain, address) {
  const regex = new RegExp(chain.addressValidation);
  if (!regex.test(address)) {
    throw new Error(`Invalid address for ${chain.name}`);
  }
  return true;
}
function getTransactionUrl(chain, txHash) {
  return chain.explorerUrl.replace('{txHash}', txHash);
}

function getAddressUrl(chain, address) {
  return chain.addressUrl.replace('{address}', address);
}

Check Memo Requirements

function checkMemoRequirement(chain) {
  if (chain.memoNeeded) {
    return { required: true, message: `${chain.name} requires a memo/tag` };
  }
  return { required: false };
}

Next Steps