> ## 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 OneBalance

> A 1:1 mapping from OneBalance backend endpoints to Zerion API for wallet data, covering aggregated balances, transaction history, and asset list, with side-by-side code samples.

OneBalance's [backend services were deprecated on May 18, 2026](https://zerion.io/blog/migrating-from-onebalance-to-zerion-api/). If you've been calling OneBalance for aggregated balances, transaction history, or the asset list, Zerion API replaces the wallet data layer with normalized responses across [60+ EVM chains and Solana](/supported-blockchains).

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

What you get with Zerion:

* **Full wallet portfolio in one call:** OneBalance's `aggregated-balance` requires one request per asset (you specify `aggregatedAssetId=ob:usdc` etc.). Zerion's `/positions/` returns every token a wallet holds in a single call.
* **More chains, same shape:** Zerion covers 60+ EVM chains plus Solana versus OneBalance's 11. Solana addresses use the same `/wallets/{address}/...` paths as EVM, with the same enriched response shape.
* **Enriched transaction history and DeFi positions:** Zerion's `/transactions/` returns decoded `operation_type`, `transfers[]`, fees, and dApp metadata. DeFi positions (lending, staking, LPs) are exposed alongside wallet balances via `filter[positions]=only_complex`.

<Note>
  Zerion API is the data-layer replacement for OneBalance. For multichain execution (swaps, contract calls), pair Zerion with [Relay](https://relay.link/). For embedded wallets and smart account management, pair with [Privy](https://privy.io/) or [Turnkey](https://turnkey.com/).
</Note>

## Endpoint parity

| Use case                 | OneBalance                                                        | Zerion API                                                                                                                    |
| ------------------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Wallet portfolio total   | `GET /api/v3/balances/aggregated-balance` (one call per asset)    | [`GET /v1/wallets/{address}/portfolio`](/api-reference/wallets/get-wallet-portfolio) (one call, every asset)                  |
| Token balances           | `GET /api/v3/balances/aggregated-balance` per `aggregatedAssetId` | [`GET /v1/wallets/{address}/positions/?filter[positions]=only_simple`](/api-reference/wallets/get-wallet-fungible-positions)  |
| DeFi positions           | (not covered)                                                     | [`GET /v1/wallets/{address}/positions/?filter[positions]=only_complex`](/api-reference/wallets/get-wallet-fungible-positions) |
| Wallet + DeFi (one call) | (not covered)                                                     | [`GET /v1/wallets/{address}/positions/?filter[positions]=no_filter`](/api-reference/wallets/get-wallet-fungible-positions)    |
| Transaction history      | `GET /api/v3/status/get-tx-history`                               | [`GET /v1/wallets/{address}/transactions/`](/api-reference/wallets/get-wallet-transactions)                                   |
| Asset list               | `GET /api/assets/list`                                            | [`GET /v1/fungibles/`](/api-reference/fungibles/get-list-of-fungible-assets)                                                  |
| Realtime updates         | (polling `quote/status`)                                          | [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>

## Wallet portfolio

OneBalance returns the aggregated value of one asset across chains per request. To know a wallet's total USD value, you call `aggregated-balance` for each asset and sum the `fiatValue`. Zerion's `/portfolio` endpoint returns the total, 24h change, and breakdowns by chain and position type in one call.

<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}/portfolio?currency=usd`,
    {
      headers: {
        accept: "application/json",
        authorization: `Basic ${btoa(API_KEY + ":")}`,
      },
    }
  );
  const { data } = await res.json();
  const attrs = data.attributes;

  console.log(`Total: $${attrs.total.positions.toFixed(2)}`);
  console.log(`24h change: ${(attrs.changes.percent_1d * 100).toFixed(2)}%`);
  console.log(`By chain:`, attrs.positions_distribution_by_chain);
  ```

  ```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}/portfolio?currency=usd`,
    {
      headers: {
        accept: "application/json",
        authorization: `Basic ${btoa(API_KEY + ":")}`,
      },
    }
  );
  const { data } = await res.json();
  const attrs = data.attributes;

  console.log(`Total: $${attrs.total.positions.toFixed(2)}`);
  console.log(`24h change: ${(attrs.changes.percent_1d * 100).toFixed(2)}%`);
  console.log(`By chain:`, attrs.positions_distribution_by_chain);
  ```

  ```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}/portfolio",
      params={"currency": "usd"},
      auth=(api_key, ""),
  )
  res.raise_for_status()
  attrs = res.json()["data"]["attributes"]
  print(f"Total: ${attrs['total']['positions']:.2f}")
  print(f"24h change: {attrs['changes']['percent_1d'] * 100:.2f}%")
  print(f"By chain: {attrs['positions_distribution_by_chain']}")
  ```

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

  api_key = os.environ["ZERION_API_KEY"]
  address = "6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/portfolio",
      params={"currency": "usd"},
      auth=(api_key, ""),
  )
  res.raise_for_status()
  attrs = res.json()["data"]["attributes"]
  print(f"Total: ${attrs['total']['positions']:.2f}")
  print(f"24h change: {attrs['changes']['percent_1d'] * 100:.2f}%")
  print(f"By chain: {attrs['positions_distribution_by_chain']}")
  ```

  ```bash cURL (EVM) theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/portfolio?currency=usd"
  ```

  ```bash cURL (Solana) theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/wallets/6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH/portfolio?currency=usd"
  ```
</CodeGroup>

### Field mapping

| OneBalance (`aggregated-balance`)                                                         | Zerion (`/portfolio` → `data.attributes.…`)                                                 |
| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `totalBalance.fiatValue` (per-asset, summed client-side)                                  | `total.positions` (whole wallet, one number)                                                |
| `balanceByAggregatedAsset[].fiatValue`                                                    | Sum positions client-side from `/positions/`, or use `total.positions` for the wallet total |
| `balanceByAggregatedAsset[].individualAssetBalances[]` (per-chain breakdown of one asset) | `positions_distribution_by_chain` (per-chain breakdown of the whole wallet)                 |
| (no equivalent)                                                                           | `changes.percent_1d`, `changes.absolute_1d` (24h change)                                    |
| (no equivalent)                                                                           | `positions_distribution_by_type` (wallet vs deposited vs staked vs locked)                  |

## Token balances

OneBalance returns balances grouped by aggregated asset (e.g., "USDC across all chains"). Zerion returns one entry per token per chain via `/positions/`, with `relationships.chain.data.id` on each entry. To replicate OneBalance's per-asset aggregation, group Zerion positions client-side by `fungible_info.id` and sum `value`.

<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();

  // Per-position view (one entry per token per chain)
  for (const pos of data) {
    const { fungible_info, quantity, value } = pos.attributes;
    const chain = pos.relationships.chain.data.id;
    console.log(`${fungible_info.symbol} on ${chain}: ${quantity.float} = $${value?.toFixed(2) ?? "N/A"}`);
  }

  // OneBalance-style aggregated view: sum by fungible id
  const byAsset = {};
  for (const pos of data) {
    const id = pos.attributes.fungible_info.id;
    const symbol = pos.attributes.fungible_info.symbol;
    byAsset[id] = byAsset[id] ?? { symbol, total: 0, chains: [] };
    byAsset[id].total += pos.attributes.value ?? 0;
    byAsset[id].chains.push(pos.relationships.chain.data.id);
  }
  ```

  ```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, value } = pos.attributes;
    const chain = pos.relationships.chain.data.id;
    console.log(`${fungible_info.symbol} on ${chain}: ${quantity.float} = $${value?.toFixed(2) ?? "N/A"}`);
  }
  ```

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

  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()

  # Per-position view
  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}")

  # OneBalance-style aggregated view: sum by fungible id
  by_asset = defaultdict(lambda: {"symbol": None, "total": 0.0, "chains": []})
  for pos in res.json()["data"]:
      info = pos["attributes"]["fungible_info"]
      by_asset[info["id"]]["symbol"] = info["symbol"]
      by_asset[info["id"]]["total"] += pos["attributes"]["value"] or 0
      by_asset[info["id"]]["chains"].append(pos["relationships"]["chain"]["data"]["id"])
  ```

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

  api_key = os.environ["ZERION_API_KEY"]
  address = "6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/positions/",
      params={
          "currency": "usd",
          "filter[chain_ids]": "solana",
          "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

| OneBalance (`balanceByAggregatedAsset[].…`)                                 | Zerion (`data[].attributes.…`)                                                                |
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `aggregatedAssetId` (`"ob:usdc"`)                                           | `fungible_info.id` (Zerion-specific fungible ID; one per token across chains)                 |
| `balance` (raw, summed across chains)                                       | Sum `quantity.int` across positions with the same `fungible_info.id`                          |
| `fiatValue` (USD value, summed)                                             | Sum `value` across positions with the same `fungible_info.id`                                 |
| `individualAssetBalances[].assetType` (CAIP, e.g. `eip155:1/erc20:0xa0b8…`) | `relationships.chain.data.id` + `fungible_info.implementations[].address`                     |
| `individualAssetBalances[].balance` (per chain, raw)                        | `quantity.int` on the matching position                                                       |
| `individualAssetBalances[].fiatValue` (per chain, USD)                      | `value` on the matching position                                                              |
| `accounts.evm` / `accounts.solana` (CAIP account format)                    | Zerion takes plain addresses (`0x…` or base58 Solana) on the same `/wallets/{address}/…` path |

## Transaction history

OneBalance's `get-tx-history` returns transactions performed through the OneBalance system (smart-account operations). Zerion's `/transactions/` returns enriched, decoded wallet history with `operation_type`, `transfers[]`, fees, and dApp metadata for any address, on every supported chain.

<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) ?? "?"}`);
  }
  ```

  ```javascript JavaScript (Solana) theme={null}
  const API_KEY = process.env.ZERION_API_KEY;
  const address = "6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH";
  const headers = {
    accept: "application/json",
    authorization: `Basic ${btoa(API_KEY + ":")}`,
  };

  const res = await fetch(
    `https://api.zerion.io/v1/wallets/${address}/transactions/?currency=usd&filter[chain_ids]=solana&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}")
  ```

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

  api_key = os.environ["ZERION_API_KEY"]
  address = "6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH"

  res = requests.get(
      f"https://api.zerion.io/v1/wallets/{address}/transactions/",
      params={"currency": "usd", "filter[chain_ids]": "solana", "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

OneBalance's `get-tx-history` is scoped to OneBalance-system operations and surfaces quote-level metadata. Zerion's `/transactions/` is a wallet-level, decoded activity feed. The shape differs more than for balances; map at the concept level.

| OneBalance concept                       | Zerion (`data[].attributes.…`)                                                                                                |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Transaction id / hash                    | `hash`                                                                                                                        |
| Block timestamp                          | `mined_at` (ISO 8601) / `mined_at_block`                                                                                      |
| Originating chain                        | `relationships.chain.data.id` (string IDs, e.g. `"ethereum"`)                                                                 |
| Operation kind (transfer / swap / call)  | `operation_type` (`send`, `receive`, `trade`, `approve`, `deposit`, `withdraw`, `mint`, `burn`, `claim`, `execute`, `deploy`) |
| Token movements (per-leg amount + USD)   | `transfers[]` with `direction`, `quantity.int`, `value`, `fungible_info`, `sender`, `recipient`                               |
| Gas / fee paid                           | `fee.value` (USD), `fee.fungible_info`                                                                                        |
| (no OneBalance equivalent)               | `relationships.dapp.data.id` (dApp slug when Zerion recognizes the protocol)                                                  |
| Quote status (`PENDING`, `CONFIRMED`, …) | `status` (`confirmed`, `pending`, `failed`)                                                                                   |

## Asset list

OneBalance's `/api/assets/list` returns its catalog of aggregated assets (each `ob:*` ID groups one logical token across chains). Zerion's `/v1/fungibles/` is the equivalent token catalog, with each fungible exposing `implementations[]` per chain.

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

  const res = await fetch(
    `https://api.zerion.io/v1/fungibles/?filter[search_query]=usdc&page[size]=5`,
    { headers }
  );
  const { data } = await res.json();

  for (const f of data) {
    const a = f.attributes;
    console.log(`${a.symbol} (${a.name}): ${a.implementations.length} chain implementations`);
    for (const impl of a.implementations.slice(0, 3)) {
      console.log(`  ${impl.chain_id}: ${impl.address || "native"} (${impl.decimals} decimals)`);
    }
  }
  ```

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

  api_key = os.environ["ZERION_API_KEY"]

  res = requests.get(
      "https://api.zerion.io/v1/fungibles/",
      params={"filter[search_query]": "usdc", "page[size]": 5},
      auth=(api_key, ""),
  )
  for f in res.json()["data"]:
      a = f["attributes"]
      print(f"{a['symbol']} ({a['name']}): {len(a['implementations'])} chain implementations")
      for impl in a["implementations"][:3]:
          print(f"  {impl['chain_id']}: {impl.get('address') or 'native'} ({impl['decimals']} decimals)")
  ```

  ```bash cURL theme={null}
  curl -u "YOUR_API_KEY:" \
    "https://api.zerion.io/v1/fungibles/?filter[search_query]=usdc&page[size]=5"
  ```
</CodeGroup>

### Field mapping

| OneBalance (`/api/assets/list` items)                         | Zerion (`/v1/fungibles/` → `data[].attributes.…`)                            |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `aggregatedAssetId` (`"ob:usdc"`)                             | `id` on the response item; pass to `filter[fungible_ids]` on other endpoints |
| `symbol`, `name`, `decimals`                                  | `symbol`, `name`, `implementations[].decimals`                               |
| `aggregatedEntities[].assetType` (CAIP, `eip155:1/erc20:0x…`) | `implementations[].chain_id` + `implementations[].address`                   |
| `aggregatedEntities[].decimals`                               | `implementations[].decimals`                                                 |

## Pagination

OneBalance's `get-tx-history` accepts `offset` and `limit`. Zerion returns a fully-formed `links.next` URL on every paginated response. Fetch it 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;
}
```

## Differences from OneBalance

Most OneBalance data-layer use cases have a direct Zerion equivalent. A few aren't covered yet, and others behave differently. Worth a scan before you cut over.

**Not supported today:**

* **Multichain execution (swap, transfer, contract call):** OneBalance's `quote` / `prepare-call-quote` / `execute-quote` flow lets you spend an aggregated balance and bridge in one operation. Zerion is data-only. Pair Zerion with [Relay](https://relay.link/) for execution.
* **Smart account management:** `predict-address`, account deployment, and signing flows have no Zerion equivalent. Pair with [Privy](https://privy.io/) or [Turnkey](https://turnkey.com/) for embedded wallets and key management.
* **Resource locks / EIP-7702 helpers:** OneBalance-specific primitives for spending aggregated balances. No Zerion equivalent; tied to OneBalance's execution layer.

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

**Worth knowing:**

* **Authentication:** OneBalance uses an `x-api-key` header. Zerion uses [HTTP Basic Auth](/authentication). Get a key at [dashboard.zerion.io](https://dashboard.zerion.io).
* **Chain coverage:** OneBalance supports 11 chains. Zerion supports 60+ EVM chains and Solana, with NFTs on EVM. See the [full list](/supported-blockchains).
* **Address format:** OneBalance accepts CAIP-style accounts (`eip155:1:0x…`, `solana:5eyk…:…`). Zerion takes plain `0x…` EVM or base58 Solana addresses on the same `/wallets/{address}/…` path.
* **Aggregation model:** OneBalance groups balances by `aggregatedAssetId` (one entry per logical token); per-chain detail is nested in `individualAssetBalances`. Zerion returns one entry per token per chain; group client-side by `fungible_info.id` if you need OneBalance-style aggregation.
* **Pagination:** OneBalance uses `offset` + `limit`. Zerion returns `links.next` as a fully-formed URL you can fetch as-is. See [pagination](/pagination-and-filtering).
* **Response shape:** Zerion uses [JSON:API](https://jsonapi.org/). Payloads live under `data[].attributes` with related entities under `data[].relationships`.
* **DeFi positions:** Zerion exposes lending, staking, and LP positions via `filter[positions]=only_complex` on the same `/positions/` endpoint. OneBalance does not surface DeFi positions in its data API.
* **Realtime updates:** OneBalance offers polling (`get-quote-status`). Zerion offers [transaction webhooks](/webhooks) for push notifications on wallet activity.

## 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).
