DexPaprika API — Verified Reference (2026-03-02)
Every claim in this document was verified against the live API with 72 tests, 72 pass, 0 failures.Base URLs
Pagination (applies to ALL list endpoints)
- Pages are 1-indexed.
page=0is silently treated aspage=1. - Max
limitis 100. Values >100 return HTTP 400 (rejected, not capped). - Exception:
/pools/filteruses wrapper keyresultsinstead ofpools.
Endpoints
GET /networks
Response: Flat array (no wrapper, no page_info).- 33 networks as of 2026-03-02
- Each item: 2 keys —
id(string),display_name(string) - Common IDs:
ethereum,solana,bsc,arbitrum,base,polygon,optimism,avalanche
GET /stats
Response: Flat object (no wrapper).- 4 keys:
chains,factories,pools,tokens - Key is
factories, NOTdexes— this is the DEX/factory count
GET /search?query=
Response: Object with 3 array keys.- Case-insensitive
- Empty query → 400
- Token result shape (15 keys):
- Pool result shape includes:
id,dex_id,dex_name,chain,created_at_block_number,created_at,volume_usd,transactions,price_usd,last_price_change_usd_5m(nullable),last_price_change_usd_1h(nullable),last_price_change_usd_24h(nullable),tokens(array)
has_image, added_at, price_stats, summary, or last_updated.
GET /networks//tokens/
Response: Flat object (no wrapper). Top-level keys (13 total):price_stats (4 keys):
summary (13 keys):
Price is at:
response.summary.price_usd
summary.main_pool does NOT exist. There is no main_pool field anywhere in this response.
Each time window object (8 keys, same shape for all intervals):
CRITICAL: Fields are
sells and buys (plural). NOT sell/buy (singular). The singular forms do not exist.
GET /networks//multi/prices?tokens=,
Response: Flat array (no wrapper, no page_info).- Each item: 3 keys —
chain,id,price_usd - Order is NOT guaranteed
- Max 10 tokens. 11+ returns 400 with
{"message":"max 10 tokens allowed."} - Invalid/unknown tokens are silently omitted (not an error)
- All-invalid tokens → HTTP 200 with empty array
[] - Comma-separated addresses in a single
tokensparam
GET /networks//pools
Response:{pools: [...], page_info: {...}}
Parameters:
Pool item keys (14 total):
GET /networks//pools/filter
Response:{results: [...], page_info: {...}}
Note: wrapper key is results, not pools.
Parameters:
Non-functional params (accepted but return 0 results):
volume_7d_min, volume_30d_min, liquidity_usd_min, liquidity_usd_max
All filters combine with AND logic.
Filter result item keys (7 total):
IMPORTANT field name differences from
/pools listing:
GET /networks//pools/
Response: Flat object (no wrapper). Parameters:inversed (boolean, default: false) — flips the token pair price ratio.
Top-level keys (20 total):
GET /networks//pools//ohlcv
Response: Flat array (no wrapper). Parameters:
Missing
start → 400.
Candle keys (7 total):
GET /networks//pools//transactions
Response:{transactions: [...], page_info: {...}}
Parameters:
Max 100 pages via page param. Use
cursor for deeper.
Transaction item keys (24 total):
GET /networks//tokens//pools
Response:{pools: [...], page_info: {...}}
Parameters:
GET /networks//dexes
Response:{dexes: [...], page_info: {...}}
Note: page_info exists but may show total_items: 0 (appears buggy). The limit param may be ignored — all DEXes are returned.
DEX item keys (4 total):
GET /networks//dexes//pools
Response:{pools: [...], page_info: {...}}
Same pool item shape as /networks/{network}/pools.
Streaming API
Two SSE feeds onstreaming.dexpaprika.com:
GET /sse/prices (single token)
POST /sse/prices (multiple tokens, up to 25)
GET /sse/reserves (single pool or token)
POST /sse/reserves (multiple, up to 25)
SSE event format
event:/data: orderings within a single SSE message are valid per the spec, and the server has emitted either during rollout. Parsers must buffer one message at a time (split on blank line) and dispatch on the parsed event type, not on field order.
Other event types you may receive on either feed:
Streaming constraints
- Max 25 subscriptions per POST connection. 26+ entries get rejected with HTTP 400. The two endpoints use different rejection wording:
POST /sse/prices→{"message":"too many assets, max 25 allowed"}POST /sse/reserves→{"message":"too many subscriptions"}
- Max 10 concurrent SSE streams per IP. 11th returns
429 {"message":"ip stream limit exceeded"}. - Ping interval: 15 seconds (
event: ping). Use a missing ping as a connection-liveness signal. - All assets must be valid — one invalid asset cancels the entire stream with HTTP 400.
- First reserve events on a quiet pool may take seconds-to-minutes (events arrive only on actual on-chain changes).
- Treat unknown event names as no-ops.
Streaming errors
In-stream errors arrive as SSE:
event: error + data: {"message": "..."}. Deprecations and other non-fatal notices arrive as event: warning.
Error handling (REST)
Constraints summary
Common token addresses
Key gotchas for implementers
sells/buysnotsell/buy— plural forms only in token summary time windowssummary.main_pooldoes not exist — to find a token’s best pool, query/tokens/{address}/pools?order_by=volume_usd&sort=desc&limit=1- Filter uses different field names than pool listing:
addressnotid,volume_usd_24hnotvolume_usd,txns_24hnottransactions - Filter wrapper key is
results, notpools - Stats key is
factories, notdexes - Pages are 1-indexed everywhere — page=0 is silently normalized to page=1
- Limits are enforced, not capped — limit=200 returns 400, not 100 results
- Streaming
pis a string — parse as decimal for precision, do not treat as JSON number - Streaming bare URL is 404 — only
/streampath works - Search token shape ≠ token details shape — different fields at top level
- OHLCV is the only flat-array list response — all other list endpoints wrap in
{key: [...], page_info: {...}} - DEXes endpoint
page_infois buggy — may showtotal_items: 0while returning all results - Non-functional filter params (
volume_7d_min,volume_30d_min,liquidity_usd_min,liquidity_usd_max) are accepted but always return 0 results - First streaming events may take 10-20 seconds — don’t use short timeouts