> ## 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.

# Standard Swap Flow

> Integrate standard CEX swaps using the unified v2 quotes and exchanges API

## 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`.

<Info>
  **Best For**: Users who prioritize speed and want the fastest completion times (typically 3-30 minutes) with straightforward single-hop routing.
</Info>

<Note>
  Looking for the v1 standard swap guide? See [API v1 — Standard Swap](/api-v1/swap-flows/standard-swap).
</Note>

<Note>
  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](/developer-hub/swap-flows/fixed-rate-swap) for the full flow.
</Note>

## How It Works

<Steps>
  <Step title="Get Tokens">
    Bulk fetch CEX-supported tokens and cache to your DB, or search by name/symbol. Note each token's `id`.
  </Step>

  <Step title="Get Quotes">
    Call `GET /quotes` with token IDs. The response returns quotes from all available providers — select the one with `type: "standard"`.
  </Step>

  <Step title="Create Order">
    Call `POST /exchanges` with the selected `quoteId` and the user's destination address.
  </Step>

  <Step title="Send Deposit">
    Send exactly `inAmount` of the input token to the `depositAddress` returned in the order.
  </Step>

  <Step title="Monitor Status">
    Poll `GET /orders/{houdiniId}` until `statusLabel` is `FINISHED`.
  </Step>
</Steps>

## Integration Guide

### Step 1: Get Tokens

There are two approaches for getting tokens. Choose the one that fits your integration:

<Tabs>
  <Tab title="Bulk Fetch + Cache">
    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.

    <Warning>
      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.
    </Warning>

    <CodeGroup>
      ```javascript JavaScript theme={null}
      // 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
      }
      ```

      ```bash cURL theme={null}
      curl -X GET "https://api-partner.houdiniswap.com/v2/tokens?hasCex=true&pageSize=20&page=1" \
        -H "Authorization: your_api_key:your_api_secret"
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Token Search">
    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.

    <CodeGroup>
      ```javascript JavaScript theme={null}
      // 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
      }
      ```

      ```bash cURL theme={null}
      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"
      ```
    </CodeGroup>
  </Tab>
</Tabs>

### Step 2: Get Quotes

Call `GET /quotes` using token IDs (not symbols). The response includes quotes from all available providers across all swap types.

<CodeGroup>
  ```javascript JavaScript theme={null}
  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
  ```

  ```bash cURL theme={null}
  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"
  ```
</CodeGroup>

### Quotes Response

```json theme={null}
{
  "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`:

<CodeGroup>
  ```javascript JavaScript theme={null}
  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);
  ```

  ```bash cURL theme={null}
  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"
    }'
  ```
</CodeGroup>

### Order Response

```json theme={null}
{
  "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

<Warning>
  Send exactly `inAmount` of `inSymbol` to `depositAddress` before `expires`.
</Warning>

### 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](/developer-hub/core-concepts/websocket-order-updates) for real-time updates:

<CodeGroup>
  ```javascript JavaScript theme={null}
  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
  ```

  ```bash cURL theme={null}
  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"
  ```
</CodeGroup>

### Status Progression

```
NEW / WAITING
  ↓ Deposit sent and detected
CONFIRMING
  ↓ Blockchain confirmations received
EXCHANGING
  ↓ CEX processes the swap
FINISHED
```

<Tip>
  Poll every 30 seconds. Standard swaps typically complete in 3–30 minutes. For real-time updates without polling, use the [WebSocket API](/developer-hub/core-concepts/websocket-order-updates).
</Tip>

## Best Practices

<AccordionGroup>
  <Accordion title="Token Fetching" icon="database">
    * **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.
  </Accordion>

  <Accordion title="Transaction Monitoring" icon="chart-line">
    * Poll `/orders/{houdiniId}` every 30 seconds
    * Store `houdiniId` for future reference and support lookups
    * Handle all `statusLabel` values: FINISHED, FAILED, EXPIRED, REFUNDED
  </Accordion>

  <Accordion title="Error Handling" icon="triangle-exclamation">
    * Re-fetch quotes if quote is expired before calling `/exchanges`
    * Validate `addressTo` format before submitting
    * Implement retry logic with backoff for API calls
  </Accordion>

  <Accordion title="Security" icon="shield">
    * Never expose API keys in frontend code
    * Use backend-only API integration
    * Validate all addresses before submitting
    * Store order records for audit trail
  </Accordion>
</AccordionGroup>

## Common Issues

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="Wrong Amount Deposited">
    **Issue**: User sent an incorrect amount to the deposit address.

    **Solution**: A partial refund may be processed. Contact support with the `houdiniId`.
  </Accordion>

  <Accordion title="Order Expired">
    **Cause**: Deposit was not received before the `expires` timestamp.

    **Solution**: Fetch a new quote and create a new order.
  </Accordion>

  <Accordion title="Status Stuck at CONFIRMING">
    **Solution**: Wait for blockchain confirmations. Check the deposit transaction on a block explorer and verify the correct amount was sent.
  </Accordion>
</AccordionGroup>

## Example Repositories

See full working integrations on GitHub:

<CardGroup cols={2}>
  <Card title="Next.js Example" icon="react" href="https://github.com/HoudiniSwap/houdini-api-examples/tree/main/nextjs-example">
    Full Next.js integration showing standard, private, and DEX swap flows
  </Card>

  <Card title="Node.js Example" icon="node-js" href="https://github.com/HoudiniSwap/houdini-api-examples/tree/main/node-examples">
    Backend Node.js integration with token fetching, quoting, and order tracking
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Private Swaps" icon="lock" href="/developer-hub/swap-flows/private-swap">
    Multi-hop privacy swaps
  </Card>

  <Card title="DEX Swaps" icon="arrows-rotate" href="/developer-hub/swap-flows/dex-swap">
    On-chain decentralized swaps
  </Card>

  <Card title="Order Lifecycle" icon="rotate" href="/developer-hub/core-concepts/order-lifecycle">
    Understand all order statuses
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/developer-hub/troubleshooting/errors">
    Handle errors and edge cases
  </Card>
</CardGroup>
