> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pool Targeting: Route Swaps Through Specific Pools

> Learn how to target specific liquidity pools or DEX protocols when executing swaps via the Mobula Swap API

## Overview

By default, the Mobula Swap API automatically finds the best route across all available liquidity sources. However, you may want to **target a specific pool** or **restrict routing to certain protocols** — for example, to:

* Execute a swap directly through a specific Aerodrome CL pool on Base
* Restrict routing to only Uniswap V3 pools
* Avoid certain factory contracts
* Force routing through a specific DEX for compliance or analytics

The Swap API provides three parameters for pool targeting:

| Parameter | Routing | Description |
| - | - | - |
| `poolAddress` | **Direct on-chain** | Target a specific pool by address — bypasses aggregators, executes directly via MobulaRouter |
| `onlyProtocols` | Via aggregator | Restrict to specific pool types (e.g., `uniswap-v3`) — routed through KyberSwap/Jupiter |
| `excludedProtocols` | Via aggregator | Exclude specific factory addresses from routing |

<Note>
  **Key difference**: `poolAddress` routes the swap **directly on-chain** through MobulaRouter's `executeRoute` function. `onlyProtocols` passes the restriction to an external aggregator (KyberSwap, Jupiter) which handles the routing.
</Note>

## Direct Pool Access (`poolAddress`)

Use `poolAddress` when you know the exact pool contract address and want to swap **directly through it**, without going through an external aggregator. The swap is executed on-chain via MobulaRouter's internal routing engine.

### Basic Example

Route a USDC → WETH swap directly through a specific Aerodrome CL pool on Base:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:8453\
&tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
&tokenOut=0x4200000000000000000000000000000000000006\
&amount=100\
&walletAddress=0xYourWallet\
&slippage=1\
&poolAddress=0xb4cb800910b228ed3d0834cf79d697127bbb00e5"
```

### Concrete Example — USDC to TKFG on Aerodrome CL (Base)

This example swaps \~300 USDC (raw units) to TKFG on Base, routed directly through the Aerodrome CL pool:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm%3A8453\
&tokenIn=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\
&tokenOut=0xe9d139df6212fde346ec650e83039f322018f60d\
&amountRaw=300539874\
&walletAddress=0xYourWallet\
&slippage=1\
&poolAddress=0x66fbdb0b14a889b3735da163843289a55d28bb97"
```

The response transaction will use MobulaRouter's `executeRoute` selector (`0x1688b026` as of v2.19.0; `0xa564dfa4` on routers still running v2.17.0), executing the swap directly on-chain without any aggregator intermediary.

<Tip>
  You can discover pool addresses using the [Token Markets](/rest-api-reference/endpoint/token-markets) endpoint, which returns all pools for a given token pair along with their addresses, types, and liquidity.
</Tip>

### When to Use `poolAddress`

* You want **zero aggregator fees** — the swap goes directly through the pool
* You need **deterministic routing** — always the exact same pool, no fallback
* You're building a **pool-specific UI** (e.g., showing swap for a specific market)
* Multiple pools exist for the same pair (e.g., different fee tiers) and you want a specific one

## Filtering by Protocol (`onlyProtocols`)

Use `onlyProtocols` to restrict the swap to pools of a specific type. The swap is routed through an external aggregator (KyberSwap on EVM, Jupiter on Solana) which applies the filter.

### Single Protocol

Route a swap exclusively through Uniswap V3 pools:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:1\
&tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\
&tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\
&amount=0.5\
&walletAddress=0xYourWallet\
&slippage=1\
&onlyProtocols=uniswap-v3"
```

### Multiple Protocols

Route through either Aerodrome CL or Uniswap V3 pools on Base:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:8453\
&tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
&tokenOut=0x4200000000000000000000000000000000000006\
&amount=100\
&walletAddress=0xYourWallet\
&slippage=1\
&onlyProtocols=aerodrome-cl-2,uniswap-v3"
```

## Excluding Protocols (`excludedProtocols`)

Use `excludedProtocols` to exclude specific factory addresses from routing. Unlike `onlyProtocols` which takes pool type names, this parameter takes **factory contract addresses**:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:1\
&tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\
&tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\
&amount=1\
&walletAddress=0xYourWallet\
&slippage=1\
&excludedProtocols=0x1F98431c8aD98523631AE4a59f267346ea31F984"
```

## Common Pool Types

### EVM Chains

| Pool Type | Description |
| - | - |
| `uniswap-v2` | Uniswap V2 and forks (SushiSwap, PancakeSwap V2, etc.) |
| `uniswap-v3` | Uniswap V3 concentrated liquidity pools |
| `uniswap-v4` | Uniswap V4 pools with hooks |
| `aerodrome` | Aerodrome V2 pools (Base) |
| `aerodrome-cl-2` | Aerodrome CL (concentrated liquidity) pools (Base) |
| `pancakeswap-v3` | PancakeSwap V3 pools |
| `solidly-v2` | Solidly V2 pools and forks |
| `solidly-v3` | Solidly V3 pools (CL) |
| `trader-joe-v2.1` | Trader Joe Liquidity Book pools |
| `maverick-v2` | Maverick V2 pools |

### Solana

| Pool Type | Description |
| - | - |
| `raydium-amm` | Raydium AMM pools |
| `raydium-clmm` | Raydium concentrated liquidity pools |
| `raydium-cpmm` | Raydium constant product pools |
| `orca-whirlpool` | Orca Whirlpool concentrated liquidity pools |
| `meteora-dlmm` | Meteora DLMM pools |
| `pumpfun` | PumpFun bonding curve pools |
| `pumpswap` | PumpSwap pools |

<Note>
  Only **tradable** pool types are accepted by `onlyProtocols`. Non-tradable types are automatically filtered out. If no valid pool types remain after filtering, the API returns a "No route found" error.
</Note>

## Choosing a Router (`onlyRouters`)

You can also restrict which **aggregator/router** handles the swap, independently from pool targeting:

| Router | Chains | Description |
| - | - | - |
| `kyberswap` | EVM | KyberSwap aggregator (no extra fees) |
| `lifi` | EVM | LI.FI cross-chain aggregator |
| `jupiter` | Solana | Jupiter aggregator |

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/swap/quoting?\
chainId=evm:8453\
&tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\
&tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
&amount=0.01\
&walletAddress=0xYourWallet\
&slippage=1\
&onlyRouters=kyberswap"
```

## TypeScript Example

```typescript theme={null}
// Direct pool access — swap through a specific pool on-chain
async function swapViaSpecificPool() {
  const params = new URLSearchParams({
    chainId: 'evm:8453',
    tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
    tokenOut: '0x4200000000000000000000000000000000000006', // WETH
    amount: '100', // 100 USDC
    walletAddress: '0xYourWallet',
    slippage: '1',
    poolAddress: '0xb4cb800910b228ed3d0834cf79d697127bbb00e5', // Specific pool
  });

  const response = await fetch(
    `https://api.mobula.io/api/2/swap/quoting?${params}`,
    { headers: { Authorization: 'YOUR_API_KEY' } }
  );

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

  // Transaction uses MobulaRouter's executeRoute (direct on-chain)
  console.log('Route:', data.route);
  console.log('Estimated output:', data.estimatedAmountOut);
  console.log('Transaction:', data.evm?.transaction);
}

// Protocol-filtered — restrict aggregator to specific pool types
async function swapWithProtocolFilter() {
  const params = new URLSearchParams({
    chainId: 'evm:8453',
    tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    tokenOut: '0x4200000000000000000000000000000000000006',
    amount: '100',
    walletAddress: '0xYourWallet',
    slippage: '1',
    onlyProtocols: 'aerodrome-cl-2', // Only Aerodrome CL pools
  });

  const response = await fetch(
    `https://api.mobula.io/api/2/swap/quoting?${params}`,
    { headers: { Authorization: 'YOUR_API_KEY' } }
  );

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

  // Transaction uses aggregator (KyberSwap) with protocol filter
  console.log('Route:', data.route);
  console.log('Estimated output:', data.estimatedAmountOut);
  console.log('Transaction:', data.evm?.transaction);
}
```

## Troubleshooting

| Issue | Cause | Solution |
| - | - | - |
| `"No route found"` | No pool of the requested type exists for this pair | Check the pool type name is correct, or try without `onlyProtocols` |
| `"Pool not found"` | The `poolAddress` doesn't exist in Mobula's index | Verify the pool address on a block explorer |
| Swap uses aggregator instead of direct access | Used `onlyProtocols` instead of `poolAddress` | Use `poolAddress` for direct on-chain routing |
| `"Invalid protocol"` | Typo in the pool type name | Check the [Common Pool Types](#common-pool-types) table above |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.