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

# Rate limits and best practices

> DexPaprika API rate limits, pagination rules, caching strategies, and performance optimization tips for building efficient applications.

## Rate limits

| Tier                      | Monthly credits            | Requests per minute | Notes                      |
| ------------------------- | -------------------------- | ------------------- | -------------------------- |
| **Free (no key)**         | 50,000 / month per IP      | 30 / min            | No API key needed to start |
| **Free (registered key)** | 300,000 / month            | 30 / min            | Free API key, no card      |
| **Pro**                   | 5,000,000 / month included | 300 / min           | \$20 per additional 1M     |
| **Enterprise**            | Agreed per contract        | Agreed per contract | Streaming unmetered        |

Monthly credit allowances reset each billing month. When you exceed the per-minute rate, requests return HTTP 429; retry after a short pause. When the monthly allowance runs out, requests return HTTP 402.

### Requests and credits

An HTTP call is a **request**. What it spends is a **credit**. One request costs one credit, with no compute units and no per-endpoint weights: a light call and a heavy call cost the same. Credits are the customer-facing unit, and they are what [console.dexpaprika.com](https://console.dexpaprika.com), invoices and the [pricing page](https://dexpaprika.com/api/pricing) count.

Two places the distinction matters. The per-minute limit counts requests, so 30 per minute means 30 HTTP calls per minute. Batch endpoints charge one credit per item, so one HTTP call for 10 tokens is 1 request and 10 credits.

<Note>
  Need more headroom? [Pro](/api-pro/introduction) raises the monthly allowance to 5M credits with per-1M overage, and Enterprise is custom. Plans and checkout are on [pricing](https://dexpaprika.com/api/pricing).
</Note>

***

## Pagination rules

The search endpoints page with a cursor. `GET /networks/{network}/dexes` and `GET /networks/{network}/pools/{pool_address}/transactions` are the two that still page with numbers.

| Rule                       | Value                                                                           |
| -------------------------- | ------------------------------------------------------------------------------- |
| **Cursor endpoints**       | All `*/search` paths: read `has_next_page`, send `next_cursor` back as `cursor` |
| **First page**             | `page=1` (1-indexed), on the two page-based endpoints only                      |
| **Page 0 behavior**        | Silently treated as page 1                                                      |
| **Max items per page**     | 100 (via `limit` parameter)                                                     |
| **Default items per page** | Varies by endpoint (typically 10 or 50)                                         |
| **Transaction pages**      | Max 100 pages; use `cursor` for deeper history                                  |

***

## Reduce API calls

### Use batch pricing

Instead of making one request per token:

```
GET /networks/ethereum/tokens/0xc02a.../  → 1 request, 1 credit
GET /networks/ethereum/tokens/0xa0b8.../  → 1 request, 1 credit
GET /networks/ethereum/tokens/0x6b17.../  → 1 request, 1 credit
= 3 requests, 3 credits
```

Use batch pricing for up to 10 tokens at once:

```
GET /networks/ethereum/multi/prices?tokens=0xc02a...,0xa0b8...,0x6b17...
= 1 request, billed as 3 credits (one per token)
```

Batching collapses three round-trips into one HTTP call, which cuts latency, connection overhead and pressure on the 30-per-minute request limit. It does not cut your credit spend: each token in the batch bills as one credit, so 10 tokens cost 10 credits whether you fetch them one at a time or together. Batch for speed and for headroom against the per-minute limit, not to save credits.

### Use streaming for real-time data

<Tip>
  Sizing a workload before you pick a plan? [Plan your credit usage](/knowledge-base/credit-usage) has measured update rates, four worked cost models, and the point where streaming stops costing less than polling.
</Tip>

If you need live prices, don't poll the REST API in a loop. Open one streaming connection instead:

```bash theme={null}
# Polling (bad): 60 requests/minute for 1 token
while true; do curl ...; sleep 1; done

# Streaming (good): 1 connection, updates pushed only when the price moves
curl -N "https://streaming.dexpaprika.com/sse/prices?method=token_price&chain=ethereum&address=0xc02a..."
```

A single POST `/sse/prices` connection accepts up to **25 assets**. Each IP can hold **10 concurrent SSE streams**; the 11th returns `429 ip stream limit exceeded`.

Streaming is billed the same way as REST: each update delivered over the stream costs one credit. Because updates are pushed only when a swap moves the price, an idle market costs nothing, but a fast-moving one draws on your monthly allowance much as polling would. Budget for the update rate of what you subscribe to, not the number of connections.

### Cache static data

Some data changes rarely and can be cached:

| Data                                      | Cache for                                |
| ----------------------------------------- | ---------------------------------------- |
| Network list (`/networks`)                | 24 hours                                 |
| DEX list (`/networks/{n}/dexes`)          | 1 hour                                   |
| Token metadata (name, symbol, decimals)   | 24 hours                                 |
| Pool token pair info                      | 24 hours                                 |
| OHLCV historical data (completed candles) | Forever (completed candles don't change) |

Data that changes frequently and should be fetched fresh:

* Token prices
* Pool volumes and transaction counts
* Recent transactions
* Current OHLCV candle (incomplete)

### Request only what you need

* Use `limit` to control page size. Do not fetch 100 items if you need 5
* Use `order_by` and `sort` to get the most relevant results first
* Use the filter endpoint for targeted queries instead of fetching all pools and filtering client-side

***

## Handle errors gracefully

### Implement exponential backoff

When requests fail, don't retry immediately in a tight loop:

```python theme={null}
import time
import requests

def fetch_with_backoff(url, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url)
        if response.status_code == 200:
            return response.json()
        if response.status_code == 429:
            wait = 2 ** attempt  # 1s, 2s, 4s
            time.sleep(wait)
            continue
        if response.status_code >= 500:
            wait = 2 ** attempt
            time.sleep(wait)
            continue
        # 400, 404, 410 -- don't retry, fix the request
        response.raise_for_status()
    raise Exception("Max retries exceeded")
```

### Don't retry client errors

* **400**: fix the request parameters
* **404**: verify the network ID and addresses
* **410**: use the replacement endpoint

Only retry on **429** (rate limit) and **500** (server error).

***

## Streaming best practices

### Validate before streaming

The streaming API rejects the entire request if any asset is invalid. Always verify tokens exist via REST first:

```python theme={null}
# Validate each token before streaming
for token in tokens:
    resp = requests.get(f"https://api.dexpaprika.com/networks/{token['chain']}/tokens/{token['address']}")
    if resp.status_code != 200:
        tokens.remove(token)  # Remove invalid tokens
```

### Use batched POST for multiple tokens

Instead of opening multiple GET connections:

```
# Bad: 3 connections for 3 tokens
GET /sse/prices?method=token_price&chain=ethereum&address=0xaaa...
GET /sse/prices?method=token_price&chain=ethereum&address=0xbbb...
GET /sse/prices?method=token_price&chain=ethereum&address=0xccc...
```

Use one POST connection:

```bash theme={null}
# Good: 1 connection for up to 25 tokens
POST /sse/prices
[
  {"chain": "ethereum", "address": "0xaaa...", "method": "token_price"},
  {"chain": "ethereum", "address": "0xbbb...", "method": "token_price"},
  {"chain": "ethereum", "address": "0xccc...", "method": "token_price"}
]
```

### Reconnect with backoff

Streaming connections can drop (network issues, server restarts). Always implement auto-reconnection:

```python theme={null}
import time

def stream_with_reconnect(url, payload, max_backoff=60):
    backoff = 1
    while True:
        try:
            resp = requests.post(url, json=payload, stream=True,
                headers={"Accept": "text/event-stream"})
            if resp.status_code != 200:
                raise Exception(f"HTTP {resp.status_code}")
            backoff = 1  # Reset on successful connection
            for line in resp.iter_lines():
                if line and line.startswith(b'data:'):
                    process_event(line)
        except Exception as e:
            print(f"Disconnected: {e}. Reconnecting in {backoff}s...")
            time.sleep(backoff)
            backoff = min(backoff * 2, max_backoff)
```

### Parse prices as decimals

The streaming `p` field is a string, not a number. Use decimal parsing to avoid floating-point precision issues:

```python theme={null}
from decimal import Decimal
price = Decimal(data['p'])  # Not float(data['p'])
```

***

## Production checklist

<AccordionGroup>
  <Accordion title="Before going to production">
    * [ ] Cache network and DEX lists
    * [ ] Use batch pricing where possible
    * [ ] Use streaming instead of polling for live prices
    * [ ] Implement exponential backoff for retries
    * [ ] Handle all HTTP status codes (200, 400, 404, 410, 429, 500)
    * [ ] Parse streaming prices as decimals, not floats
    * [ ] Validate tokens before adding to streaming connections
    * [ ] Monitor monthly credit spend in [console.dexpaprika.com](https://console.dexpaprika.com) against your tier's allowance (streaming updates included)
    * [ ] Consider Pro if approaching your monthly limit
  </Accordion>
</AccordionGroup>

### FAQs

<AccordionGroup>
  <Accordion title="Is there a per-minute rate limit?">
    Yes. The free tier allows 30 requests a minute and Pro allows 300, alongside the monthly credit allowance. Exceeding the per-minute rate returns HTTP 429; retry after a short pause.
  </Accordion>

  <Accordion title="What is the difference between a request and a credit?">
    A request is one HTTP call. A credit is what it spends. One request costs one credit on every plan, with no compute units or per-endpoint multipliers, so the two numbers match except on batch endpoints, where one request charges one credit per item.
  </Accordion>

  <Accordion title="Do streaming updates count toward my credits?">
    Yes. Each price update delivered over an SSE stream costs one credit, the same as a REST call. Updates are pushed only when a swap moves the price, so an idle subscription costs nothing, but an active one draws on your monthly allowance.
  </Accordion>

  <Accordion title="Can I increase the free tier limit?">
    Registering for a free API key raises the keyless 50,000 credits a month to 300,000. Beyond that, [Pro](/api-pro/introduction) includes 5,000,000 credits a month with per-1M overage.
  </Accordion>
</AccordionGroup>

<script type="application/ld+json">
  {JSON.stringify({
      "@context": "https://schema.org",
      "@type": "FAQPage",
      "mainEntity": [
        {"@type": "Question","name": "Is there a per-minute DexPaprika rate limit?","acceptedAnswer": {"@type": "Answer","text": "Yes. Free allows 30 requests a minute and Pro 300 a minute, alongside the monthly credit allowance. Exceeding it returns HTTP 429."}},
        {"@type": "Question","name": "What is the difference between a request and a credit?","acceptedAnswer": {"@type": "Answer","text": "A request is one HTTP call; a credit is what it spends. One request costs one credit, with no compute units. Batch endpoints charge one credit per item."}},
        {"@type": "Question","name": "Do streaming updates count toward my credits?","acceptedAnswer": {"@type": "Answer","text": "Yes. Each SSE price update costs one credit, like a REST call. Updates are pushed only when a swap moves the price."}},
        {"@type": "Question","name": "Can I increase the free tier limit?","acceptedAnswer": {"@type": "Answer","text": "Registering for a free API key raises 50,000 credits a month to 300,000. Pro includes 5,000,000 credits a month."}}
      ]
    })}
</script>
