Skip to main content
If you’ve been calling Mobula for wallet holdings, net worth, activity, trades, PnL, DeFi positions, NFTs, or token prices, the same data is available on Zerion API across 60+ EVM chains and Solana, usually in a single call. This guide shows the direct mapping for the main Mobula wallet and market endpoints, with copy-pasteable code for each. What you get with Zerion:
  • Every chain by default: Mobula’s wallet endpoints read a default set of “premium” chains, and reaching the rest means passing blockchains= or fetchAllChains=true. Zerion returns every supported chain for an address in one call, narrowed with filter[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, or baseTokenAmount depending on which endpoint you called. Every Zerion response is the same JSON:API envelope: data[].attributes with related entities under data[].relationships.
  • Interpreted transactions: Mobula returns an actions[] array where each entry’s fields are prefixed by its model (transfer* or swap*), so you branch before you can read an amount. Zerion returns one operation_type per transaction and one uniformly shaped transfers[] array.

Endpoint parity

Mobula paths below are relative to https://api.mobula.io/api.
Prefer not to write code? The Zerion CLI wraps the same endpoints with a one-shot npx @zerion/cli init flow, useful for quick experiments and AI agents.

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 as filter[chain_ids]=ethereum,base; read it back from relationships.chain.data.id. See the full list.
Coverage defaults also differ. Mobula’s wallet endpoints read a default premium-chain set unless you widen it: on a test address, /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 as total_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: hashhash, timestampmined_at, amount / amount_usdtransfers[].quantity.float / transfers[].value, from / totransfers[].sender / transfers[].recipient, contracttransfers[].fungible_info.implementations[].address, tx_costfee.value, blockchainrelationships.chain.data.id, and assettransfers[].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

See the wallet PnL tracker recipe for a worked example.

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

Despite the name, Mobula’s positions[].tokens[].amountRaw is not always a raw integer. On a live Aave V3 USDC supply it returned "10.019356", identical to amountFormatted, for a 6-decimal token. If you currently divide amountRaw by 10 ** decimals, re-check that logic against Zerion’s quantity.int, which is always the raw integer string (10017049 for the same position).
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. 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
Results are asset-level, not pair-level: Zerion has no equivalent to Mobula’s pairs[], pool metadata, or launchpad fields.

Multiple wallets

Mobula aggregates an arbitrary number of addresses with wallets=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
Passing two addresses of the same chain type returns 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’s offset / 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, and securityScore-style fields aren’t returned. Zerion’s curation surfaces are flags.is_trash, filter[trash], and fungible_info.flags.verified. See spam filtering.
  • Wallet labelling and funding sources: Mobula annotates wallets with entity names, labels, and a fundingInfo object 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 / atl with dates and a price-at snapshot 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.
If any of these matter for your migration, let us know. Your feedback helps shape our roadmap. Worth knowing:
  • 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[] and rewards[] inside each position, inside each protocol. Zerion returns one row per leg tagged with protocol_module and position_type. Group by relationships.dapp.data.id to reconstruct protocols, and by group_id to reconstruct pools.
  • Pagination: Mobula pages with offset / limit; Zerion returns a fully-formed links.next URL on its paginated endpoints, while /positions/ returns everything in one response. See pagination.
  • Pricing and spam: Mobula exposes filterSpam, minliq, and per-asset liquidity so you can filter client-side. Zerion applies a liquidity gate before pricing an asset and flags junk with flags.is_trash, which you filter server-side with filter[trash]=only_non_trash. Low-liquidity tokens that would otherwise carry an unreliable price come back with price: null rather than a figure that distorts a portfolio total.

Get in touch

Have a use case we don’t cover or need assistance with the migration? Our team is happy to help! Reach out via the chat widget on dashboard.zerion.io, or email us.