token_overview is the heaviest call in the stack, and wasting it on tokens nobody selects is how a screener burns its credit budget without delivering value.
TL;DR
- Discover an already ranked starting point from the trending feed
- Bulk scan thousands of tokens per batch with server side filters
- Enrich with a full snapshot only when a user selects a token
- Batch refresh watchlist prices instead of looping single calls
https://public-api.birdeye.so, authenticate with the X-API-KEY header, and select the network with the x-chain header, for example solana, ethereum, base, bsc, or arbitrum.
The four stage pipeline
1
Discover trending tokens
Computing what is trending yourself from raw trade data is a rabbit hole. This endpoint skips all of that with an already ranked list from real onchain activity. Control the sort field and the lookback window to match your use case.Endpoint:
GET /defi/token_trendingPage size hard caps at 50 tokens, so paginate with
offset for a deeper board. For momentum focused use cases, interval=1h surfaces breakout tokens far earlier than 24h.2
Filter thousands of tokens per batch
This is where the screener’s efficiency is actually built. Instead of downloading a large token list and filtering client side, push filter logic to the server and get back only tokens that match, up to 5000 per batch with 40 plus filter parameters covering liquidity, valuation, holders, listing age, activity recency, volume, price momentum, and trade count.Endpoint:
GET /defi/v3/token/list/scrollThe scroll endpoint requires a Business or Enterprise package and covers Solana, Base, BSC, and Ethereum only. On other plans,
GET /defi/v3/token/list exposes the same filter and sort parameters with standard offset and limit pagination at up to 100 tokens per call.3
Enrich with a deep snapshot on selection
When a user selects a token, this is the one call to make. It returns price, liquidity, market cap, holder count, supply, and per timeframe metrics across up to eight windows by default.Endpoint:
GET /defi/token_overview4
Batch refresh watchlist prices
Once users build watchlists, the refresh loop should not scale linearly with watchlist size. Batch up to 100 tokens in one call instead of looping single price requests.Endpoint:
POST /defi/multi_priceWatch your credit budget
Wire this into your monitoring stack from day one, so a runaway scan does not silently burn budget on an edge case. Endpoint:GET /utils/v1/credits
Before you ship
- Trending and scroll results write to a cache, the UI reads from the cache only.
token_overviewfires only on explicit user selection, never speculatively.- Watchlist refresh always batches through
multi_price, never loops single price calls. nullresponses frommulti_priceare handled explicitly, not assumed away.- Only one worker per chain per account runs the scroll session, not one per user request.
- Credit usage is observable, so degradation is controlled instead of a surprise 429.
FAQ
Does the scroll endpoint work on all chains?
Does the scroll endpoint work on all chains?
No. Unlike most Birdeye Data endpoints,
GET /defi/v3/token/list/scroll currently covers Solana, Base, BSC, and Ethereum only. For other chains, use GET /defi/v3/token/list, which has the same filter and sort parameters with standard offset and limit pagination at up to 100 tokens per call.Can I run multiple background workers against the same API key?
Can I run multiple background workers against the same API key?
Not with the scroll endpoint. The one active scroll session limit is enforced at the account level, not the key level. If two workers open concurrent scroll sessions, the second fails. Run one worker per chain per account, writing to a shared cache that all application instances read from.
What is a reasonable refresh interval for watchlists?
What is a reasonable refresh interval for watchlists?
It depends on the use case, but 5 to 10 seconds per batch through
multi_price is a reasonable starting point for a trading terminal. Monitor credit consumption and tune from there, and avoid refreshing tokens that are not visible in the current viewport.
