> ## 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](/api-reference/introduction),
  [Networks](/api-reference/networks/get-a-list-of-available-blockchain-networks),
  [Pools](/api-reference/pools/get-a-pool-on-a-network)
</Tip>

## 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.price_usd}")
# Output: Wrapped Ether: $3245.67
```

## API Methods Reference

<Note>Parameters marked with an asterisk (\*) are required.</Note>

<ResponseField name="Networks" type="category">
  <Expandable title="methods">
    ### client.networks.list()

    **Endpoint:** [GET `/networks`](/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](/api-reference/networks/get-a-list-of-available-blockchain-networks).

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

<ResponseField name="DEXes" type="category">
  <Expandable title="methods">
    ### client.dexes.list\_by\_network(network\_id, page, limit)

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

    Gets all DEXes on a specific network.

    **Parameters:**

    * `network_id`\* - 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](/api-reference/dexes/get-a-list-of-available-dexes-on-a-network).

    ```python theme={null}
    # Get all DEXes on Ethereum
    dexes = client.dexes.list_by_network("ethereum")
    print(f"Found {len(dexes.dexes)} DEXes on Ethereum")
    ```
  </Expandable>
</ResponseField>

<ResponseField name="Pools" type="category">
  <Expandable title="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](/tutorials/pool-filtering).
    </Warning>

    **Endpoint:** [GET `/pools`](/api-reference/pools/get-top-x-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.)

    **Returns:** Paginated list of pool objects with pricing data. [Response Structure](/api-reference/pools/get-top-x-pools).

    ```python theme={null}
    # Get top 10 pools by volume
    top_pools = client.pools.list(limit=10, order_by="volume_usd", sort="desc")
    print(f"Top pool: {top_pools.pools[0].dex_name}")
    ```

    ***

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

    **Endpoint:** [GET `/networks/{network}/pools/search`](/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](/api-reference/pools/advanced-pool-filtering-on-a-specific-network).

    ```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](/tutorials/pool-filtering).
    </Warning>

    **Endpoint:** [GET `/networks/{network}/pools/search?dex_name=...`](/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.
    </Note>

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

    ```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}`](/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](/api-reference/pools/get-a-pool-on-a-network).

    ```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)

    **Endpoint:** [GET `/networks/{network}/pools/{pool_address}/transactions`](/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.

    **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

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

    ```python theme={null}
    # Get the latest 20 transactions for a pool
    transactions = client.pools.get_transactions(
        network_id="ethereum",
        pool_address="0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc",
        limit=20
    )
    from datetime import datetime
    latest_tx_time = datetime.fromtimestamp(transactions.transactions[0].block_timestamp).strftime('%Y-%m-%d %H:%M:%S')
    print(f"Latest transaction: {latest_tx_time}")
    ```

    ***

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

    **Endpoint:** [GET `/networks/{network}/pools/{pool_address}/ohlcv`](/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 (ISO date string, YYYY-MM-DD, or Unix timestamp)
    * `end` - End time (optional)
    * `limit` - Number of data points to return
    * `interval` - Time interval ('1m', '5m', '15m', '30m', '1h', '6h', '12h', '24h')
    * `inversed` - Whether to invert the price ratio (boolean)

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

    ```python theme={null}
    from datetime import datetime, timedelta

    # Get OHLCV data for the past 7 days with 1-hour intervals
    end_date = datetime.now()
    start_date = end_date - timedelta(days=7)

    ohlcv = client.pools.get_ohlcv(
        network_id="ethereum",
        pool_address="0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc",
        start=start_date.strftime("%Y-%m-%d"),
        end=end_date.strftime("%Y-%m-%d"),
        interval="1h",
        limit=168  # 24 * 7 hours
    )

    print(f"Received {len(ohlcv)} OHLCV data points")
    ```
  </Expandable>
</ResponseField>

<ResponseField name="Tokens" type="category">
  <Expandable title="methods">
    ### client.tokens.get\_details(network\_id, token\_address)

    **Endpoint:** [GET `/networks/{network}/tokens/{token_address}`](/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](/api-reference/tokens/get-a-tokens-latest-data-on-a-network).

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

    ***

    ### 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](/tutorials/pool-filtering).
    </Warning>

    **Endpoint:** [GET `/networks/{network}/pools/search?token_address=...`](/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](/api-reference/pools/advanced-pool-filtering-on-a-specific-network).

    ```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")
    ```
  </Expandable>
</ResponseField>

<ResponseField name="Search" type="category">
  <Expandable title="methods">
    ### client.search.search(query)

    **Endpoint:** [GET `/search`](/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](/api-reference/search/search-for-tokens-pools-and-dexes).

    ```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")
    ```
  </Expandable>
</ResponseField>

<ResponseField name="Utils" type="category">
  <Expandable title="methods">
    ### client.utils.get\_stats()

    **Endpoint:** [GET `/stats`](/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](/api-reference/utils/retrieve-high-level-asset-statistics).

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

    print(f"Total chains: {stats.chains}")
    print(f"Total DEXes: {stats.dexes}")
    print(f"Total pools: {stats.pools}")
    print(f"Total tokens: {stats.tokens}")
    ```
  </Expandable>
</ResponseField>

## Complete Example

<Expandable title="example">
  ```python theme={null}
  from dexpaprika_sdk import DexPaprikaClient

  def main():
      # Initialize client
      client = DexPaprikaClient()
      
      # Get Ethereum network details
      networks = client.networks.list()
      ethereum = next((n for n in networks if n.id == "ethereum"), None)
      print(f"Found {ethereum.display_name} with {ethereum.dexes_count} DEXes")
      
      # Get WETH token details
      weth = client.tokens.get_details(
          network_id="ethereum",
          token_address="0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
      )
      print(f"{weth.name} price: ${weth.price_usd}")
      
      # Find WETH/USDC pools
      pools = client.tokens.get_pools(
          network_id="ethereum",
          token_address="0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",  # WETH
          limit=5, 
          order_by="volume_usd",
          sort="desc",
          address="0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"  # USDC
      )
      
      # Show top pools
      print('Top WETH/USDC pools:')
      for pool in pools.pools:
          print(f"{pool.dex_name}: ${pool.volume_usd:,.2f} 24h volume")

  if __name__ == "__main__":
      main()
  ```
</Expandable>

## Advanced Features

### Error Handling

<Expandable title="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 on these status codes:
  # 408 (Request Timeout), 429 (Too Many Requests),
  # 500, 502, 503, 504 (Server Errors)

  # 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.RetryError as e:
      print(f"Failed after multiple retries: {e}")
  ```
</Expandable>

### Caching System

<Expandable title="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)
  ```
</Expandable>

### Pagination Helper

<Expandable title="pagination">
  ```python theme={null}
  from dexpaprika_sdk import DexPaprikaClient
  import time

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

      while True:
          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

          # Free allows 30 requests a minute, so pause 2 seconds between pages
          time.sleep(2)

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

  # Usage example
  ethereum_pools = fetch_all_pools("ethereum")
  ```
</Expandable>

### Parameter Validation

<Expandable title="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(sort="invalid_sort")
  except ValueError as e:
      print(e)  # "sort must be one of: asc, desc"
      
  try:
      # Invalid limit parameter
      client.pools.list(limit=500)
  except ValueError as e:
      print(e)  # "limit must be at most 100"
  ```
</Expandable>

### Working with Models

<Expandable title="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
  ```
</Expandable>

## Resources

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

## API Status

The DexPaprika API provides consistent data with stable endpoints. No API key is currently required to access the service. We aim to maintain backward compatibility and provide notice of any significant changes.

### FAQs

<AccordionGroup>
  <Accordion title="Do I need an API key with this SDK?">
    Not to start. Keyless requests work at 50,000 credits a month per IP, and a [free registered key](https://console.dexpaprika.com/dashboard) raises that to 300,000 with no card.
  </Accordion>

  <Accordion title="How do I find identifiers?">
    Use Coverage Checker or list Networks and query Tokens/Pools to discover addresses.
  </Accordion>

  <Accordion title="How do I get historical or transactions data?">
    Use pools/transactions endpoints with `pool_address`, `network`, and time/paging params as documented.
  </Accordion>

  <Accordion title="What about rate limiting?">
    30 requests a minute on the free tier, 300 on Pro, against a monthly allowance of 50,000 credits keyless, 300,000 with a free key, or 5,000,000 on Pro. Retry transient HTTP errors with backoff. See [rate limits](/knowledge-base/rate-limits) for how the counters work, and [Pro pricing](https://dexpaprika.com/api/pricing) for what the 5,000,000 credit tier costs.
  </Accordion>
</AccordionGroup>

<script type="application/ld+json">
  {JSON.stringify({
        "@context": "https://schema.org",
        "@type": "FAQPage",
        "mainEntity": [
          {"@type": "Question", "name": "Do I need an API key with this SDK?", "acceptedAnswer": {"@type": "Answer", "text": "Not to start. Keyless requests work at 50,000 credits a month per IP, and a free registered key raises that to 300,000 with no card."}},
          {"@type": "Question", "name": "How do I find identifiers?", "acceptedAnswer": {"@type": "Answer", "text": "Use Coverage Checker or list Networks and query Tokens/Pools to discover addresses."}},
          {"@type": "Question", "name": "How do I get historical or transactions data?", "acceptedAnswer": {"@type": "Answer", "text": "Use pools/transactions endpoints with pool_address, network, and time/paging params as documented."}},
          {"@type": "Question", "name": "What about rate limiting?", "acceptedAnswer": {"@type": "Answer", "text": "30 requests a minute on the free tier, 300 on Pro, against a monthly allowance of 50,000 credits keyless, 300,000 with a free key, or 5,000,000 on Pro. Retry transient HTTP errors with backoff."}}
         ]
    })}
</script>
