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

# Payout Wallet Rotation

> Improve swap privacy by rotating provider routing paths across consecutive orders

# Payout Wallet Rotation

Rotate swap routing paths across consecutive orders so that repeated swaps from the same user don't always flow through the same provider wallet.

## Overview

When a user makes multiple swaps, Houdini normally selects the best-priced route each time. In practice, this often means the same provider handles consecutive swaps — creating a pattern that reduces privacy.

Payout wallet rotation solves this by deprioritizing recently used provider paths and selecting the next-best route instead, while keeping the price within an acceptable range.

<Note>
  Rotation applies to **CEX swaps only** (standard and private). DEX swaps execute on-chain through smart contracts and are not affected by provider path selection.
</Note>

## How It Works

<Steps>
  <Step title="Quote request with rotation enabled">
    You request quotes with `rotatePayoutWallets=true`. Houdini fetches quotes from all available providers as usual.
  </Step>

  <Step title="Recent path lookup">
    The system checks your recent orders (last N orders within 24 hours) to find which provider paths were already used.
  </Step>

  <Step title="Path deprioritization">
    Quotes matching recently used paths are moved down in the ranking. Quotes using fresh (not recently used) paths are promoted to the top.
  </Step>

  <Step title="Price protection">
    If the best non-recently-used quote deviates more than the allowed threshold from the original best quote, rotation is skipped and the best-priced route is used instead. You never pay significantly more for rotation.
  </Step>
</Steps>

## Parameters

<ParamField query="rotatePayoutWallets" type="boolean" default="false">
  Enable payout wallet rotation. When `true`, the system deprioritizes recently used provider paths in the quote ranking.
</ParamField>

<ParamField query="deviationThreshold" type="number" default="5">
  Maximum allowed price deviation percentage. If the best rotated quote is more than this percentage worse than the original best quote, rotation is skipped. Range: 0–100.
</ParamField>

<ParamField query="rotationLookback" type="number" default="10">
  Number of recent orders to check for previously used paths. Valid range: 2–99.
</ParamField>

## Lookup Priority

The system determines "recently used paths" based on the following priority:

| Priority | Identifier             | When used                                                          |
| -------- | ---------------------- | ------------------------------------------------------------------ |
| 1        | `multiId`              | MultiSwap orders — checks all orders in the same multi-swap group  |
| 2        | Partner ID             | Partner API calls — checks recent orders from your partner account |
| 3        | `receiverAddress` + IP | Anonymous/private orders — checks by destination address and IP    |

For partner integrations, your partner ID is automatically used (priority 2). You don't need to pass any additional identifiers.

## Price Protection

Rotation never forces a significantly worse price. The `deviationThreshold` parameter controls the maximum acceptable price difference:

* **Deviation ≤ threshold**: Rotated quote is used (different provider path)
* **Deviation > threshold**: Rotation is skipped, best-priced quote is returned
* **All quotes recently used**: Original ranking is preserved (no rotation possible)

**Example**: With `deviationThreshold=5`, if the best quote returns 10 ETH and the best *non-recently-used* quote returns 9.6 ETH (4% worse), the rotated quote is used. If it returns 9.4 ETH (6% worse), rotation is skipped.

## API v2 Usage

In v2, rotation is configured at **quote time**. The rotation parameters are query params on `GET /quotes`, and the selected quote carries the rotation context through to the exchange.

### Step 1: Get Quotes with Rotation

<CodeGroup>
  ```javascript Node.js theme={null}
  const params = new URLSearchParams({
    amount: '1',
    from: '6689b73ec90e45f3b3e51566',  // ETH token id
    to:   '6689b73ec90e45f3b3e51577',  // SOL token id
    types: 'private',
    rotatePayoutWallets: 'true',
    deviationThreshold: '5',
    rotationLookback: '10',
    receiverAddress: '1nc1nerator11111111111111111111111111111111'
  });

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

  const { quotes } = await response.json();
  // Quotes are already re-ranked with rotation applied
  const bestQuote = quotes[0];
  ```

  ```bash cURL theme={null}
  curl -G "https://api-partner.houdiniswap.com/v2/quotes" \
    -H "Authorization: YOUR_PARTNER_ID:YOUR_SECRET" \
    -d "amount=1" \
    -d "from=6689b73ec90e45f3b3e51566" \
    -d "to=6689b73ec90e45f3b3e51577" \
    -d "types=private" \
    -d "rotatePayoutWallets=true" \
    -d "deviationThreshold=5" \
    -d "rotationLookback=10" \
    -d "receiverAddress=1nc1nerator11111111111111111111111111111111"
  ```
</CodeGroup>

### Step 2: Create Exchange

No additional parameters needed — the quote already has rotation applied.

```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'
  },
  body: JSON.stringify({
    quoteId: bestQuote.quoteId,
    addressTo: '1nc1nerator11111111111111111111111111111111'
  })
});
```

## API v1 Usage

In v1, rotation can be configured on both the quote and exchange endpoints.

### Option A: Rotation at Quote Time

Pass rotation parameters as query params on `GET /quote`:

<CodeGroup>
  ```javascript Node.js theme={null}
  const params = new URLSearchParams({
    amount: '1',
    from: 'ETH',
    to: 'BNB',
    anonymous: 'true',
    useXmr: 'false',
    rotatePayoutWallets: 'true',
    deviationThreshold: '5',
    rotationLookback: '10'
  });

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

  ```bash cURL theme={null}
  curl -G "https://api-partner.houdiniswap.com/quote" \
    -H "Authorization: YOUR_PARTNER_ID:YOUR_SECRET" \
    -d "amount=1" \
    -d "from=ETH" \
    -d "to=BNB" \
    -d "anonymous=true" \
    -d "useXmr=false" \
    -d "rotatePayoutWallets=true" \
    -d "deviationThreshold=5" \
    -d "rotationLookback=10"
  ```
</CodeGroup>

### Option B: Rotation at Exchange Time

Pass a `filters` object in the `POST /exchange` request body:

<CodeGroup>
  ```javascript Node.js theme={null}
  const response = await fetch('https://api-partner.houdiniswap.com/exchange', {
    method: 'POST',
    headers: {
      'Authorization': `${API_KEY}:${API_SECRET}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      amount: 1,
      from: 'ETH',
      to: 'BNB',
      addressTo: '0x000000000000000000000000000000000000dead',
      anonymous: true,
      useXmr: false,
      ip: '203.0.113.1',
      userAgent: 'Mozilla/5.0',
      timezone: 'UTC',
      filters: {
        rotatePayoutWallets: true,
        deviationThreshold: 5,
        rotationLookback: 10
      }
    })
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api-partner.houdiniswap.com/exchange" \
    -H "Authorization: YOUR_PARTNER_ID:YOUR_SECRET" \
    -H "Content-Type: application/json" \
    -d '{
      "amount": 1,
      "from": "ETH",
      "to": "BNB",
      "addressTo": "0x000000000000000000000000000000000000dead",
      "anonymous": true,
      "useXmr": false,
      "ip": "203.0.113.1",
      "userAgent": "Mozilla/5.0",
      "timezone": "UTC",
      "filters": {
        "rotatePayoutWallets": true,
        "deviationThreshold": 5,
        "rotationLookback": 10
      }
    }'
  ```
</CodeGroup>

<Warning>
  When `rotatePayoutWallets` is enabled on `POST /exchange` in v1, any `inQuoteId` and `outQuoteId` values are discarded. The system fetches fresh quotes with rotation applied at exchange time. This adds a few seconds to the exchange request.
</Warning>

## v1 vs v2 Behavior

| Aspect                                | v1                                                | v2                                                   |
| ------------------------------------- | ------------------------------------------------- | ---------------------------------------------------- |
| **Where rotation is configured**      | Quote endpoint, exchange endpoint, or both        | Quote endpoint only                                  |
| **How rotation reaches the exchange** | `filters` object passed directly in exchange body | Inherited from the selected quote via `quoteId`      |
| **Quote IDs with rotation**           | Discarded when rotation is enabled on exchange    | Preserved — rotation is already applied to the quote |
| **Latency impact**                    | Adds \~3-5s when used on exchange (re-quotes)     | No additional latency on exchange                    |

<Tip>
  For v1 integrations, we recommend using rotation at **quote time** (Option A) rather than exchange time. This avoids the re-quoting overhead and gives you visibility into the rotated quotes before committing to an exchange.
</Tip>

## Best Practices

<AccordionGroup>
  <Accordion title="Use rotation for privacy-sensitive flows">
    Enable rotation for private/anonymous swaps where users make repeated swaps. For one-off standard swaps, rotation adds little value.
  </Accordion>

  <Accordion title="Keep the default deviation threshold">
    The default 5% threshold balances privacy with price quality. Setting it too high (e.g., 20%) may route through significantly worse-priced providers. Setting it too low (e.g., 1%) may prevent rotation entirely when quotes are tightly clustered.
  </Accordion>

  <Accordion title="Adjust lookback based on volume">
    If your integration processes many swaps per hour, increase `rotationLookback` to 20–30 to ensure broader path diversity. For low-volume integrations, the default of 10 is sufficient.
  </Accordion>

  <Accordion title="Combine with the swaps filter">
    Use the `swaps` parameter (v2) or `onlySwaps` filter (v1) alongside rotation to restrict which providers are considered. Rotation will only rotate within the allowed provider set.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Private Swap Integration" icon="mask" href="/developer-hub/swap-flows/private-swap">
    Full guide for integrating private multi-hop swaps
  </Card>

  <Card title="Routing Types" icon="route" href="/developer-hub/core-concepts/routing-types">
    Understand the three routing strategies
  </Card>
</CardGroup>
