> ## Documentation Index
> Fetch the complete documentation index at: https://developers.zerion.io/llms.txt
> Use this file to discover all available pages before exploring further.

# From Allium

> Map Allium Realtime Developer APIs to Zerion API endpoints for token balances, transactions, DeFi positions, PnL, and prices, with code samples.

If you've been calling Allium's [Realtime APIs](https://docs.allium.so/api/developer/overview) for wallet balances, transactions, DeFi positions, PnL, or token prices, the same data is available on Zerion API across [60+ EVM chains and Solana](/supported-blockchains), usually in a single call and with USD values precomputed.

This guide shows the direct mapping for the main Allium Realtime endpoints, with copy-pasteable code for each.

What you get with Zerion:

* **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 with `filter[chain_ids]`.
* **One call for tokens + DeFi:** Collapse Allium's `wallet/balances` and `wallet/positions` into a single `/positions/?filter[positions]=no_filter` response.
* **Values precomputed:** Allium balances return `raw_balance` (and a `token.price` you multiply yourself). Zerion returns `quantity.float` and `value` (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`](/api-reference/wallets/get-wallet-fungible-positions)              |
| Token balances               | `POST /api/v1/developer/wallet/balances`              | [`GET /v1/wallets/{address}/positions/?filter[positions]=only_simple`](/api-reference/wallets/get-wallet-fungible-positions)            |
| DeFi positions               | `POST /api/v1/developer/wallet/positions`             | [`GET /v1/wallets/{address}/positions/?filter[positions]=only_complex`](/api-reference/wallets/get-wallet-fungible-positions)           |
| Transactions / activity      | `POST /api/v1/developer/wallet/transactions`          | [`GET /v1/wallets/{address}/transactions/`](/api-reference/wallets/get-wallet-transactions)                                             |
| Holdings PnL                 | `POST /api/v1/developer/wallet/pnl`                   | [`GET /v1/wallets/{address}/pnl`](/api-reference/wallets/get-wallet-pnl)                                                                |
| Net worth + 24h change       | (compute from holdings)                               | [`GET /v1/wallets/{address}/portfolio`](/api-reference/wallets/get-wallet-portfolio)                                                    |
| Net worth over time          | `wallet/balances/history` (per-token snapshots)       | [`GET /v1/wallets/{address}/charts/{period}`](/api-reference/wallets/get-wallet-balance-chart)                                          |
| Token price                  | `POST /api/v1/developer/prices`                       | [`GET /v1/fungibles/by-implementation?implementation={chain}:{address}`](/api-reference/fungibles/get-fungible-asset-by-implementation) |
| Token metadata / search      | `tokens/list`, `tokens/search`                        | [`GET /v1/fungibles/`](/api-reference/fungibles/get-list-of-fungible-assets)                                                            |
| NFTs                         | (historical NFT trades)                               | [`GET /v1/wallets/{address}/nft-positions/`](/api-reference/wallets/get-wallet-nft-positions)                                           |
| Multiple wallets in one call | Array body (1-100 wallets)                            | [Wallet sets](/api-reference/wallet-sets/get-wallet-set-fungible-positions) (`/v1/wallet-sets/...`)                                     |
| Realtime updates             | Streaming                                             | [Transaction webhooks](/webhooks)                                                                                                       |

<Tip>
  Prefer not to write code? The [Zerion CLI](/build-with-ai/zerion-cli) wraps the same endpoints with a one-shot `npx @zerion/cli init` flow, useful for quick experiments and AI agents.
</Tip>

## A note on request shape

The biggest structural change is how you address a wallet:

* **Allium:** `POST` an 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 with `filter[chain_ids]`. To read many wallets in one request, use the [wallet sets](/api-reference/wallet-sets/get-wallet-set-fungible-positions) endpoints.

So a single Allium call that fans out across `[{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's `wallet/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](https://jsonapi.org/) 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.

<CodeGroup>
  ```javascript JavaScript (EVM) theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";

  const res = await fetch(
    `https://api.zerion.io/v1/wallets/${address}/positions/?currency=usd&filter[positions]=only_simple&filter[trash]=only_non_trash&sort=-value`,
    {
      headers: {
        accept: "application/json",
        authorization: `Basic ${btoa(API_KEY + ":")}`,
      },
    }
  );
  const { data } = await res.json();

  for (const pos of data) {
    const { fungible_info, quantity, price, value } = pos.attributes;
    const chain = pos.relationships.chain.data.id;
    console.log(`${fungible_info.symbol} on ${chain}: ${quantity.float} @ $${price} = $${value?.toFixed(2) ?? "N/A"}`);
  }
  ```

  ```javascript JavaScript (Solana) theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const address = "6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH";

  const res = await fetch(
    `https://api.zerion.io/v1/wallets/${address}/positions/?currency=usd&filter[chain_ids]=solana&filter[trash]=only_non_trash&sort=-value`,
    {
      headers: {
        accept: "application/json",
        authorization: `Basic ${btoa(API_KEY + ":")}`,
      },
    }
  );
  const { data } = await res.json();

  for (const pos of data) {
    const { fungible_info, quantity, price, value } = pos.attributes;
    const chain = pos.relationships.chain.data.id;
    console.log(`${fungible_info.symbol} on ${chain}: ${quantity.float} @ $${price} = $${value?.toFixed(2) ?? "N/A"}`);
  }
  ```

  ```python Python (EVM) theme={null}
  import os, requests

  api_key = os.environ["ZERION_API_KEY"]
  address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/positions/",
      params={
          "currency": "usd",
          "filter[positions]": "only_simple",
          "filter[trash]": "only_non_trash",
          "sort": "-value",
      },
      auth=(api_key, ""),
  )
  res.raise_for_status()

  for pos in res.json()["data"]:
      info = pos["attributes"]["fungible_info"]
      qty = pos["attributes"]["quantity"]["float"]
      value = pos["attributes"]["value"]
      chain = pos["relationships"]["chain"]["data"]["id"]
      print(f"{info['symbol']} on {chain}: {qty} = ${value:.2f}" if value else f"{info['symbol']} on {chain}: {qty}")
  ```

  ```bash cURL (EVM) theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/positions/?currency=usd&filter[positions]=only_simple&filter[trash]=only_non_trash&sort=-value"
  ```

  ```bash cURL (Solana) theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH/positions/?currency=usd&filter[chain_ids]=solana&filter[trash]=only_non_trash&sort=-value"
  ```
</CodeGroup>

### 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}`](/api-reference/fungibles/get-fungible-asset-by-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's `wallet/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/`](/api-reference/wallets/get-wallet-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.

<CodeGroup>
  ```javascript JavaScript (EVM) theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
  const headers = {
    accept: "application/json",
    authorization: `Basic ${btoa(API_KEY + ":")}`,
  };

  const res = await fetch(
    `https://api.zerion.io/v1/wallets/${address}/transactions/?currency=usd&page[size]=20`,
    { headers }
  );
  const { data } = await res.json();

  for (const tx of data) {
    const { operation_type, mined_at, transfers, fee } = tx.attributes;
    const chain = tx.relationships.chain.data.id;
    const dappId = tx.relationships.dapp?.data?.id;

    console.log(`[${mined_at}] ${operation_type} on ${chain}`);
    if (dappId) console.log(`  via ${dappId}`);
    for (const t of transfers) {
      const sign = t.direction === "out" ? "-" : "+";
      const symbol = t.fungible_info?.symbol ?? "NFT";
      console.log(`  ${sign}${t.quantity.float} ${symbol} ($${t.value?.toFixed(2) ?? "?"})`);
    }
    console.log(`  Fee: $${fee.value?.toFixed(2) ?? "?"}`);
  }
  ```

  ```python Python (EVM) theme={null}
  import os, requests

  api_key = os.environ["ZERION_API_KEY"]
  address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/transactions/",
      params={"currency": "usd", "page[size]": 20},
      auth=(api_key, ""),
  )
  for tx in res.json()["data"]:
      attrs = tx["attributes"]
      chain = tx["relationships"]["chain"]["data"]["id"]
      dapp_id = (tx["relationships"].get("dapp") or {}).get("data", {}).get("id")
      print(f"[{attrs['mined_at']}] {attrs['operation_type']} on {chain}")
      if dapp_id:
          print(f"  via {dapp_id}")
      for t in attrs["transfers"]:
          sign = "-" if t["direction"] == "out" else "+"
          symbol = (t.get("fungible_info") or {}).get("symbol", "NFT")
          val = t.get("value")
          print(f"  {sign}{t['quantity']['float']} {symbol} (${val:.2f})" if val else f"  {sign}{t['quantity']['float']} {symbol}")
  ```

  ```bash cURL (EVM) theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/transactions/?currency=usd&page[size]=20"
  ```

  ```bash cURL (Solana) theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH/transactions/?currency=usd&filter[chain_ids]=solana&page[size]=20"
  ```
</CodeGroup>

### 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's `wallet/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).

<CodeGroup>
  ```javascript JavaScript theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";

  const res = await fetch(
    `https://api.zerion.io/v1/wallets/${address}/positions/?currency=usd&filter[positions]=only_complex&sort=-value`,
    { headers: { accept: "application/json", authorization: `Basic ${btoa(API_KEY + ":")}` } }
  );
  const { data } = await res.json();

  for (const pos of data) {
    const { name, protocol, protocol_module, position_type, quantity, value } = pos.attributes;
    const chain = pos.relationships.chain.data.id;
    console.log(`[${position_type}] ${name} | ${protocol} (${protocol_module}) on ${chain}: ${quantity.float} = $${value?.toFixed(2) ?? "N/A"}`);
  }
  ```

  ```python Python theme={null}
  import os, requests

  api_key = os.environ["ZERION_API_KEY"]
  address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/positions/",
      params={"currency": "usd", "filter[positions]": "only_complex", "sort": "-value"},
      auth=(api_key, ""),
  )
  for pos in res.json()["data"]:
      a = pos["attributes"]
      chain = pos["relationships"]["chain"]["data"]["id"]
      print(f"[{a.get('position_type')}] {a['name']} | {a.get('protocol')} ({a.get('protocol_module')}) on {chain}: {a['quantity']['float']} = ${a['value'] or 0:.2f}")
  ```

  ```bash cURL theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/positions/?currency=usd&filter[positions]=only_complex&sort=-value"
  ```
</CodeGroup>

### 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`](/api-reference/wallets/get-wallet-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](/api-reference/wallets/get-wallet-fungible-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)                                                                                                    |

<Note>
  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](#get-in-touch).
</Note>

## Holdings PnL

Allium's `wallet/pnl` returns per-token PnL (`realized_pnl`, `unrealized_pnl`, `average_cost`) plus wallet totals. Zerion's [`/pnl`](/api-reference/wallets/get-wallet-pnl) returns wallet-level PnL computed with FIFO: realized and unrealized gain, net invested, total fees, and external in/out flows.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";

  const res = await fetch(
    `https://api.zerion.io/v1/wallets/${address}/pnl?currency=usd`,
    { headers: { accept: "application/json", authorization: `Basic ${btoa(API_KEY + ":")}` } }
  );
  const { data } = await res.json();
  const a = data.attributes;

  console.log(`Realized gain:   $${a.realized_gain?.toFixed(2)}`);
  console.log(`Unrealized gain: $${a.unrealized_gain?.toFixed(2)}`);
  console.log(`Net invested:    $${a.net_invested?.toFixed(2)}`);
  console.log(`Total fees:      $${a.total_fee?.toFixed(2)}`);
  ```

  ```python Python theme={null}
  import os, requests

  api_key = os.environ["ZERION_API_KEY"]
  address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/pnl",
      params={"currency": "usd"},
      auth=(api_key, ""),
  )
  a = res.json()["data"]["attributes"]
  print(f"Realized gain:   ${a['realized_gain']:.2f}")
  print(f"Unrealized gain: ${a['unrealized_gain']:.2f}")
  print(f"Net invested:    ${a['net_invested']:.2f}")
  print(f"Total fees:      ${a['total_fee']:.2f}")
  ```

  ```bash cURL theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/pnl?currency=usd"
  ```
</CodeGroup>

### 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`](/api-reference/wallets/get-wallet-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`                                                                                      |

<Tip>
  Allium's `wallet/pnl` accepts a batch of wallets and returns per-token rows. To replicate a per-token breakdown on Zerion, call `/pnl` with `filter[fungible_ids]=…`. See the [wallet PnL tracker recipe](/recipes/wallet-pnl-tracker) for a worked example.
</Tip>

## Token prices

Allium's `prices` 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.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const implementation = "ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; // USDC

  const res = await fetch(
    `https://api.zerion.io/v1/fungibles/by-implementation?implementation=${implementation}&currency=usd`,
    { headers: { accept: "application/json", authorization: `Basic ${btoa(API_KEY + ":")}` } }
  );
  const { data } = await res.json();
  const m = data.attributes.market_data;

  console.log(`${data.attributes.symbol}: $${m.price}`);
  console.log(`24h change: ${m.changes?.percent_1d?.toFixed(2)}%`);
  ```

  ```python Python theme={null}
  import os, requests

  api_key = os.environ["ZERION_API_KEY"]
  implementation = "ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"  # USDC

  res = requests.get(
      "https://api.zerion.io/v1/fungibles/by-implementation",
      params={"implementation": implementation, "currency": "usd"},
      auth=(api_key, ""),
  )
  a = res.json()["data"]["attributes"]
  m = a["market_data"]
  print(f"{a['symbol']}: ${m['price']}")
  print(f"24h change: {m['changes']['percent_1d']}%")
  ```

  ```bash cURL theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/fungibles/by-implementation?implementation=ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&currency=usd"
  ```
</CodeGroup>

### 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](/api-reference/fungibles/get-a-chart-for-a-fungible-asset) 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/`](/api-reference/fungibles/get-list-of-fungible-assets) with `filter[implementation_address]`. |

<Note>
  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/`](/api-reference/fungibles/get-list-of-fungible-assets) and read `market_data.price` from each result, or cache the Zerion `fungible_id` per token and reuse it.
</Note>

## Pagination

Replace Allium's `cursor` query parameter with Zerion's `links.next` URL. Each Zerion response includes a fully-formed next-page link you can fetch as-is.

```javascript theme={null}
async function getAll(url) {
  const all = [];
  const headers = { accept: "application/json", authorization: `Basic ${btoa(API_KEY + ":")}` };

  while (url) {
    const res = await fetch(url, { headers });
    const { data, links } = await res.json();
    all.push(...data);
    url = links?.next ?? null;
  }
  return all;
}
```

## Realtime updates

Allium offers a streaming product for low-latency blockchain data. Zerion offers [transaction webhooks](/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](/recipes/wallet-activity-alerts) 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](/supported-blockchains) for the ones you rely on.
* **Perpetuals:** Allium returns `perp` positions with leverage, mark price, and liquidation price. Zerion's positions model does not return perpetuals.
* **Per-token historical balance snapshots:** Allium's `wallet/balances/history` returns point-in-time token balances. Zerion exposes wallet value over time via [`/charts/{period}`](/api-reference/wallets/get-wallet-balance-chart) and asset price history via the [fungible chart](/api-reference/fungibles/get-a-chart-for-a-fungible-asset), but not a per-token balance-at-timestamp endpoint.
* **OHLC price candles:** Allium's `prices` endpoint 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_usd` and `holders_count` on tokens. Zerion does not return pool liquidity or holder counts.

If any of these matter for your migration, [let us know](#get-in-touch). Your feedback helps shape our roadmap.

**Worth knowing:**

* **Authentication:** Allium uses an `X-API-KEY` header. Zerion uses [HTTP Basic Auth](/authentication). Get a key at [dashboard.zerion.io](https://dashboard.zerion.io).
* **Request shape:** Allium endpoints are `POST` with a JSON array of `{chain, address}` objects. Zerion endpoints are `GET /v1/wallets/{address}/...` with the address in the path. See [the note above](#a-note-on-request-shape).
* **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](/api-reference/wallet-sets/get-wallet-set-fungible-positions) endpoints.
* **Values precomputed:** Allium balances return `raw_balance` and a `token.price`; you divide by `10^decimals` and multiply. Zerion returns `quantity.float` and `value` (USD) per position.
* **One endpoint for tokens and DeFi:** Zerion serves both wallet tokens and DeFi positions from `/positions/`. Switch via `filter[positions]=only_simple` (wallet only), `only_complex` (DeFi only), or `no_filter` (both).
* **Flattened DeFi:** Allium returns typed positions with nested `supplies`/`borrows`/`collateral`. Zerion returns one row per position tagged with `protocol_module` and `position_type` (including `loan` for debt). Group by `relationships.dapp.data.id` to reconstruct protocols, and by `group_id` to 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](/supported-blockchains).
* **Response shape:** Zerion uses [JSON:API](https://jsonapi.org/). Payloads live under `data[].attributes` with related entities under `data[].relationships`.
* **Spam filtering:** Allium gates dust with `min_liquidity` / `with_liquidity_info`. Zerion uses `filter[trash]=only_non_trash`. See [spam filtering](/spam-filtering) for the full taxonomy.
* **Pagination:** Allium pages with a `cursor` query parameter; Zerion returns a fully-formed `links.next` URL you can fetch as-is. See [pagination](/pagination-and-filtering).

## 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](https://dashboard.zerion.io), or [email us](mailto:api@zerion.io).
