# DexPaprika: DEX Data for AI Agents

DEX data across 36 blockchains. 33M+ tokens, 36M+ pools. No API key needed to start; quotas apply per plan.

> **Field naming note:** URL paths use `network` and `token_address`, but JSON responses use `chain` and `id` for the same values.

---

## Option A: CLI (Recommended)

Install and query in seconds. Best for agents that can run shell commands.

```bash
curl -sSL https://raw.githubusercontent.com/coinpaprika/dexpaprika-cli/main/install.sh | sh
```

After install, use `--output json --raw` for machine-readable output. Run `dexpaprika-cli onboard` for an interactive quick-start guide.

### Get token price

```bash
dexpaprika-cli token ethereum 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 --output json --raw
```

### Search for any token

```bash
dexpaprika-cli search USDC --output json --raw
```

### Historical OHLCV

```bash
# hourly candles over the last 24 hours (a relative --start needs CLI 0.7.0+)
dexpaprika-cli pool-ohlcv ethereum 0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640 --start -24h --interval 1h --limit 24 --output json --raw

# USD candles for a token across every pool it trades in: Dev or Pro key, CLI 0.9.0+
DEXPAPRIKA_API_BASE_URL=https://api-pro.dexpaprika.com dexpaprika-cli token-ohlcv ethereum 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 --start -24h --interval 1h --limit 24 --output json --raw
```

### Top pools on a network

```bash
dexpaprika-cli pools ethereum --limit 10 --output json --raw
```

### Batch token prices

```bash
dexpaprika-cli prices ethereum --tokens 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2,0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --output json --raw
```

### Stream real-time prices

```bash
dexpaprika-cli stream ethereum 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
```

### All commands

```bash
dexpaprika-cli --help
```

---

## Option B: Direct HTTP API

Can't install binaries? Use the REST API directly. No key needed to start, no setup.

**Base URL:** `https://api.dexpaprika.com`

### Keys, plans and hosts

| Caller | Host | Header |
| ------ | ---- | ------ |
| No key | `https://api.dexpaprika.com` | none |
| Free key | `https://api.dexpaprika.com` | `Authorization: <key>` |
| Dev, Pro or Enterprise key | `https://api-pro.dexpaprika.com` | `Authorization: <key>` |

- Send the key as the entire `Authorization` header value, exactly as the console shows it (it starts with `api_`), with nothing in front of it.
- A free key from <https://console.dexpaprika.com> raises the per-minute rate and the credit allowance. Paid plans raise both again.
- Pool transactions and token OHLCV need a Dev, Pro or Enterprise key on `api-pro`. Everything else in the table below works without a key.
- Current limits and prices for every plan are on <https://dexpaprika.com/api/pricing>. Don't hard-code them, because they change.

### Endpoints

| Need                      | Endpoint                                                    |
| ------------------------- | ----------------------------------------------------------- |
| List networks             | `GET /networks`                                             |
| Token price + data        | `GET /networks/{network}/tokens/{token_address}`            |
| Pool OHLCV (charts)       | `GET /networks/{network}/pools/{pool_address}/ohlcv`        |
| Token OHLCV, USD across all pools (Dev or Pro, on api-pro) | `GET /networks/{network}/tokens/{token_address}/ohlcv` |
| Top / filter pools on network | `GET /networks/{network}/pools/search`                  |
| Pools for specific DEX    | `GET /networks/{network}/pools/search?dex_name={dex_id}`    |
| Single pool details       | `GET /networks/{network}/pools/{pool_address}`              |
| Pool transactions (Dev or Pro, on api-pro) | `GET /networks/{network}/pools/{pool_address}/transactions` |
| Pools containing token    | `GET /networks/{network}/pools/search?token_address={token_address}` |
| Batch token prices        | `GET /networks/{network}/multi/prices?tokens={addresses}`   |
| Search tokens/pools/DEXes | `GET /search?query={term}`                                  |
| Top / filter tokens on network | `GET /networks/{network}/tokens/search`                 |

### Python: Get token price

```python
import requests

r = requests.get("https://api.dexpaprika.com/networks/ethereum/tokens/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
token = r.json()
print(f"{token['symbol']}: ${token['summary']['price_usd']}")
# WETH: $1949.80
```

Response shape:

```json
{
    "id": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
    "symbol": "WETH",
    "name": "Wrapped Ether",
    "chain": "ethereum",
    "decimals": 18,
    "summary": {
        "price_usd": 1961.37,
        "fdv": 4042695827.62,
        "liquidity_usd": 600300838.77,
        "pools": 4452,
        "24h": {
            "volume": 297956.4,
            "volume_usd": 602685018.28,
            "buys": 96906,
            "sells": 108936,
            "txns": 206371,
            "buy_usd": 313242803.62,
            "sell_usd": 289442214.65,
            "last_price_usd_change": -4.86
        },
        "6h": {},
        "1h": {},
        "30m": {},
        "15m": {},
        "5m": {},
        "1m": {}
    }
}
```

### Python: Search

```python
r = requests.get("https://api.dexpaprika.com/search", params={"query": "WETH"})
results = r.json()
# results has: tokens[], pools[], dexes[]
for t in results['tokens']:
    print(f"{t['symbol']} on {t['chain']}: ${t['price_usd']}")
```

**Note:** Search does fuzzy name+symbol matching. Searching "UNI" will also return "United Stables", "Unit Bitcoin", etc. Filter results client-side by exact `symbol` match if needed.

Response shape:

```json
{
    "tokens": [
        {
            "id": "0xc02a...",
            "chain": "ethereum",
            "symbol": "WETH",
            "name": "Wrapped Ether",
            "price_usd": 2024.9,
            "liquidity_usd": 604172672.26,
            "volume_usd": 636477516.22
        }
    ],
    "pools": [
        {
            "id": "0x88e6...",
            "chain": "ethereum",
            "dex_name": "Uniswap V3",
            "volume_usd": 337786442.82,
            "tokens": [{ "symbol": "USDC" }, { "symbol": "WETH" }]
        }
    ],
    "dexes": []
}
```

### Python: Batch token prices

```python
r = requests.get("https://api.dexpaprika.com/networks/ethereum/multi/prices",
    params={"tokens": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2,0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"})
prices = r.json()  # Returns an ARRAY, not a keyed object
for p in prices:
    print(f"{p['id']}: ${p['price_usd']}")
```

Response shape (array):

```json
[
    { "id": "0xc02a...", "price_usd": 2024.9 },
    { "id": "0xa0b8...", "price_usd": 1.0 }
]
```

### Python: Historical OHLCV

```python
r = requests.get("https://api.dexpaprika.com/networks/ethereum/pools/0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640/ohlcv",
    params={"start": "-24h", "interval": "1h", "limit": 24})
for candle in r.json():
    print(f"{candle['time_open']}: O={candle['open']} H={candle['high']} L={candle['low']} C={candle['close']}")
```

OHLCV params: `start` (required, defines window start; data returned is after this timestamp; a relative offset such as `-24h` or `-7d`, Unix seconds, RFC3339 or `yyyy-mm-dd`), `end` (same formats), `limit` (default 10, max 1000), `interval` (`1m`|`5m`|`10m`|`15m`|`30m`|`1h`|`6h`|`12h`|`24h`), `inversed` (boolean, inverts the price ratio; use `true` to get USD-denominated prices from stablecoin-paired pools like USDC/WETH).

**OHLCV units:** `open`, `high`, `low`, `close` are the price ratio between the pool's two tokens (e.g., USDC per WETH). For USD prices from stablecoin pairs, set `inversed=true`. `volume` is in the base token amount.

### Python: token OHLCV across every pool (Dev or Pro)

```python
import os, requests

r = requests.get("https://api-pro.dexpaprika.com/networks/ethereum/tokens/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2/ohlcv",
    headers={"Authorization": os.environ["DEXPAPRIKA_API_KEY"]},
    params={"start": "-24h", "interval": "1h", "limit": 24})
```

Prices are USD, volume-weighted across every pool the token trades in on the network, and `volume` is the USD traded across all of them. Same `start`, `end`, `interval` and `limit` as pool OHLCV, no `inversed`. Needs a Dev, Pro or Enterprise key on `https://api-pro.dexpaprika.com`; keyless and free keys get `403` with `"error": "plan_required"` (see Troubleshooting), so fall back to pool OHLCV on the token's busiest pool. Reference: https://docs.dexpaprika.com/api-reference/tokens/get-ohlcv-data-for-a-token

### Top pools, or filter by volume, liquidity, price, or DEX

Listing top pools and filtered slices both go through the same search endpoint:

- `GET /networks/{network}/pools/search` for one network, `GET /pools/search` across all networks.

```python
r = requests.get("https://api.dexpaprika.com/networks/ethereum/pools/search", params={
    "order_by": "volume_usd_24h",
    "sort": "desc",
    "limit": 10,
})
data = r.json()  # {"results": [...], "has_next_page": bool, "next_cursor": "..."}
for pool in data["results"]:
    print(pool["dex_name"], pool["volume_usd_24h"])
```

Sort fields use 24h-suffixed names: `volume_usd_24h`, `liquidity_usd`, `txns_24h`, `price_change_percentage_24h` (legacy names like `volume_usd` return HTTP 400 here). Every range filter has both bounds. `volume_usd_24h_min` and `volume_usd_24h_max` both bind, and so do the `_min`/`_max` pairs for `volume_usd_7d`, `volume_usd_30d`, `liquidity_usd`, `txns_24h`, `price_usd` and `price_change_percentage_24h`. `/tokens/search` adds `fdv_usd_min` and `fdv_usd_max`; on `/pools/search` the FDV pair is silently ignored, and the shorter spellings `fdv_min` and `volume_24h_min` are ignored everywhere. `created_after` and `created_before` take a relative offset such as `-24h`, Unix seconds, RFC3339 or `YYYY-MM-DD`, both bounds inclusive; `created_after=-24h` is what was created in the last day. A name the API does not know is dropped without error and you get default ordering that looks like it worked, so read the `query` object the response echoes back: it lists exactly the parameters the server parsed, and a filter missing from it was thrown away. Full parameter list: <https://docs.dexpaprika.com/api-reference/pools>.

Each row's `tokens[]` entries carry only `id`, `chain` and `has_image`, not `symbol` or `name`. Look symbols up per address, or use `/search` when you need them inline.

To list pools containing a specific token, add `token_address={address}`: it restricts results to pools containing that token, but only on the network-scoped endpoint (the cross-network `/pools/search` accepts `token_address` and silently ignores it). An unknown address returns HTTP 200 with an empty `results` array, not an error.

Token discovery works the same way via `GET /networks/{network}/tokens/search` (top tokens, or filter by volume/liquidity/FDV). Note its rows identify tokens by `address` and carry `fdv_usd`/`txns_24h`, but no `symbol`/`name`; look up details per address if you need them.

### Pagination

Two models, depending on the endpoint:

- **Search endpoints** (`/pools/search`, `/tokens/search`): cursor-based. Read `next_cursor` from the response and pass it back as `?cursor=...` while `has_next_page` is true. No `page` param.
- **Other list endpoints** (`/networks/{network}/dexes`): page-based, `?page=1&limit=10&order_by=volume_usd&sort=desc` (pages are 1-indexed). Pools on one DEX are no longer one of these: `/networks/{network}/dexes/{dex}/pools` was removed and returns HTTP 410, so use `/pools/search?dex_name={dex_id}`, which is cursor-based and returns rows under `results` with `volume_usd_24h`.

Note: Results may be fewer than `limit` if fewer items exist.

### Streaming (real-time prices + pool reserves)

For live SSE streams of token prices (`/sse/prices`) or pool reserve updates (`/sse/reserves`), see the streaming skill: `https://agents.dexpaprika.com/streaming/skill.md`

---

## Common Token Addresses

Don't guess. Use `search` to find tokens, or use these:

| Token | Chain    | Address                                        |
| ----- | -------- | ---------------------------------------------- |
| WETH  | ethereum | `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2`   |
| USDC  | ethereum | `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48`   |
| USDC  | polygon  | `0x2791bca1f2de4661ed88a30c99a7a9449aa84174`   |
| USDC  | solana   | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |
| SOL   | solana   | `So11111111111111111111111111111111111111112`  |

## Supported Networks

Chain IDs are **lowercase**. Common: `ethereum`, `solana`, `polygon`, `arbitrum`, `base`, `optimism`, `avalanche`, `bsc`. Full list: `GET /networks` or `dexpaprika-cli networks`.

## Troubleshooting

- **Check API health:** `dexpaprika-cli status` or `GET https://api.dexpaprika.com/stats`
- **HTTP status:** `200` OK | `400` bad params | `404` not found | `410` endpoint removed (the body names its replacement) | `500` server error
- **Refusals.** The JSON body carries `error`, `tier` and `links` (`register`, `pricing`, `docs`). Read `error` and act on it:

| Status and `error` | What it means | What to do |
| ------------------ | ------------- | ---------- |
| `429` `rate_limited` | Too many requests this minute. | Wait the seconds in the `Retry-After` header (also `retry_after` in the body) before the next call, and lower your request rate. Do not retry in a tight loop. If it keeps happening, tell the user that a free key or a paid plan raises the per-minute limit. |
| `402` `payment_required` | The credit allowance is spent. Waiting a minute will not help. | Stop and tell the user. Keyless: register a free key. Free key: upgrade the plan. Dev or Pro: enable overage in the console. |
| `403` `plan_required` | The endpoint needs a Dev, Pro or Enterprise plan (`required_tier` says which). Not retryable, and it costs no credits. | Tell the user what it needs. After they upgrade, call it on `https://api-pro.dexpaprika.com` with the key in `Authorization`. Until then, use pool OHLCV or pool details. |
| `403` `wrong_host` | A free key reached `api-pro` or `streaming-pro`, which serve paid plans only. | Use `https://api.dexpaprika.com`. |
| `403` HTML page, "Sorry, you have been blocked" | A request reached `api-pro` without a usable `Authorization` header. | Send the key, starting with `api_`, as the whole header value. |
| `401` `unauthorized` | The key is not one we recognise. | Copy it again from <https://console.dexpaprika.com>. |

- **This skill doesn't cover your use case?** Fetch the full docs at <https://docs.dexpaprika.com>
- **Still stuck?** Contact support@coinpaprika.com
