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

# DexPaprika DEX API Python SDK: on-chain liquidity and swap data client

> The official Python client library for the DexPaprika API, providing easy access to decentralized exchange data across multiple blockchain networks

> [!TIP]
>
> See also: [REST intro](https://docs.dexpaprika.com/api-reference/introduction.md),
> [Networks](https://docs.dexpaprika.com/api-reference/networks/get-a-list-of-available-blockchain-networks.md),
> [Pools](https://docs.dexpaprika.com/api-reference/pools/get-a-pool-on-a-network.md)

## Installation

```bash theme={null}
# Using pip
pip install dexpaprika-sdk

# Using poetry
poetry add dexpaprika-sdk

# From source
git clone https://github.com/coinpaprika/dexpaprika-sdk-python
cd dexpaprika-sdk-python
pip install -e .
```

## Prerequisites

* Python 3.8 or higher
* Connection to the internet to access the DexPaprika API
* No API key needed to start

## Quick example: get token price

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient
from dexpaprika_sdk.models import TokenDetails  # Type hint example

# Create client and get WETH price on Ethereum
client = DexPaprikaClient()
token: TokenDetails = client.tokens.get_details("ethereum", "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
print(f"{token.name}: ${token.summary.price_usd:.2f}")
# Output: Wrapped Ether: $3245.67
```

## Using an API key (optional)

The SDK works without a key, and that is the default. A [free key](https://console.dexpaprika.com)
raises both the per-minute request limit and the credit allowance. Current figures are on the [rate limits page](https://docs.dexpaprika.com/knowledge-base/rate-limits.md).

Requires 0.9.0 or later.

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient

# Explicit
client = DexPaprikaClient(api_key="api_your_key_here")

# Or leave it out and set DEXPAPRIKA_API_KEY in the environment
client = DexPaprikaClient()
```

An explicit key beats the environment variable, and no key at all keeps the keyless behaviour
unchanged. The host is never inferred from the key: free keys are served from the default base URL,
and [Dev, Pro and Enterprise](https://docs.dexpaprika.com/api-pro/introduction.md) keys move to `api-pro.dexpaprika.com`.

> [!WARNING]
>
> The key is sent as the entire `Authorization` header value. **Nothing goes in front of it**,
> no scheme word of any kind. The SDK writes the header for you, so this matters when you are
> debugging what went out or calling the API directly. See
> [401 Unauthorized](https://docs.dexpaprika.com/knowledge-base/error-handling.md#401-unauthorized).

## API methods reference

> [!NOTE]
>
> Parameters marked with an asterisk (\*) are required.

**Networks** `category`

**methods**

### client.networks.list()

**Endpoint:** [GET `/networks`](https://docs.dexpaprika.com/api-reference/networks/get-a-list-of-available-blockchain-networks)

Gets all supported blockchain networks including Ethereum, Solana, etc.

**Parameters:** None

**Returns:** Network IDs, names, and related information. [Response Structure](https://docs.dexpaprika.com/api-reference/networks/get-a-list-of-available-blockchain-networks.md).

```python theme={null}
# Get all networks
networks = client.networks.list()
print(f"Found {len(networks)} networks")
```

**DEXes** `category`

**methods**

### client.dexes.list(network, page, limit)

**Endpoint:** [GET `/networks/{network}/dexes`](https://docs.dexpaprika.com/api-reference/dexes/get-a-list-of-available-dexes-on-a-network)

Gets all DEXes on a specific network.

**Parameters:**

* `network`\* - ID of the network (e.g., 'ethereum', 'solana')
* `page` - Page number for pagination (starts at 0)
* `limit` - Number of results per page

**Returns:** DEX IDs, names, pool counts, and volume information. [Response Structure](https://docs.dexpaprika.com/api-reference/dexes/get-a-list-of-available-dexes-on-a-network.md).

```python theme={null}
# Get all DEXes on Ethereum
dexes = client.dexes.list("ethereum")
print(f"Found {len(dexes.dexes)} DEXes on Ethereum")
```

**Pools** `category`

**methods**

### client.pools.list(page, limit, sort, order\_by)

> [!WARNING]
>
> **The `GET /pools` endpoint was removed and returns `410 Gone`.** Whatever this
> method does locally, the request cannot succeed. Use the network-scoped method
> below and pass a network, or call `GET /pools/search` with a `chains` filter
> directly. See [pool filtering](https://docs.dexpaprika.com/tutorials/pool-filtering.md).

**Endpoint:** GET `/pools` (removed, `410 Gone`)

Gets top pools across all networks with pagination.

**Parameters:**

* `page` - Page number for pagination (starts at 0)
* `limit` - Number of results per page
* `sort` - Sort direction ('asc' or 'desc')
* `order_by` - Field to sort by ('volume\_usd', 'liquidity\_usd', etc.)

***

### client.pools.list\_by\_network(network\_id, page, limit, sort, order\_by)

**Endpoint:** [GET `/networks/{network}/pools/search`](https://docs.dexpaprika.com/api-reference/pools/advanced-pool-filtering-on-a-specific-network)

Gets pools on a specific network with pagination and sorting options.

**Parameters:**

* `network_id`\* - ID of the network
* `limit` - Number of results per page
* `sort` - Sort direction ('asc' or 'desc')
* `order_by` - Field to sort by ('volume\_usd\_24h', 'liquidity\_usd', 'txns\_24h', and the rest of the canonical list). Legacy values are mapped, so `volume_usd` is sent as `order_by=volume_usd_24h`, and REST rejects the legacy spelling with `400`
* `cursor` - Cursor for the next page, taken from `next_cursor` on the previous response. `page` is validated but never sent: the endpoint is cursor-paginated

**Returns:** Cursor-paginated pools for the given network: a `results` array plus `has_next_page` and `next_cursor`. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/advanced-pool-filtering-on-a-specific-network.md).

```python theme={null}
# Get top 5 pools on Ethereum by volume
pools = client.pools.list_by_network(
    network_id="ethereum",
    limit=5,
    order_by="volume_usd_24h",
    sort="desc"
)
print(f"Found {len(pools.results)} pools on Ethereum")
```

***

### client.pools.list\_by\_dex(network\_id, dex\_id, limit, sort, order\_by, cursor)

> [!WARNING]
>
> **`GET /networks/{network}/dexes/{dex}/pools` was removed and returns `410 Gone`.**
> This method now calls `GET /networks/{network}/pools/search?dex_name=...` instead. The DEX id
> moved out of the path and into a filter, so `page` is gone and the response shape changed.
> See [pool filtering](https://docs.dexpaprika.com/tutorials/pool-filtering.md).

**Endpoint:** [GET `/networks/{network}/pools/search?dex_name=...`](https://docs.dexpaprika.com/api-reference/pools/advanced-pool-filtering-on-a-specific-network)

Gets pools on a specific DEX within a network.

**Parameters:**

* `network_id`\* - ID of the network
* `dex_id`\* - ID of the DEX, the `dex_id` field from `client.dexes.list_by_network()`, case-insensitive (a display name like `Uniswap V3` returns no rows instead of an error)
* `limit` - Number of results per page (max 100)
* `sort` - Sort direction ('asc' or 'desc')
* `order_by` - Field to sort by ('volume\_usd\_24h', 'liquidity\_usd', 'txns\_24h', and the rest of the canonical list)
* `cursor` - Cursor for the next page, taken from `next_cursor` on the previous response

> [!NOTE]
>
> There is no `page` argument any more. The SDK normalizes legacy sort values, so `volume_usd` is
> sent as `order_by=volume_usd_24h`; REST rejects the legacy spelling with a `400` that lists the
> values it will take.

**Returns:** A `results` list plus `has_next_page` and `next_cursor` for cursor pagination. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/advanced-pool-filtering-on-a-specific-network.md).

```python theme={null}
# Get the busiest Uniswap V3 pools on Ethereum
uniswap_pools = client.pools.list_by_dex(
    network_id="ethereum", 
    dex_id="uniswap_v3", 
    limit=10, 
    order_by="volume_usd_24h", 
    sort="desc"
)
for pool in uniswap_pools.results:
    print(f"{pool.dex_name}: ${pool.volume_usd_24h:,.2f} 24h volume")
```

***

### client.pools.get\_details(network\_id, pool\_address, inversed)

**Endpoint:** [GET `/networks/{network}/pools/{pool_address}`](https://docs.dexpaprika.com/api-reference/pools/get-a-pool-on-a-network)

Gets detailed information about a specific pool.

**Parameters:**

* `network_id`\* - ID of the network
* `pool_address`\* - On-chain address of the pool
* `inversed` - Whether to invert the price ratio (boolean)

**Returns:** Detailed pool information including tokens, volumes, liquidity, and more. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/get-a-pool-on-a-network.md).

```python theme={null}
from dexpaprika_sdk.models import PoolDetails  # Type hint example

# Get details for a specific pool (WETH/USDC on Uniswap V2)
pool: PoolDetails = client.pools.get_details(
    network_id="ethereum", 
    pool_address="0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc", 
    inversed=False
)
print(f"Pool: {pool.tokens[0].symbol}/{pool.tokens[1].symbol}")
```

***

### client.pools.get\_transactions(network\_id, pool\_address, page, limit, cursor, from\_timestamp, to\_timestamp)

**Endpoint:** [GET `/networks/{network}/pools/{pool_address}/transactions`](https://docs.dexpaprika.com/api-reference/pools/get-transactions-of-a-pool-on-a-network-paging-can-be-used-up-to-100-pages)

Gets transaction history for a specific pool with pagination.

Needs a Dev, Pro or Enterprise key and the `https://api-pro.dexpaprika.com` base URL since 30 September 2026; keyless and free keys get `403`. See [pool transactions](https://docs.dexpaprika.com/api-reference/pools/get-transactions-of-a-pool-on-a-network-paging-can-be-used-up-to-100-pages.md).

**Parameters:**

* `network_id`\* - ID of the network
* `pool_address`\* - On-chain address of the pool
* `page` - Page number for pagination
* `limit` - Number of transactions per page
* `cursor` - Transaction ID for cursor-based pagination
* `from_timestamp` / `to_timestamp` - Time window: a relative offset such as `"-1h"`, Unix seconds, RFC3339 or `YYYY-MM-DD`. `from_timestamp` is inclusive, `to_timestamp` exclusive; results go back 7 days at most

**Returns:** List of transactions with details about tokens, amounts, and timestamps. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/get-transactions-of-a-pool-on-a-network-paging-can-be-used-up-to-100-pages.md).

```python theme={null}
# Get the latest 20 transactions for a pool
transactions = client.pools.get_transactions(
    network_id="ethereum",
    pool_address="0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc",
    limit=20
)
latest = transactions.transactions[0]
print(f"Latest transaction: {latest.id} in block {latest.created_at_block_number}")

# Only the last hour
last_hour = client.pools.get_transactions(
    network_id="ethereum",
    pool_address="0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc",
    limit=20,
    from_timestamp="-1h"
)
```

***

### client.pools.get\_ohlcv(network\_id, pool\_address, start, end, limit, interval, inversed)

**Endpoint:** [GET `/networks/{network}/pools/{pool_address}/ohlcv`](https://docs.dexpaprika.com/api-reference/pools/get-ohlcv-data-for-a-pool-pair)

Gets OHLCV (Open, High, Low, Close, Volume) chart data for a pool.

**Parameters:**

* `network_id`\* - ID of the network
* `pool_address`\* - On-chain address of the pool
* `start`\* - Start time (relative offset such as `-24h`, ISO date string, YYYY-MM-DD, or Unix timestamp), inside your plan's [history window](https://docs.dexpaprika.com/knowledge-base/rate-limits.md#ohlcv-limits-by-plan)
* `end` - End time (optional)
* `limit` - Number of data points to return
* `interval` - Time interval ('1m', '5m', '10m', '15m', '30m', '1h', '6h', '12h', '24h'); without a key only '1h' and up
* `inversed` - Whether to invert the price ratio (boolean)

**Returns:** Array of OHLCV data points for the specified time range and interval. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/get-ohlcv-data-for-a-pool-pair.md).

```python theme={null}
# Hourly candles for the last 24 hours, which works without a key
ohlcv = client.pools.get_ohlcv(
    network_id="ethereum",
    pool_address="0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc",
    start="-24h",
    interval="1h",
    limit=24
)

print(f"Received {len(ohlcv)} OHLCV data points")
```

***

### client.pools.get\_indicator(network\_id, pool\_address, indicator, interval, start, end, limit, cursor, period, fast\_period, slow\_period, signal\_period, std\_dev)

**Endpoint:** [GET `/networks/{network}/pools/{pool_address}/indicators`](https://docs.dexpaprika.com/api-reference/pools/get-a-technical-indicator-for-a-pool)

Computes RSI, EMA, MACD, Bollinger Bands or VWAP from a pool's candles. Requires SDK 0.13.0 or later.

**Parameters:**

* `network_id`\* - ID of the network
* `pool_address`\* - On-chain address of the pool
* `indicator`\* - `'rsi'`, `'ema'`, `'macd'`, `'bbands'` or `'vwap'`
* `interval` - Candle interval (`'1m'` to `'24h'`, or `'1d'`); pass it every time
* `start`, `end`, `limit`, `cursor` - Range and paging, same formats as OHLCV
* `period` - rsi, ema, bbands and vwap
* `fast_period`, `slow_period`, `signal_period` - macd only
* `std_dev` - bbands only

Only the parameters you pass are sent. One that belongs to another indicator, such as `fast_period` with `indicator="rsi"`, raises `requests.HTTPError` with status 400.

**Returns:** `data`, oldest first, one point per completed candle: `value` for rsi, ema and vwap; `macd`, `signal` and `histogram` for macd; `upper`, `middle` and `lower` for bbands. `parameters` echoes the settings used, defaults included, and `has_next_page`/`next_cursor` page through longer ranges. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/get-a-technical-indicator-for-a-pool.md).

Works on every plan, keyless included, with the same interval and history limits as pool OHLCV ([limits by plan](https://docs.dexpaprika.com/knowledge-base/rate-limits.md#ohlcv-limits-by-plan)). Tutorial: [technical indicators](https://docs.dexpaprika.com/tutorials/technical-indicators.md).

```python theme={null}
# Hourly RSI over the last 24 hours, which works without a key
rsi = client.pools.get_indicator(
    network_id="ethereum",
    pool_address="0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640",
    indicator="rsi",
    interval="1h",
    start="-24h",
)

last = rsi.data[-1]
print(f"RSI {last.value:.1f} at {last.timestamp}")
```

**Tokens** `category`

**methods**

### client.tokens.get\_details(network\_id, token\_address)

**Endpoint:** [GET `/networks/{network}/tokens/{token_address}`](https://docs.dexpaprika.com/api-reference/tokens/get-a-tokens-latest-data-on-a-network)

Gets comprehensive token information.

**Parameters:**

* `network_id`\* - ID of the network
* `token_address`\* - Token contract address

**Returns:** Token details including price, market cap, volume, and metadata. [Response Structure](https://docs.dexpaprika.com/api-reference/tokens/get-a-tokens-latest-data-on-a-network.md).

```python theme={null}
# Get WETH token details
weth = client.tokens.get_details(
    network_id="ethereum",
    token_address="0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
)
print(f"{weth.name} price: ${weth.summary.price_usd:,.2f}")
```

***

### client.tokens.get\_pools(network\_id, token\_address, limit, sort, order\_by, cursor)

> [!WARNING]
>
> **`GET /networks/{network}/tokens/{token_address}/pools` was removed and returns `410 Gone`.**
> This method now calls `GET /networks/{network}/pools/search?token_address=...` instead, so it still
> works. The old second-token `address` pair filter and the `reorder` flag have no replacement: pass
> either and the SDK raises a `DeprecationWarning` and drops it. See [pool filtering](https://docs.dexpaprika.com/tutorials/pool-filtering.md).

**Endpoint:** [GET `/networks/{network}/pools/search?token_address=...`](https://docs.dexpaprika.com/api-reference/pools/advanced-pool-filtering-on-a-specific-network)

Gets pools containing a specific token.

**Parameters:**

* `network_id`\* - ID of the network
* `token_address`\* - Token contract address
* `limit` - Number of results per page (1 to 100)
* `sort` - Sort direction ('asc' or 'desc')
* `order_by` - Field to sort by ('volume\_usd\_24h', 'liquidity\_usd', 'txns\_24h', and the rest of the canonical list). Legacy values are mapped, so `volume_usd` is sent as `order_by=volume_usd_24h`; REST rejects the legacy spelling with `400`
* `cursor` - Cursor for the next page, taken from `next_cursor` on the previous response. `page` is validated but never sent: the endpoint is cursor-paginated
* `address`, `reorder` - deprecated and ignored

**Returns:** A `PoolSearchResponse` with `results`, `has_next_page` and `next_cursor`. [Response Structure](https://docs.dexpaprika.com/api-reference/pools/advanced-pool-filtering-on-a-specific-network.md).

```python theme={null}
# Get the busiest WETH pools on Ethereum
pools = client.tokens.get_pools(
    network_id="ethereum",
    token_address="0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",  # WETH
    limit=5,
    order_by="volume_usd_24h",
    sort="desc",
)

for pool in pools.results:
    print(f"{pool.dex_name}: ${pool.volume_usd_24h:,.2f} 24h volume")
```

***

### client.tokens.get\_indicator(network\_id, token\_address, indicator, ...)

**Endpoint:** [GET `/networks/{network}/tokens/{token_address}/indicators`](https://docs.dexpaprika.com/api-reference/tokens/get-a-technical-indicator-for-a-token)

The same indicators computed from the token's USD candles across every pool it trades in. Same parameters and response shape as `client.pools.get_indicator`. Requires SDK 0.13.0 or later.

Needs a Dev, Pro or Enterprise key and the `https://api-pro.dexpaprika.com` base URL; keyless and free keys get `403` with the required plan named in the message.

```python theme={null}
macd = client.tokens.get_indicator(
    network_id="ethereum",
    token_address="0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",  # WETH
    indicator="macd",
    interval="1h",
    start="-7d",
)

last = macd.data[-1]
print(last.macd, last.signal, last.histogram)
```

**Search** `category`

**methods**

### client.search.search(query)

**Endpoint:** [GET `/search`](https://docs.dexpaprika.com/api-reference/search/search-for-tokens-pools-and-dexes)

Searches across tokens, pools, and DEXes using a query string.

**Parameters:**

* `query`\* - Search query string

**Returns:** Matching entities from all categories (tokens, pools, DEXes). [Response Structure](https://docs.dexpaprika.com/api-reference/search/search-for-tokens-pools-and-dexes.md).

```python theme={null}
# Search for "ethereum" across all entities
results = client.search.search("ethereum")

print(f"Found {len(results.tokens)} tokens")
print(f"Found {len(results.pools)} pools")
print(f"Found {len(results.dexes)} dexes")
```

**Utils** `category`

**methods**

### client.utils.get\_stats()

**Endpoint:** [GET `/stats`](https://docs.dexpaprika.com/api-reference/utils/retrieve-high-level-asset-statistics)

Gets platform-wide statistics.

**Parameters:** None

**Returns:** Counts of chains, DEXes, pools, and tokens indexed. [Response Structure](https://docs.dexpaprika.com/api-reference/utils/retrieve-high-level-asset-statistics.md).

```python theme={null}
# Get platform statistics
stats = client.utils.get_stats()

print(f"Total chains: {stats.chains}")
print(f"Total DEX factories: {stats.factories}")
print(f"Total pools: {stats.pools}")
print(f"Total tokens: {stats.tokens}")
```

## Complete example

**example**

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient

WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"


def main():
    client = DexPaprikaClient()

    # Networks come back as a list of Network(id, display_name)
    networks = client.networks.list()
    ethereum = next(n for n in networks if n.id == "ethereum")
    print(f"{ethereum.display_name} is one of {len(networks)} networks")

    # Price lives under summary
    weth = client.tokens.get_details(network_id="ethereum", token_address=WETH)
    print(f"{weth.name} price: ${weth.summary.price_usd:,.2f}")

    # Pools for a token are served by pool search. Rows sit under results,
    # sorted by volume_usd_24h. There is no pair filter, so match the second
    # token client-side.
    pools = client.tokens.get_pools(
        network_id="ethereum",
        token_address=WETH,
        limit=20,
        order_by="volume_usd_24h",
        sort="desc",
    )
    weth_usdc = [p for p in pools.results if any(t.id == USDC for t in p.tokens)]

    print("Top WETH/USDC pools:")
    for pool in weth_usdc[:5]:
        print(f"{pool.dex_name}: ${pool.volume_usd_24h:,.2f} 24h volume")


if __name__ == "__main__":
    main()
```

## Advanced features

### Error handling

**error handling**

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient
import requests

# Basic error handling
try:
    client = DexPaprikaClient()
    token = client.tokens.get_details("ethereum", "0xinvalidaddress")
except Exception as e:
    if "404" in str(e):
        print("Token not found")
    elif "429" in str(e):
        print("Rate limit exceeded")
    else:
        print(f"An error occurred: {e}")

# The SDK automatically retries 429 (Too Many Requests), any 5xx
# (server errors), connection errors and timeouts. On a 429 it waits
# as long as the API's Retry-After header asks.

# Custom retry configuration
client = DexPaprikaClient(
    max_retries=4,  # Number of retry attempts (default: 4)
    backoff_times=[0.1, 0.5, 1.0, 5.0]  # Backoff times in seconds
)

# All API requests will now use these retry settings
try:
    networks = client.networks.list()
except requests.exceptions.RequestException as e:
    print(f"Request failed: {e}")
```

### Caching system

**caching**

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient
import time

# The SDK includes built-in caching by default
# Demonstration of cache behavior

# Create a regular client with default cache (5 minutes TTL)
client = DexPaprikaClient()

# First call - hits the API
start_time = time.time()
networks = client.networks.list()
first_call_time = time.time() - start_time
print(f"First call (API): {len(networks)} networks, took {first_call_time:.4f}s")

# Second call - served from cache (much faster)
start_time = time.time()
networks = client.networks.list()
second_call_time = time.time() - start_time
print(f"Second call (cached): {len(networks)} networks, took {second_call_time:.4f}s")
print(f"Cache speedup: {first_call_time / second_call_time:.1f}x")

# You can skip the cache when you need fresh data
fresh_networks = client.networks._get("/networks", skip_cache=True)

# Clear the entire cache
client.clear_cache()

# Clear cache only for specific endpoints
client.clear_cache(endpoint_prefix="/networks")

# Different types of data have different cache durations:
# - Network data: 24 hours
# - Pool data: 5 minutes
# - Token data: 10 minutes
# - Statistics: 15 minutes
# - Other data: 5 minutes (default)
```

### Pagination helper

**pagination**

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient
import time

def fetch_all_pools(network_id, max_pages=10):
    client = DexPaprikaClient()
    all_pools = []
    limit = 50
    cursor = None

    # Every page is one request against your allowance, so cap the walk
    for _ in range(max_pages):
        response = client.pools.list_by_network(
            network_id=network_id,
            limit=limit,
            sort="desc",
            order_by="volume_usd_24h",
            cursor=cursor,
        )

        all_pools.extend(response.results)

        # The search endpoint is cursor-paginated, not page-numbered
        if not response.has_next_page or not response.next_cursor:
            break
        cursor = response.next_cursor

        # Keyless allows 15 requests a minute, so pause 4 seconds between pages.
        # A free key doubles the rate: https://console.dexpaprika.com
        time.sleep(4)

    print(f"Fetched a total of {len(all_pools)} pools on {network_id}")
    return all_pools

# Usage example
ethereum_pools = fetch_all_pools("ethereum")
```

### Parameter validation

**validation**

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient

# The SDK automatically validates parameters before making API requests
client = DexPaprikaClient()

# Invalid parameter examples will raise helpful error messages
try:
    # Invalid network ID
    client.pools.list_by_network(network_id="", limit=5)
except ValueError as e:
    print(e)  # "network_id is required"
    
try:
    # Invalid sort parameter
    client.pools.list_by_network(network_id="ethereum", sort="invalid_sort")
except ValueError as e:
    print(e)  # "sort must be one of: asc, desc"
    
try:
    # Invalid limit parameter
    client.pools.list_by_network(network_id="ethereum", limit=500)
except ValueError as e:
    print(e)  # "limit must be at most 100"
```

### Working with models

**models**

```python theme={null}
from dexpaprika_sdk import DexPaprikaClient
from dexpaprika_sdk.models import PoolDetails  # Type hint example

client = DexPaprikaClient()

# Get pool details
pool: PoolDetails = client.pools.get_details(
    network_id="ethereum",
    pool_address="0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"  # USDC/WETH Uniswap v3 pool
)

# Access pool properties with type checking and auto-completion
print(f"Pool: {pool.tokens[0].symbol}/{pool.tokens[1].symbol}")
print(f"Volume (24h): ${pool.day.volume_usd:.2f}")
print(f"Transactions (24h): {pool.day.txns}")
print(f"Price: ${pool.last_price_usd:.4f}")

# Time interval data is available for multiple timeframes
print(f"1h price change: {pool.hour1.last_price_usd_change:.2f}%")
print(f"24h price change: {pool.day.last_price_usd_change:.2f}%")

# All API responses are converted to typed Pydantic models
# This provides automatic validation, serialization/deserialization,
# and IDE auto-completion support through Python type hints
```

## Resources

* [GitHub Repository](https://github.com/coinpaprika/dexpaprika-sdk-python)
* [DexPaprika Website](https://dexpaprika.com)
* [API Reference](https://docs.dexpaprika.com/api-reference/introduction.md)
* [Discord Community](https://discord.gg/DhJge5TUGM)

## API status

The DexPaprika API provides consistent data with stable endpoints. Requests are answered without an API key on the free tier, and a free key raises the credit allowance. We aim to maintain backward compatibility and provide notice of any significant changes.

### FAQs

> **Do I need an API key with this SDK?**
>
> Not to start. Keyless requests work at 10,000 credits per rolling 30 days per IP, and a [free registered key](https://console.dexpaprika.com/dashboard) raises that to 100,000 with no card.

> **How do I find identifiers?**
>
> Use Coverage Checker or list Networks and query Tokens/Pools to discover addresses.

> **How do I get historical or transactions data?**
>
> Use pools/transactions endpoints with `pool_address`, `network`, and time/paging params as documented. Transactions need a Dev, Pro or Enterprise key on `api-pro.dexpaprika.com`.

> **What about rate limiting?**
>
> 15 requests a minute keyless, 30 with a [free key](https://console.dexpaprika.com) and 500 on Pro, against 10,000 credits keyless and 100,000 with a free key over a rolling 30 days, or 5,000,000 a month on Pro. Retry transient HTTP errors with backoff. See [rate limits](https://docs.dexpaprika.com/knowledge-base/rate-limits.md) for how the counters work, and [Pro pricing](https://dexpaprika.com/api/pricing) for what the 5,000,000 credit tier costs.


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