- Every chain by default: Mobula’s wallet endpoints read a default set of “premium” chains, and reaching the rest means passing
blockchains=orfetchAllChains=true. Zerion returns every supported chain for an address in one call, narrowed withfilter[chain_ids]when you want less. - One call for tokens + DeFi: Mobula splits wallet tokens (
/1/wallet/portfolio) and DeFi positions (/2/wallet/defi-positions) across two endpoints and two response shapes. Zerion serves both from/positions/?filter[positions]=no_filter. - One response shape: Mobula’s V1 endpoints are snake_case, V2 is camelCase, and a token balance is named
token_balance,balance,transferAmount, orbaseTokenAmountdepending on which endpoint you called. Every Zerion response is the same JSON:API envelope:data[].attributeswith related entities underdata[].relationships. - Interpreted transactions: Mobula returns an
actions[]array where each entry’s fields are prefixed by itsmodel(transfer*orswap*), so you branch before you can read an amount. Zerion returns oneoperation_typeper transaction and one uniformly shapedtransfers[]array.
Endpoint parity
Mobula paths below are relative tohttps://api.mobula.io/api.
A note on chains
Chain identifiers are the first thing to change:- Mobula: V1 endpoints take chain names (
blockchains=ethereum,base,solana), V2 endpoints take prefixed IDs (chainIds=evm:1), and responses label chains with a display name ("blockchain": "BNB Smart Chain (BEP20)") or a prefixed ID ("chainId": "evm:56"). - Zerion: one identifier everywhere: a lowercase slug like
ethereum,base,binance-smart-chain,solana. Pass it asfilter[chain_ids]=ethereum,base; read it back fromrelationships.chain.data.id. See the full list.
/1/wallet/portfolio returned balances on 10 chains by default and 38 with fetchAllChains=true. Zerion queries every supported chain by default, so there’s no flag to remember and nothing to fan out.
Wallet holdings
Mobula’s/1/wallet/portfolio returns data.assets[], where each entry carries a nested asset object for metadata, a token_balance, an estimated_balance in USD, and a contracts_balances[] array with the per-chain breakdown. Zerion returns a flat JSON:API collection, one row per token per chain, with attributes.fungible_info for metadata, attributes.quantity for amounts, and attributes.value for USD. The same endpoint accepts EVM and Solana addresses.
Field mapping
price and value are null for tokens without a reliable price. Guard for null before summing or formatting.Native gas tokens come back as ordinary rows, already decimal-adjusted and priced, with
address: null in the matching fungible_info.implementations[] entry.Net worth
Mobula reports net worth astotal_wallet_balance on the portfolio response, so getting a total means fetching every asset row. Zerion’s /portfolio is a separate, small response: the total, the 24h change, a breakdown by chain, and a breakdown by position type.
Field mapping
Net worth over time
Mobula’s/1/wallet/history returns balance_history as [timestamp_ms, value] pairs. Zerion’s /charts/{period} returns the same shape with the timestamp in seconds, and the period fixes both the window and the point spacing.
cURL
Wallet activity
Mobula’s/2/wallet/activity returns one entry per transaction with an actions[] array, where each action’s fields are prefixed by its model: a transfer action uses transferAmount / transferType / transferAsset, a swap action uses swapAmountIn / swapAssetOut / swapPlatform. Zerion’s /transactions/ gives each transaction a single decoded operation_type and one uniformly shaped transfers[] array, plus fees and the dApp when Zerion recognizes the contract.
Field mapping
Filter mapping
If you’re on the older
/1/wallet/transactions, the same /transactions/ call replaces it. Its per-row fields map as follows: hash → hash, timestamp → mined_at, amount / amount_usd → transfers[].quantity.float / transfers[].value, from / to → transfers[].sender / transfers[].recipient, contract → transfers[].fungible_info.implementations[].address, tx_cost → fee.value, blockchain → relationships.chain.data.id, and asset → transfers[].fungible_info. Its type is not a 1:1 match for operation_type: buy and sell both become trade (read transfers[].direction to tell them apart), and native becomes send or receive.Trades
Mobula’s/2/wallet/trades returns DEX fills in base/quote terms: type is buy or sell, and amounts split across baseToken* and quoteToken*. Zerion models the same events as transactions with operation_type: trade, where the direction of each transfer tells you what was spent and what was received.
cURL
Mobula’s
operation, labels, id, platformFeesUSD, and mevFeesUSD have no Zerion equivalent.
Per-token PnL
Mobula’s/2/wallet/positions returns one row per token with realized and unrealized PnL, average buy and sell prices, buy/sell counts, and fees. Zerion’s /pnl returns FIFO-computed PnL across all chains; add filter[fungible_ids] or filter[fungible_implementations] and the response gains a breakdown object with the same per-token statistics.
Field mapping
DeFi positions
Mobula’s/2/wallet/defi-positions nests three levels deep: data.protocols[], each with a positions[] array, each of those holding tokens[], rewards[], and a metadata object whose fields change with the protocol category. Zerion flattens this: each position leg is one row under /positions/?filter[positions]=only_complex, tagged with protocol, protocol_module, and position_type, and grouped by group_id.
Two things to know before you map this one. Mobula’s endpoint requires a blockchains parameter, and it is marked beta. Its own docs note the response shape may change without notice. Its protocol coverage is also an allowlist: on EVM, Aave V3, Lido, Ether.Fi and EigenLayer. Zerion has no protocol allowlist and covers every chain marked DeFi in the supported chains list. On one test address the two returned 1 position and 103 respectively, so budget time to check the protocols you care about rather than assuming parity.
Field mapping
Zerion’s
/positions/ serves wallet tokens and DeFi positions. If you currently call /1/wallet/portfolio and /2/wallet/defi-positions back to back, collapse both into one Zerion call with filter[positions]=no_filter.NFTs
Mobula’s/1/wallet/nfts returns raw holdings with a token_uri you resolve yourself. Zerion’s /nft-positions/ returns resolved media, collection metadata, and floor-price valuation.
cURL
Token prices and metadata
Mobula splits this across/2/token/price (pool-derived price for one token), /1/market/data (market figures by asset name or contract), and /1/metadata (descriptive metadata). Zerion returns one fungible object carrying all three.
Field mapping
Zerion prices are aggregated rather than tied to a single pool, so Mobula’s pool-level fields from
/2/token/details (poolAddress, exchange, factory, largestPoolQuote, bonded) have no equivalent. Neither do rank, cexs[], tags[], kyc, audit, investors, and release_schedule.
Search
Mobula’s/1/search and /2/fast-search return assets, tokens, and pairs. Zerion’s fungibles list takes a filter[search_query] and returns matching assets with their market data.
cURL
pairs[], pool metadata, or launchpad fields.
Multiple wallets
Mobula aggregates an arbitrary number of addresses withwallets=addr1,addr2,…. Zerion’s wallet sets aggregate across chain types rather than across many accounts: a set takes at most one EVM address and one Solana address, and returns a combined portfolio, positions, transactions, and balance chart. For PnL, call the per-wallet /pnl endpoint for each address.
cURL
400 (duplicate address type evm at index 1). To aggregate several EVM accounts, call the per-wallet endpoints in parallel and sum client-side.
Pagination
Replace Mobula’soffset / limit (and cursorHash / cursorDirection) with Zerion’s links.next. Paginated endpoints (transactions, NFT positions, and fungibles) return a fully-formed next-page URL you can fetch as-is, so there’s no offset arithmetic and no drift when new rows land mid-scan.
/positions/ is the exception: it isn’t paginated, ignores page[size], and returns the full set in one response, so the loop below simply exits after the first page.
Realtime updates
Mobula pushes realtime data over WebSocket streams (balances, positions, trades, transfers) and manages webhook subscriptions through/1/webhook. Zerion offers two equivalents:
- Transaction webhooks: subscribe a callback URL to a list of wallets and receive a POST for every new transaction. This is the closest match to Mobula’s balance and wallet-transfer streams. See the wallet activity alerts recipe for a working example.
- Kafka streams: a continuous feed of interpreted trade and price events across chains, for indexing and analytics at high throughput. Provisioned per customer on Enterprise plans.
Differences from Mobula
Most Mobula wallet and market use cases have a direct Zerion equivalent. A few aren’t covered, and others behave differently. Worth a scan before you cut over. Not supported today:- Trading and market microstructure: Mobula’s token trades, pair trades, OHLCV candles, holder positions, top-trader positions, order books, and Pulse launchpad feeds have no Zerion equivalent. Zerion’s market data is asset-level: price, market cap, supply, volume, and charts.
- Token security and analytics signals:
/2/token/security, buy/sell taxes, holder distribution, sniper and bundler detection, andsecurityScore-style fields aren’t returned. Zerion’s curation surfaces areflags.is_trash,filter[trash], andfungible_info.flags.verified. See spam filtering. - Wallet labelling and funding sources: Mobula annotates wallets with entity names, labels, and a
fundingInfoobject tracing the first deposit. Zerion identifies dApps (relationships.dapp) but does not label wallet owners or trace funding. - Perpetuals and prediction markets: Mobula covers perps and Polymarket positions, quoting, and execution. Zerion’s positions model is spot and DeFi-protocol oriented, and does not return perps or prediction-market positions.
- Execution beyond swaps: Zerion offers swap quotes; Mobula’s perp order lifecycle, bridge intents, and Safe deployment flows have no equivalent.
- ATH / ATL and price-at-timestamp: Mobula returns
ath/atlwith dates and aprice-atsnapshot endpoint. Zerion returns live price plus a chart timeseries you can read historical values from. - DeFi yields and risk metrics: Mobula’s DeFi positions carry
supplyAPY,borrowAPY,healthFactor,ltv,liquidationThreshold, and pool APY / 24h fees. Zerion returns the position’s balance, USD value, protocol and type, but no yield or liquidation figures. - Non-EVM chains beyond Solana: Mobula indexes chains such as TON, Sui, Starknet, and Stellar. Zerion covers EVM chains and Solana. Check the supported chains list for the ones you rely on.
- Authentication: Mobula takes the API key in an
Authorization: <key>header. Zerion uses HTTP Basic Auth: the key as username, empty password. Get a key at dashboard.zerion.io. - Chain identifiers: Mobula mixes names (
ethereum), prefixed IDs (evm:1), and display labels (BNB Smart Chain (BEP20)). Zerion uses one lowercase slug everywhere. See the note above. - Flattened DeFi: Mobula nests
tokens[]andrewards[]inside each position, inside each protocol. Zerion returns one row per leg tagged withprotocol_moduleandposition_type. Group byrelationships.dapp.data.idto reconstruct protocols, and bygroup_idto reconstruct pools. - Pagination: Mobula pages with
offset/limit; Zerion returns a fully-formedlinks.nextURL on its paginated endpoints, while/positions/returns everything in one response. See pagination. - Pricing and spam: Mobula exposes
filterSpam,minliq, and per-assetliquidityso you can filter client-side. Zerion applies a liquidity gate before pricing an asset and flags junk withflags.is_trash, which you filter server-side withfilter[trash]=only_non_trash. Low-liquidity tokens that would otherwise carry an unreliable price come back withprice: nullrather than a figure that distorts a portfolio total.