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

# Holdings

> Current on-chain token balances of a wallet, read live from the chain via Moralis. Period independent, no cost basis.

Return a wallet current on-chain token balances, read live from the blockchain through Moralis. Unlike the tracker and leaderboard, which are built from the trades CabalSpy observes, this endpoint reflects what the wallet actually holds on chain right now, including the native coin.

Because it reads raw balances from the chain, it has no cost basis and therefore no PnL. It answers one question only, what does this wallet hold at this moment.

<Tip>
  This endpoint is period independent. It may return loading true for a brief moment while the balance cache warms up, in that case simply call it again. The wallet must be tracked by CabalSpy, otherwise you get a wallet not found error.
</Tip>

## Query Parameters

<ParamField query="blockchain" type="string" required>
  Chain of the wallet. One of solana, bnb, base, eth.
</ParamField>

<ParamField query="address" type="string" required>
  The wallet address whose balances you want.
</ParamField>

<ParamField query="api_key" type="string" required>
  Your API key. Alternatively pass it as an Authorization Bearer header.
</ParamField>

## Usage Example

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.cabalspy.xyz/v1/wallets/holdings?blockchain=solana&address=7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW&api_key=YOUR_KEY"
  ```

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

  params = {
      "blockchain": "solana",
      "address": "7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW",
      "api_key": "YOUR_KEY",
  }
  r = requests.get("https://api.cabalspy.xyz/v1/wallets/holdings", params=params)
  h = r.json()["data"]["active_holdings"]

  if h["loading"]:
      print("cache warming, retry")
  else:
      for t in h["tokens"]:
          print(t["symbol"], t["amount_formatted"])
  ```

  ```javascript JavaScript theme={null}
  const p = new URLSearchParams({
    blockchain: "solana",
    address: "7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW",
    api_key: "YOUR_KEY",
  });
  const res = await fetch(`https://api.cabalspy.xyz/v1/wallets/holdings?${p}`);
  const h = (await res.json()).data.active_holdings;
  h.tokens.forEach(t => console.log(t.symbol, t.amount_formatted));
  ```
</CodeGroup>

## Response

<ResponseField name="success" type="boolean">
  True on success.
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="active_holdings" type="object">
      <Expandable title="active_holdings">
        <ResponseField name="tokens" type="array">
          <Expandable title="token">
            <ResponseField name="token_address" type="string">
              Token contract or mint address. The native coin uses a pseudo address.
            </ResponseField>

            <ResponseField name="token_name" type="string">
              Token name (may be empty).
            </ResponseField>

            <ResponseField name="symbol" type="string">
              Token symbol.
            </ResponseField>

            <ResponseField name="amount" type="string">
              Raw balance as a string in the smallest unit.
            </ResponseField>

            <ResponseField name="amount_formatted" type="string">
              Human readable balance adjusted for decimals.
            </ResponseField>

            <ResponseField name="decimals" type="integer">
              Token decimals.
            </ResponseField>

            <ResponseField name="verified_contract" type="boolean">
              Whether the token contract is verified (EVM chains).
            </ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="count" type="integer">
          Number of tokens held.
        </ResponseField>

        <ResponseField name="last_updated" type="string">
          ISO timestamp of the last balance refresh (null if unknown).
        </ResponseField>

        <ResponseField name="stale" type="boolean">
          Whether the cached balance is considered stale.
        </ResponseField>

        <ResponseField name="loading" type="boolean">
          True while the balance cache is still warming up. Call again shortly.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "active_holdings": {
        "tokens": [
          {
            "token_address": "native",
            "token_name": "Solana",
            "symbol": "SOL",
            "amount": "12480000000",
            "amount_formatted": "12.48",
            "decimals": 9,
            "verified_contract": true
          },
          {
            "token_address": "3Pkrq4MmLvDXyn1fa3sz5MekKRkZkc1iLDcz5AzWpump",
            "token_name": "invisibull",
            "symbol": "invisibull",
            "amount": "22113972037624",
            "amount_formatted": "22113972.03",
            "decimals": 6,
            "verified_contract": false
          }
        ],
        "count": 2,
        "last_updated": "2026-07-06T11:00:12Z",
        "stale": false,
        "loading": false
      }
    },
    "meta": {
      "request_id": "req_5162c7cf7f87",
      "cached": false,
      "cache_age_seconds": 0,
      "version": "1.0.0",
      "timestamp": "2026-07-06T11:01:57Z"
    }
  }
  ```

  ```json Loading theme={null}
  {
    "success": true,
    "data": {
      "active_holdings": {
        "tokens": [],
        "count": 0,
        "last_updated": null,
        "stale": false,
        "loading": true
      }
    },
    "meta": {
      "request_id": "req_9aa1917e433b",
      "cached": false,
      "cache_age_seconds": 0,
      "version": "1.0.0",
      "timestamp": "2026-07-06T11:02:10Z"
    }
  }
  ```
</ResponseExample>

## Errors

| Status | Code               | Meaning                                |
| ------ | ------------------ | -------------------------------------- |
| 400    | missing\_parameter | address is missing.                    |
| 400    | invalid\_parameter | blockchain missing or invalid.         |
| 404    | not\_found         | The wallet is not tracked by CabalSpy. |
| 401    | unauthorized       | API key missing.                       |
| 403    | forbidden          | API key invalid or credits exhausted.  |
| 429    | rate\_limited      | Rate limit exceeded.                   |
