- Mobula
- Codex
- Birdeye
All the same surfaces you use today, with faster, fresher data. A Mobula
integration moves with minimal relearning: auth is the same convention (raw
API key in the
Authorization header) and the credit model is aligned.Conventions that differ
| Mobula | Serialized | Why |
|---|---|---|
blockchain/chainId mixed (evm:56, solana:solana, names) | chain param, always evm:<id> or solana (solana:solana accepted on input) | one format everywhere |
HyperEVM = 999 | HyperEVM = evm:645749 (canonical EIP-155) | no invented ids |
priceUSD, marketCapUSD (USD-suffix) | priceUsd, marketCapUsd (camelCase) | consistent casing |
Missing data, often 0 or absent | null when unknown, never a fake 0 | you can trust a zero |
| Unknown params silently ignored | 400 with machine-readable error.code | fail loud |
GET {data} / batch POST {payload} wrappers | always { data, meta } | one envelope |
| Timestamps: mixed seconds/ms | always unix milliseconds, fields end in At | no guessing |
| Amounts net-of-fee (Solana) | GROSS on-chain amounts (the exact swapped value) | matches the chain exactly |
Native coin as 0xeeee…eeee | native coin = 0x0000…0000 on EVM (pool.quote.address, token/pools), So11111111111111111111111111111111111111112 on Solana; 0xeeee…eeee accepted as an alias for token addresses on input, responses use 0x0000…0000 | the chain’s own convention, no synthetic address |
Endpoint map
| Mobula | Serialized | Notes |
|---|---|---|
GET /api/2/token/details | GET /v1/token?chain=&address= | richer launchpad block (bondingProgress, graduatedAt); deployer never null when we have it |
POST /api/2/token/details (batch) | POST /v1/token (full) or POST /v1/token/price (lean) | response array in input order, per-item {error} slots |
GET /api/2/token/price | GET /v1/token/price | + marketCapUsd, liquidityUsd included |
GET /api/2/token/markets pairs | GET /v1/token/pools | rank 1 = the pool we price from, then every other market by 24h volume and liquidity |
| (no batch market definition) | GET/POST /v1/pool | the static definition of one market, or of up to 100 markets across chains in one call, one slot per market |
GET /api/2/token/ohlcv-history | GET /v1/token/ohlcv | pools optional, defaults to the best pool followed through migration; intervals 1s to 1M; quote=usd on Solana; paginate with endTime while meta.hasMore |
GET /api/2/market/details (windowed stats) | GET/POST /v1/token/stats | batch up to 25 tokens, windows shared and pools per token, one slot per token; token-wide by default, pools= to restrict; 5m, 1h, 6h, 24h by default (same on /v1/pool/data); per-window txns, buy/sell split and priceChangePct |
GET /api/2/token/trades | GET /v1/token/trades | token-wide by default (no mode=pair to unlearn); cursor + fromAt; isWash on Solana; meta.usdBasis; marketAddress is poolAddress on every row |
GET /api/2/market/query (sortBy=volume24h) | GET /v1/screener?sortBy=volume | volume is strictly by 24h USD volume; the default trending ranks by relevance (wash-penalised); marketCap, createdAt |
GET /api/2/token/holder-positions | GET /v1/token/holders | top holders with supply share |
POST /api/2/fast-search | GET /v1/search?q= | tokens + pools, cross-chain ; input is q, blockchains is chain (same CSV), sortBy keeps its name (volume24h = volume, createdAt = newest, plus order), range filters ; native coins come back as rows (0xeeee… accepted, served as 0x000…0), socials on every row |
GET /api/1/metadata | GET /v1/token/metadata | socials, icon, description, dex-paid |
GET/POST /api/2/token/price-history | POST /v1/token/sparklines | batch up to 100 tokens, 24 to 30 evenly spaced points per timeframe; timestamps: true returns dated points ({ at, value } for [timestamp, price]); native prices, quote: "usd" on Solana |
| (no batch security) | GET/POST /v1/token/security | mint/freeze authority, top-10 holder concentration, snipers/bundlers, dex-paid; batch up to 100 |
POST /api/2/pulse (views[]) | GET /v1/pulse?view=new|bonding|graduated&chains= | consistent bondingProgress with the token endpoint |
GET /api/2/wallet/positions | GET /v1/wallet/positions | entry price + realized/unrealized/total PnL; GET /v1/wallet/closed-positions is the exact complement |
GET /api/2/wallet/position (single asset; POST batch) | GET /v1/wallet/positions?tokens=<address> | same per-position fields, scoped to the requested token(s) - up to 50 per call; GET /v1/wallet/closed-positions?tokens= for the realized PnL of an exited token |
GET /api/2/wallet/trades | GET /v1/wallet/trades | multihop-deduplicated (one event per tx, token and side) |
GET /api/2/wallet/activity (swap actions) | GET /v1/wallet/swaps | one row per transaction (batch twin POST, 20 wallets): swapAssetOut is sent[0], swapAssetIn is received[0] (each with its symbol, name, decimals), swapAmountUsd is volumeUsd, swapPlatform is router (Solana); every leg of the route is listed |
GET /api/2/wallet/analysis | GET /v1/wallet/pnl | daily curve + summary (win rate); explicit usdBasis |
GET /api/2/wallet/labels | GET/POST /v1/wallet/profile | full identity graph, 7.6M+ labeled wallets, linkedWallets clusters |
GET /api/2/wallet/funding | GET/POST /v1/wallet/funding | first funder + entity tag; batch up to 100 wallets (20 on Solana), one slot per wallet |
GET /1/blockchains | GET /v1/meta/chains | includes indexing status per chain |
Streams
Same idea, cleaner protocol: onewss endpoint, auth as the first frame, then
additive subscriptions with explicit acks and per-id unsubscribe. Event
payloads reuse our REST shapes, so your parser is already written.
fast-trade maps to the trades channel and token-details/market-details
to token-updates. For bars, poll GET /v1/token/ohlcv (intervals down to
1s) or fold the live trades feed; for launchpad views, poll GET /v1/pulse.Codex is a GraphQL API (single
Not carried over: Sui/Aptos/Starknet networks, NFT queries, community notes.
If one of these blocks your migration, tell us.
POST /graphql); Serialized is REST. You trade
query composition for one-purpose endpoints with stable, documented shapes,
and the mapping is direct: every Codex query a trading app relies on has a
REST counterpart below.Conventions that differ
| Codex | Serialized | Why |
|---|---|---|
| GraphQL queries over one POST endpoint | one REST endpoint per job | cacheable GETs, no query maintenance |
networkId integers (Base 8453, Solana 1399811149) | evm:<id> and solana | self-describing ids |
Composite ids address:networkId | chain + address params | no string assembly |
| Unix seconds | unix milliseconds, At suffix (candle time stays seconds) | consistent with JS Date.now() |
| USD amounts as strings, percents as decimals (0.01 = 1%) | numbers, percents as percent values | fewer conversion mistakes |
Casing varies (priceUSD vs priceUsd, change24 vs priceChange24) | camelCase everywhere | one convention |
| Mixed pagination (offset on filters, opaque cursors elsewhere) | keyset params (beforeAt, endTime) + meta.hasMore | resumable, no drift |
Endpoint map
| Codex (GraphQL) | Serialized | Notes |
|---|---|---|
token / tokens | GET/POST /v1/token, GET /v1/token/metadata | one call returns metadata AND live pricing (Codex splits them) |
getTokenPrices (spot) | GET/POST /v1/token/price | batch twin, per-item error slots |
getBars (pair) | GET /v1/token/ohlcv?pools= | TradingView-shaped candles, 1s to 1M |
getTokenBars (token-aggregated) | GET /v1/token/ohlcv (default) | token-wide is our default, no separate query |
tokenSparklines | POST /v1/token/sparklines | batch; the interval adapts to the token’s age like pointCount does; timestamps: true returns the { timestamp, value } points as { at, value } (milliseconds) |
getTokenEvents | GET /v1/token/trades | one row per swap event on EVM (the rows of one transaction share txHash), legs aggregated per transaction and side on Solana; trader badges on every row |
getTokenEventsForMaker | GET /v1/wallet/trades | same dedup |
holders, top10HoldersPercent | GET /v1/token/holders | no plan gating |
balances (wallet) | GET /v1/wallet/positions | includes entry price + PnL per position; tokens= scopes to a token list |
detailedWalletStats, walletChart | GET /v1/wallet/pnl | daily curve + summary, explicit usdBasis |
pairMetadata, getDetailedPairStats, getDetailedTokenStats | GET /v1/token/stats, GET /v1/token/pools | windowed stats token-wide or per pool |
listPairsForToken | GET /v1/token/pools | ranked, rank 1 = the pool we price from |
filterTokens (screener/trending) | GET /v1/screener + GET /v1/pulse + GET /v1/search | ranked markets (sortBy=trending or volume), launchpad lifecycle views, and text search |
filterLaunchpads | GET /v1/pulse | per-launchpad views via chains/factories |
getNetworks, getNetworkStatus | GET /v1/meta/chains | indexing status included |
mintable/freezable on token | GET/POST /v1/token/security | tri-state, never faked; deep contract audit via Token Audit |
onTokenEventsCreated, onEventsCreatedByMaker | Streams trades channel | REST-shaped events |
onBarsUpdated / onTokenBarsUpdated | GET /v1/token/ohlcv + Streams trades | poll bars down to 1s, or fold the live trade feed |
onPriceUpdated / onPricesUpdated | Streams token-updates channel | price + mcap + liquidity together |
onFilterTokensUpdated, onLaunchpadTokenEvent | GET /v1/pulse | launchpad lifecycle views, poll at your cadence |
Birdeye is REST like us, so most of the work is renaming. The structural
differences: chain selection moves from the
Not carried over: Sui/Aptos, NFT and gainers/losers leaderboards. If one of
these blocks your migration, tell us.
x-chain header (which silently
defaults to solana) to an explicit chain param, three coexisting API
generations (v1 camelCase, v2, v3 snake_case) collapse into one consistent
surface, and flat credits replace per-endpoint Compute Units.Conventions that differ
| Birdeye | Serialized | Why |
|---|---|---|
X-API-KEY header + x-chain header (defaults to solana) | Authorization key + explicit chain param | no silent wrong-chain responses |
v1/v2/v3 generations, mixed casing (priceChange24h vs volume_24h_usd) | one camelCase surface | one convention |
{success, data} envelope, items[] + has_next/hasNext | { data, meta } + meta.hasMore | one envelope |
| Unix seconds (+ human-time duplicates) | unix milliseconds, At suffix (candle time stays seconds) | no guessing |
offset+limit capped at 10,000, seek_by_time beyond | keyset pagination natively (beforeAt, endTime) | deep history without workarounds |
| Compute Units per endpoint (3 to 120 CU) | flat credits per call | predictable billing |
Endpoint map
| Birdeye | Serialized | Notes |
|---|---|---|
GET /defi/price, GET/POST /defi/multi_price | GET/POST /v1/token/price | liquidity + mcap included by default |
GET /defi/token_overview | GET /v1/token | one call: price, mcap, FDV, liquidity, best pool, launchpad state, socials |
GET /defi/v3/token/meta-data/* | GET /v1/token/metadata | + dex-paid flag |
GET /defi/v3/token/market-data/* | GET /v1/token/price | |
GET /defi/v3/token/trade-data/* | GET /v1/token/stats?windows= | raw + organic (wash-filtered) families |
GET /defi/v3/ohlcv (+ /pair), GET /defi/history_price | GET /v1/token/ohlcv | 1s to 1M; token-wide default or pools=; quote=usd on Solana |
GET /defi/v3/pair/overview/*, GET /defi/v2/markets | GET /v1/token/pools | rank 1 = the pool we price from, then by 24h volume and liquidity |
GET /defi/txs/token, GET /defi/v3/token/txs (+ seek_by_time) | GET /v1/token/trades | one modern endpoint, keyset native, trader badges on-row |
GET /trader/txs/seek_by_time | GET /v1/wallet/trades | multihop-deduplicated |
GET /defi/v3/token/holder (Solana only) | GET /v1/token/holders | EVM and Solana |
GET /defi/token_security | GET/POST /v1/token/security | batch up to 100; deep LLM contract audit via Token Audit (sister product) |
GET /defi/token_creation_info | GET /v1/token (createdAt, deployer) | included in the detail |
GET /defi/v3/token/list, /token_trending, /v2/tokens/new_listing, /v3/token/meme/list | GET /v1/pulse | launchpad lifecycle views (new, bonding, graduated) with bonding progress |
GET /wallet/v2/current-net-worth (Solana only) | GET /v1/wallet/positions | EVM and Solana, entry price + PnL included |
POST /wallet/v2/token-balance | GET /v1/wallet/positions?tokens= | up to 50 tokens, entry price + PnL on top of the balances |
GET /wallet/v2/pnl* | GET /v1/wallet/pnl | daily curve + summary, explicit usdBasis |
POST /wallet/v2/tx-first-funded | GET /v1/wallet/funding | first funder + entity tag |
| (no equivalent) | GET/POST /v1/wallet/profile | identity graph: names, ENS/.sol, socials, 7.6M+ wallets, linked-wallet clusters |
GET /defi/v3/search | GET /v1/search | cross-chain by default ; keyword is q, sort_by / sort_type are sortBy / order |
WS SUBSCRIBE_PRICE | Streams token-updates channel | one connection for all chains, not one per chain |
WS SUBSCRIBE_TXS (+ wallet txs) | Streams trades channel | REST-shaped events |
WS SUBSCRIBE_TOKEN_NEW_LISTING | GET /v1/pulse | launchpad lifecycle views (new, bonding, graduated) |