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

# Read Balances and Positions

> Read what a product account holds and how it has performed: token balances with transfer history, open positions and PnL.

Each product has two read endpoints for its account. Both take the user's wallet address as `owner`, so you never need to store the account address, and neither needs a signature.

* **`balances`** lists every token the account holds or has held, with raw and formatted amounts, USD value and transfer history. Use it for balance screens and activity feeds, and to see how much is ready to withdraw.
* **`positions`** lists what the account has put to work (vault deposits, loans, tokenized assets), valued in USD with PnL. Use it for portfolio screens.

| Product | Balances | Positions |
| - | - | - |
| Earn | [`GET /v2/earn/balances`](/v2/api-reference/earn/get-token-balances) | [`GET /v2/earn/positions`](/v2/api-reference/earn/list-earn-positions) |
| Credit | [`GET /v2/credit/balances`](/v2/api-reference/credit/get-credit-account-token-balances) | [`GET /v2/credit/positions`](/v2/api-reference/credit/list-credit-positions) |
| Tokenized Assets | [`GET /v2/tokenized_assets/balances`](/v2/api-reference/tokenized-assets/get-token-balances) | [`GET /v2/tokenized_assets/positions`](/v2/api-reference/tokenized-assets/list-positions) |

Two more views build on these: [`GET /v2/earn/positions_all`](/v2/api-reference/earn/list-earn-positions-across-all-chains) returns Earn positions on Ethereum, Base, Arbitrum and HyperEVM in one call, and [`GET /v2/credit/looped_positions`](/v2/api-reference/credit/list-looped-leveraged-credit-positions) groups leveraged loops into whole positions. Perpetual Trading has its own [`positions`](/v2/api-reference/perpetual-trading/list-perpetual-trading-positions) endpoint for the user's Hyperliquid account. It returns the open positions plus `account_value` and `withdrawable`, the USDC the user can take out, so it doubles as the balance read.

## Balances

<CodeGroup>
  ```python Python theme={"system"}
  import httpx

  response = httpx.get(
      "https://api.compasslabs.ai/v2/earn/balances",
      params={"chain": "base", "owner": "0xYourWalletAddress"},
      headers={"x-api-key": "YOUR_API_KEY"},
  )
  balances = response.json()

  usdc = balances["balances"].get("USDC", {}).get("balance_formatted", "0")  # e.g. "25.318402"
  ```

  ```typescript TypeScript theme={"system"}
  const params = new URLSearchParams({ chain: "base", owner: "0xYourWalletAddress" });
  const response = await fetch(
    `https://api.compasslabs.ai/v2/earn/balances?${params}`,
    { headers: { "x-api-key": "YOUR_API_KEY" } }
  );
  const balances = await response.json();

  const usdc = balances.balances.USDC?.balance_formatted ?? "0"; // e.g. "25.318402"
  ```
</CodeGroup>

The response, shortened to one token and one transfer:

```json theme={"system"}
{
  "earn_account_address": "0xYourEarnAccountAddress",
  "balances": {
    "USDC": {
      "token_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "token_symbol": "USDC",
      "token_decimals": 6,
      "balance": "25318402",
      "balance_formatted": "25.318402",
      "usd_value": "25.32",
      "transfers": [
        {
          "from_address": "0xYourWalletAddress",
          "to_address": "0xYourEarnAccountAddress",
          "amount": "100000000",
          "amount_formatted": "100",
          "block_number": 43830869,
          "block_timestamp": "2026-09-01T15:04:45Z",
          "transaction_hash": "0x9499...417a",
          "direction": "in"
        }
      ]
    }
  },
  "total_usd_value": "25.32"
}
```

| Field | Description |
| - | - |
| `balances` | One entry per token, keyed by symbol. |
| `balance` / `balance_formatted` | The raw on-chain amount, and the same amount in token units. |
| `usd_value` | The balance in USD, or `null` if there's no price for the token. |
| `transfers` | Every transfer in or out of the account for this token. `direction` is `in` or `out`. |
| `total_usd_value` | The sum of all priced balances. |

## Positions

<CodeGroup>
  ```python Python theme={"system"}
  response = httpx.get(
      "https://api.compasslabs.ai/v2/earn/positions",
      params={"chain": "base", "owner": "0xYourWalletAddress"},
      headers={"x-api-key": "YOUR_API_KEY"},
  )
  positions = response.json()

  for vault in positions["vaults"]:
      pnl = vault["pnl"] or {}  # null when the position can't be priced
      print(vault["vault_name"], vault["usd_value"], pnl.get("total_pnl"))
  ```

  ```typescript TypeScript theme={"system"}
  const params = new URLSearchParams({ chain: "base", owner: "0xYourWalletAddress" });
  const response = await fetch(
    `https://api.compasslabs.ai/v2/earn/positions?${params}`,
    { headers: { "x-api-key": "YOUR_API_KEY" } }
  );
  const positions = await response.json();

  for (const vault of positions.vaults) {
    console.log(vault.vault_name, vault.usd_value, vault.pnl?.total_pnl);
  }
  ```
</CodeGroup>

The response, shortened to one vault position:

```json theme={"system"}
{
  "vaults": [
    {
      "type": "VAULT",
      "vault_address": "0xVaultAddress",
      "vault_name": "Example USDC Vault",
      "underlying_symbol": "USDC",
      "underlying_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "balance": "75.41821",
      "usd_value": "75.42",
      "pnl": {
        "total_deposited": "75",
        "current_value": "75.41821",
        "unrealized_pnl": "0.41821",
        "realized_pnl": "0",
        "total_pnl": "0.41821",
        "total_pnl_percent": "0.56"
      },
      "apy_7d": "5.12",
      "apy_30d": "4.87",
      "apy_90d": "4.95"
    }
  ],
  "aave": [],
  "pendle_pt": [],
  "total_usd_value": "75.42"
}
```

Each Earn position also lists its `deposits` and `withdrawals` (Credit and Tokenized Assets positions have `events`), so you can show a full history without indexing anything yourself.

### What each product returns

| Product | `positions` returns |
| - | - |
| Earn | `vaults`, `aave` and `pendle_pt` lists. Each position has its `balance` in the underlying token, `usd_value`, APY, deposit and withdrawal history, and `pnl`. Plus `total_usd_value`. |
| Credit | `collateral_positions` and `debt_positions` with interest earned and paid, an `account_summary` with the health factor and LTV, and `borrowable_tokens` with how much more the account can borrow. Euler positions get one summary per sub-account in `euler_account_summaries`. `total_usd_value` is collateral minus debt. |
| Tokenized Assets | `positions` with each asset's balance, current price, `balance_usd` and `pnl`, plus `total_usd` and an account-level `pnl`. |
| Perpetual Trading | `positions` with size, side, entry and mark price, liquidation price, leverage, unrealized PnL and accrued funding, plus `account_value` and `withdrawable`. |

### PnL

Earn and Tokenized Assets positions carry a `pnl` object:

| Field | Meaning |
| - | - |
| `total_deposited` | Everything put into the position, over all time. |
| `current_value` | What the position is worth now. |
| `unrealized_pnl` | `current_value` minus the cost of what's still held. |
| `realized_pnl` | Profit or loss already taken out through withdrawals or sales. |
| `total_pnl` | `unrealized_pnl + realized_pnl`. |
| `total_pnl_percent` | `total_pnl / total_deposited × 100`. |

Earn reports PnL in the position's own asset: the underlying token for vaults and Aave, and SY units for Pendle PT. Tokenized Assets reports it in USD. Credit reports `interest_earned` on collateral and `interest_paid` on debt instead. See [How Yield Accrues](/v2/account-lifecycle/how-yield-accrues) for how these numbers are calculated, with a worked example.

## Good to know

* **Amounts are strings**, so they keep full precision. Parse them with a decimal library, not floats.
* **USD values can be `null`** when a token has no price. Totals only add up the priced items.
* **Symbols aren't unique on-chain.** If two tokens share a symbol, their keys become `SYMBOL (0xAddress)`. Match on `token_address` when it matters.
* **Tokenized Assets `balances` is the full ledger.** It includes tokens the account no longer holds and its USDC funding, while `positions` only lists what's still held.
* **Pick the chain.** Earn and Credit need `chain`. Tokenized Assets defaults to `ethereum`, so pass `base` or `bsc` for holdings there.

## Next

<Card title="How Yield Accrues" icon="arrow-right" href="/v2/account-lifecycle/how-yield-accrues">
  How each position earns, how PnL is calculated, and what the APY numbers mean.
</Card>
