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

# User Positions

> Current token balances and DeFi positions for a wallet, matching the Turtle app portfolio.

<Note>
  Send your API key via the `X-API-Key` header. See [Authentication](/sdk/authentication/api-keys).
</Note>

## Overview

`GET /v2/wallet/{address}/portfolio`

Return a wallet's **current** holdings: idle ERC-20 and native balances, plus structured DeFi positions across every supported protocol (Uniswap, Aave, Euler, Morpho, Curvance, Pendle, Spark, and others). The payload matches the main Turtle API `GET /wallet/{address}/balance` — the same shape the app uses.

<Warning>
  This is a breaking change from the previous DeFi-only `{ total_stats, protocols }` response. Protocol positions now live at `portfolio.holdings.wallets[].protocols`.
</Warning>

<Info>
  This is a point-in-time snapshot. For transaction history (deposits and withdrawals over time) use [Wallet Activity](/sdk/portfolio/activity).
</Info>

## Endpoint

<CodeGroup>
  ```bash curl theme={null}
  curl -X GET "https://earn.turtle.xyz/v2/wallet/0xe84ef330b7b5c02fb3fbe05f2a31cb331c2b874c/portfolio" \
    -H "X-API-Key: pk_live_xxxxx"
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch(
    'https://earn.turtle.xyz/v2/wallet/0xe84ef330b7b5c02fb3fbe05f2a31cb331c2b874c/portfolio',
    { headers: { 'X-API-Key': 'pk_live_xxxxx' } }
  );
  const { portfolio } = await res.json();
  const wallet = portfolio.holdings.wallets[0];
  const { tokens, protocols } = wallet;
  ```
</CodeGroup>

**Path Parameters**

<ParamField path="address" type="string" required>
  EVM wallet address.
</ParamField>

**Query Parameters**

<ParamField query="includeProtocolTokens" type="boolean" default="false">
  When `false`, receipt tokens for protocols that already appear as structured DeFi positions (Aave aTokens, Morpho vault shares, and similar) are hidden from `wallets[].tokens` so they are not double-counted. Set `true` to keep them in the token list.
</ParamField>

**Response**

```json theme={null}
{
  "portfolio": {
    "productsEarnings": [],
    "holdings": {
      "totalAmountInUSD": "14.11",
      "chains": [
        {
          "name": "Ethereum",
          "slug": "ethereum",
          "chainId": "1",
          "logoUrl": "https://...",
          "ecosystem": "evm",
          "status": "active",
          "explorerUrl": "https://etherscan.io"
        }
      ],
      "wallets": [
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "address": "0xe84ef330b7b5c02fb3fbe05f2a31cb331c2b874c",
          "totalAmountInUSD": "14.11",
          "tokens": [
            {
              "id": "uuid",
              "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
              "name": "USD Coin",
              "symbol": "USDC",
              "decimals": 6,
              "isNative": false,
              "logoUrl": "https://...",
              "amount": "5.00",
              "rawAmount": "5000000",
              "price": "1.00",
              "chain": {
                "name": "Ethereum",
                "slug": "ethereum",
                "chainId": "1",
                "logoUrl": "https://...",
                "ecosystem": "evm",
                "status": "active",
                "explorerUrl": "https://etherscan.io"
              }
            }
          ],
          "protocols": [
            {
              "id": "morpho",
              "name": "Morpho",
              "site_url": "https://morpho.org",
              "logo_url": "https://...",
              "stats": { "asset_usd_value": "1.01", "debt_usd_value": "0.00", "net_usd_value": "1.01" },
              "portfolio_item_list": [
                {
                  "type": "yield",
                  "name": "Huma USDC Main",
                  "detail": {
                    "supply_token_list": [
                      { "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "chain": "1", "symbol": "USDC", "name": "USD Coin", "decimals": 6, "amount": "1.005697", "price": "1", "logo_url": "https://..." }
                    ]
                  },
                  "stats": { "asset_usd_value": "1.01", "debt_usd_value": "0.00", "net_usd_value": "1.01" },
                  "pool": { "id": "0x8ac9...", "chain": "1" }
                }
              ]
            }
          ]
        }
      ]
    }
  }
}
```

## Response Fields

<ResponseField name="portfolio.productsEarnings" type="array">
  Product earnings for an authenticated Turtle user. Always `[]` on this address-scoped Earn route.
</ResponseField>

<ResponseField name="portfolio.holdings.totalAmountInUSD" type="string">
  Net USD across token balances and DeFi positions, 2 decimal places.
</ResponseField>

<ResponseField name="portfolio.holdings.chains" type="array">
  Per-chain USD rollup derived from tokens and protocol positions. Each entry has `name`, `slug`, `chainId`, `logoUrl`, `ecosystem`, `status`, `explorerUrl`.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets" type="array">
  One entry per address. This route always returns a single wallet.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].tokens" type="array">
  Idle ERC-20 and native gas-token balances. Receipt tokens for covered DeFi protocols are omitted unless `includeProtocolTokens=true`.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].tokens[].amount" type="string">
  Human-readable balance (already divided by 10^decimals).
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].tokens[].rawAmount" type="string">
  Integer on-chain balance.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].tokens[].isNative" type="boolean">
  `true` for the chain's gas token.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].tokens[].opportunityId" type="string">
  Linked Turtle opportunity UUID when enrichment succeeds. Omitted otherwise.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols" type="array">
  Structured DeFi positions, one entry per protocol the wallet holds. Protocol groups with a negative net USD are omitted.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].id" type="string">
  Protocol slug (e.g. `morpho`, `aave3`, `euler`).
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].stats" type="object">
  Protocol-level USD totals: `asset_usd_value`, `debt_usd_value`, `net_usd_value`.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].portfolio_item_list" type="array">
  Individual positions within the protocol.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].portfolio_item_list[].type" type="string">
  Position type: `yield`, `lending`, `collateral`, or `liquidity`. Use this to pick a layout — no protocol-specific rendering is needed.
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].portfolio_item_list[].detail" type="object">
  Token lists for the position: `supply_token_list`, and where relevant `borrow_token_list` / `reward_token_list`. Each token carries `address`, `chain`, `symbol`, `name`, `decimals`, `amount`, `price`, `logo_url`. Borrow rows may include a signed `apy` (negative for variable borrow).
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].portfolio_item_list[].pool" type="object">
  Pool / vault identifier for the position: `id` (contract address) and `chain`. Omitted when there is no specific pool (e.g. aggregated Morpho Blue lending).
</ResponseField>

<ResponseField name="portfolio.holdings.wallets[].protocols[].portfolio_item_list[].account" type="object">
  On-chain risk snapshot for isolated lending markets (Aave V3, Spark): `health_factor`, `ltv`, `liquidation_threshold`, `total_collateral_base`, `total_debt_base`, `available_borrows_base`. Omitted when unavailable or when the account has no debt.
</ResponseField>

## Position types

| Type | Description | Typical data |
| - | - | - |
| `yield` | Vault deposit | `supply_token_list` (1 token) |
| `lending` | Borrow / lend | `supply_token_list` plus optional `borrow_token_list` |
| `collateral` | Collateral deposit | `supply_token_list` |
| `liquidity` | LP position | `supply_token_list` (2 tokens), optional `description` (fee tier / range) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.