- One address, all chains: Allium takes a
{chain, address}pair per wallet, so a multi-chain balance read means one entry per chain. Zerion returns every supported chain for an address in one call to/wallets/{address}/positions/, filterable withfilter[chain_ids]. - One call for tokens + DeFi: Collapse Allium’s
wallet/balancesandwallet/positionsinto a single/positions/?filter[positions]=no_filterresponse. - Values precomputed: Allium balances return
raw_balance(and atoken.priceyou multiply yourself). Zerion returnsquantity.floatandvalue(USD) per position, plus a portfolio breakdown by chain and type.
Endpoint parity
| Use case | Allium Realtime API | Zerion API |
|---|---|---|
| Tokens + DeFi (one call) | Two requests (wallet/balances + wallet/positions) | GET /v1/wallets/{address}/positions/?filter[positions]=no_filter |
| Token balances | POST /api/v1/developer/wallet/balances | GET /v1/wallets/{address}/positions/?filter[positions]=only_simple |
| DeFi positions | POST /api/v1/developer/wallet/positions | GET /v1/wallets/{address}/positions/?filter[positions]=only_complex |
| Transactions / activity | POST /api/v1/developer/wallet/transactions | GET /v1/wallets/{address}/transactions/ |
| Holdings PnL | POST /api/v1/developer/wallet/pnl | GET /v1/wallets/{address}/pnl |
| Net worth + 24h change | (compute from holdings) | GET /v1/wallets/{address}/portfolio |
| Net worth over time | wallet/balances/history (per-token snapshots) | GET /v1/wallets/{address}/charts/{period} |
| Token price | POST /api/v1/developer/prices | GET /v1/fungibles/by-implementation?implementation={chain}:{address} |
| Token metadata / search | tokens/list, tokens/search | GET /v1/fungibles/ |
| NFTs | (historical NFT trades) | GET /v1/wallets/{address}/nft-positions/ |
| Multiple wallets in one call | Array body (1-100 wallets) | Wallet sets (/v1/wallet-sets/...) |
| Realtime updates | Streaming | Transaction webhooks |
A note on request shape
The biggest structural change is how you address a wallet:- Allium:
POSTan array of{chain, address}objects. You pick the chain per wallet, and you can batch up to 100 wallets in one request. - Zerion:
GET /v1/wallets/{address}/...with the address in the path. One address per call, all supported chains by default, narrowed withfilter[chain_ids]. To read many wallets in one request, use the wallet sets endpoints.
[{ethereum, 0x…}, {polygon, 0x…}] for one wallet becomes a single Zerion call to that address (both chains already included), and a single Allium call across several different wallets becomes either N Zerion calls or one wallet-set call.
Token balances
Allium’swallet/balances returns one item per token with raw_balance (an integer) and a token object that carries price but no precomputed USD value. Zerion returns a JSON:API collection where each token is one entry under data[], with attributes.fungible_info for metadata, attributes.quantity.float for the decimal-adjusted amount, and attributes.value for the USD value already computed. The same endpoint accepts both EVM and Solana addresses.
Field mapping
Allium (items[].…) | Zerion (data[].attributes.…) |
|---|---|
token.info.symbol, token.info.name | fungible_info.symbol, fungible_info.name |
token.decimals | fungible_info.implementations[].decimals |
token.address (native type for gas tokens) | fungible_info.implementations[].address (null for native) |
chain | relationships.chain.data.id |
raw_balance / raw_balance_str (integer, not decimal-adjusted) | quantity.int (raw integer string). Also quantity.float (decimal number) and quantity.numeric (decimal string), so you don’t divide by 10^decimals yourself. |
token.price | price |
raw_balance / 10^decimals × token.price (compute client-side) | value (USD, precomputed) |
token.attributes.total_liquidity_usd (with with_liquidity_info=true) | No direct equivalent. Use filter[trash] for spam, and fungible_info.flags.verified for the curation signal. |
token.attributes.price_diff_pct_1d | Available per asset via /v1/fungibles/{id} → market_data.changes.percent_1d |
block_timestamp | updated_at (ISO 8601, last balance update) |
| (no equivalent) | fungible_info.icon.url (token logo, returned by default) |
Transactions
Allium’swallet/transactions returns transactions with asset_transfers[] (each tagged sent/received), a labels[] array, and an activities[] array describing what the transaction did (dex_trade, nft_trade, asset_approval, and so on). Zerion’s /transactions/ returns enriched, human-readable transactions with a single decoded operation_type, inlined transfer metadata, fees, and the dApp when Zerion recognizes it. The same endpoint accepts both EVM and Solana addresses.
Field mapping
Allium (items[].…) | Zerion (data[].attributes.…) |
|---|---|
hash | hash |
block_timestamp | mined_at (ISO 8601) / mined_at_block |
chain | relationships.chain.data.id |
labels[] (coarse tags, e.g. transfer) + activities[].type (richer DeFi actions: dex_trade, nft_trade, asset_approval, asset_bridge, …) | operation_type (trade, send, receive, approve, revoke, deposit, withdraw, mint, burn, claim, bid, delegate, revoke_delegation, execute, deploy). Zerion folds Allium’s classification into one decoded field; activities[] is empty for plain transfers, where the tag sits in labels[]. |
type (numeric EVM envelope type, e.g. 2 for EIP-1559) | No equivalent. This is the raw transaction type, not a semantic category; Zerion does not expose it. |
asset_transfers[].transfer_type (sent / received) | transfers[].direction (out / in) |
asset_transfers[].asset.type (native, evm_erc20, evm_erc721, evm_erc1155) | transfers[].fungible_info vs transfers[].nft_info |
asset_transfers[].asset.symbol, .decimals | transfers[].fungible_info.symbol, .implementations[].decimals |
asset_transfers[].amount.raw_amount / .amount | transfers[].quantity.int (raw) / .float (decimal). USD in transfers[].value. |
asset_transfers[].from_address / .to_address | transfers[].sender / transfers[].recipient |
from_address / to_address (transaction-level) | sent_from / sent_to |
fee.amount / fee.raw_amount | fee.value (USD) / fee.quantity.float |
| (no equivalent) | relationships.dapp.data.id (dApp slug, e.g. uniswap-v3, present when Zerion identifies it) |
Filter mapping
| Allium param | Zerion equivalent |
|---|---|
activity_type=dex_trade | filter[operation_types]=trade (comma-separated for multiple) |
transaction_hash=0x… | filter[hash]=0x… |
limit=100 | page[size]=100 |
cursor=<cursor> | Follow links.next from the response |
| (chain set per wallet in the body) | filter[chain_ids]=ethereum,base |
DeFi positions
Allium’swallet/positions returns typed positions, where the field set depends on position_type (LP, lending, staked, regular, perp, vault). Lending positions nest supplies[], borrows[], and collateral[]; LP positions carry token0/token1; staked positions carry staked_token and rewards_token. Zerion flattens all of this: each position is one row under /positions/?filter[positions]=only_complex, tagged with protocol, protocol_module, and position_type (including loan for borrowed assets).
Field mapping
Allium (items[].…) | Zerion (data[].attributes.…) |
|---|---|
protocol | protocol (plus relationships.dapp.data.id for the slug) |
position_type (LP, lending, staked, perp, vault) | protocol_module (lending, staked, liquidity_pool, locked, rewards, vesting, deposit, investment, yield) + position_type (deposit, loan, staked, reward, locked) |
total_value_usd | value (per row). Wallet-level totals are in /portfolio → positions_distribution_by_type. |
supplies[] / collateral[] | rows with position_type: deposit / staked |
borrows[] | rows with position_type: loan |
staked_amount, unclaimed_rewards | rows with position_type: staked / reward |
token0 / token1 (LP pair) | one row per pool token, grouped by group_id (see positions) |
health_factor | No direct equivalent. Derive from supplied vs borrowed value. |
apy, fee_tier, in_range, unclaimed_fees_* | No direct equivalent. Zerion surfaces the position’s underlying token, USD value, and protocol module. |
chain | relationships.chain.data.id |
| (no equivalent) | application_metadata.name / application_metadata.icon.url (protocol display name + logo) |
Allium returns dedicated
perp positions (size, entry/mark price, leverage, liquidation price, unrealized PnL). Zerion’s positions model is spot and DeFi-protocol oriented and does not return perpetuals as positions. If perps matter for your migration, let us know.Holdings PnL
Allium’swallet/pnl returns per-token PnL (realized_pnl, unrealized_pnl, average_cost) plus wallet totals. Zerion’s /pnl returns wallet-level PnL computed with FIFO: realized and unrealized gain, net invested, total fees, and external in/out flows.
Field mapping
Allium (items[].…) | Zerion (data.attributes.…) |
|---|---|
total_realized_pnl.amount | realized_gain |
total_unrealized_pnl.amount | unrealized_gain |
total_balance.amount | Current value via /portfolio → total.positions |
tokens[].average_cost | No wallet-summary equivalent. Per-token cost basis is reflected in net_invested / realized_cost_basis. |
tokens[].realized_pnl / .unrealized_pnl (per token) | Wallet-level realized_gain / unrealized_gain. For a per-token breakdown, filter with filter[fungible_ids] or filter[fungible_implementations]. |
min_liquidity (query) | No direct equivalent. Assets without prices are excluded automatically and reported in meta. |
| (no equivalent) | net_invested, total_fee, received_external, sent_external |
Token prices
Allium’sprices endpoint takes a batch of {token_address, chain} objects and returns the latest price with OHLC. Zerion resolves a token by its implementation and returns full asset metadata including market_data.price and recent changes.
Field mapping
Allium (items[].…) | Zerion (data.attributes.…) |
|---|---|
price | market_data.price |
open / high / low / close | No direct equivalent for the latest interval. Use the fungible chart for a price timeseries. |
timestamp | market_data.price is the live value; chart points carry timestamps. |
decimals | implementations[].decimals |
| (one request per implementation) | One implementation per call. For a list, page /v1/fungibles/ with filter[implementation_address]. |
Allium’s
prices endpoint batches up to 200 tokens per request. Zerion’s by-implementation resolves one token per call. For a batch, query /v1/fungibles/ and read market_data.price from each result, or cache the Zerion fungible_id per token and reuse it.Pagination
Replace Allium’scursor query parameter with Zerion’s links.next URL. Each Zerion response includes a fully-formed next-page link you can fetch as-is.
Realtime updates
Allium offers a streaming product for low-latency blockchain data. Zerion offers transaction webhooks: subscribe a callback URL to one or more wallets and receive a POST when any of them transact. See the wallet activity alerts recipe for a working example.Differences from Allium
Most Allium Realtime 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:- Non-EVM, non-Solana chains: Allium Realtime covers chains like Bitcoin, Stellar, NEAR, and Sui. Zerion covers EVM chains and Solana. Check the supported chains list for the ones you rely on.
- Perpetuals: Allium returns
perppositions with leverage, mark price, and liquidation price. Zerion’s positions model does not return perpetuals. - Per-token historical balance snapshots: Allium’s
wallet/balances/historyreturns point-in-time token balances. Zerion exposes wallet value over time via/charts/{period}and asset price history via the fungible chart, but not a per-token balance-at-timestamp endpoint. - OHLC price candles: Allium’s
pricesendpoint returns open/high/low/close per interval. Zerion returns live price plus a chart timeseries, not OHLC candles. - Liquidity and holder analytics: Allium exposes
total_liquidity_usdandholders_counton tokens. Zerion does not return pool liquidity or holder counts.
- Authentication: Allium uses an
X-API-KEYheader. Zerion uses HTTP Basic Auth. Get a key at dashboard.zerion.io. - Request shape: Allium endpoints are
POSTwith a JSON array of{chain, address}objects. Zerion endpoints areGET /v1/wallets/{address}/...with the address in the path. See the note above. - One address spans all chains: Allium pairs each address with one chain. Zerion returns every supported chain for an address by default, narrowed with
filter[chain_ids]. - Multiple wallets: Allium batches up to 100 wallets per call. Zerion reads one address per
/wallets/call; for batches use the wallet sets endpoints. - Values precomputed: Allium balances return
raw_balanceand atoken.price; you divide by10^decimalsand multiply. Zerion returnsquantity.floatandvalue(USD) per position. - One endpoint for tokens and DeFi: Zerion serves both wallet tokens and DeFi positions from
/positions/. Switch viafilter[positions]=only_simple(wallet only),only_complex(DeFi only), orno_filter(both). - Flattened DeFi: Allium returns typed positions with nested
supplies/borrows/collateral. Zerion returns one row per position tagged withprotocol_moduleandposition_type(includingloanfor debt). Group byrelationships.dapp.data.idto reconstruct protocols, and bygroup_idto reconstruct LP pairs. - Chain IDs: Allium and Zerion both use lowercase string chain IDs (e.g.
ethereum,solana), so most map 1:1. Confirm the longer-tail names against the full list. - Response shape: Zerion uses JSON:API. Payloads live under
data[].attributeswith related entities underdata[].relationships. - Spam filtering: Allium gates dust with
min_liquidity/with_liquidity_info. Zerion usesfilter[trash]=only_non_trash. See spam filtering for the full taxonomy. - Pagination: Allium pages with a
cursorquery parameter; Zerion returns a fully-formedlinks.nextURL you can fetch as-is. See pagination.