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

# Portfolio State

> Bundle perp positions, spot balances, open orders, and account abstraction into one call

`/v2/user/portfolio-state` returns everything you need to display a trader's full account state in a single response: perp positions, spot balances, open orders, and account abstraction mode.

## When to use this

* **User profile pages** in a trading dashboard — show perp PnL, spot holdings, and open orders without chaining multiple calls
* **Copy trading dashboards** fetching the complete state of every leader you track
* **Login flows** that need to populate a user's full account in one request
* **Risk monitors** pulling a complete picture of an account in a single round-trip

Instead of making 4 separate requests to `clearinghouseState`, `spotClearinghouseState`, `openOrders`, and `userAbstraction`, you make one.

## Single user

```bash theme={null}
curl -H "x-api-key: YOUR_KEY" \
  "https://hyper.polynode.dev/v2/user/portfolio-state?user=0x711d5ee8df7f0075f5393f7c9197248e961542b1"
```

### Query parameters

| Parameter             | Type   | Required | Description                                         |
| --------------------- | ------ | -------- | --------------------------------------------------- |
| `user` (or `address`) | string | yes      | Wallet address (checksum or lowercase)              |
| `key`                 | string | no       | API key. Can also be passed via `x-api-key` header. |

### Example response

```json theme={null}
{
  "abstraction": "default",
  "openOrders": [
    {
      "coin": "BTC",
      "limitPx": "47927.0",
      "oid": 337312365621,
      "origSz": "0.00095",
      "reduceOnly": true,
      "side": "B",
      "sz": "0.00095",
      "timestamp": 1772587755752
    }
  ],
  "perp": {
    "assetPositions": [
      {
        "position": {
          "coin": "BTC",
          "entryPx": "69111.0",
          "leverage": {"type": "cross", "value": 5},
          "liquidationPx": "88027.2944556678",
          "marginUsed": "40.81055",
          "maxLeverage": 40,
          "positionValue": "204.05275",
          "cumFunding": {
            "allTime": "-0.080775",
            "sinceChange": "-0.119844",
            "sinceOpen": "-0.079252"
          }
        }
      }
    ],
    "marginSummary": {"...": "..."},
    "withdrawable": "0.0",
    "time": 1776229734000
  },
  "spot": {
    "balances": [
      {"coin": "USDC", "token": 0, "total": "125.45", "hold": "0.0"}
    ]
  }
}
```

### Response fields

| Field         | Type   | Description                                                                                                           |
| ------------- | ------ | --------------------------------------------------------------------------------------------------------------------- |
| `perp`        | object | Full clearinghouse state — positions, margin summary, withdrawable. Same shape as HyperLiquid's `clearinghouseState`. |
| `spot`        | object | Spot token balances. Same shape as `spotClearinghouseState`.                                                          |
| `openOrders`  | array  | All open resting orders across perp and spot. Same shape as `openOrders`.                                             |
| `abstraction` | string | Account abstraction mode. `"default"` for standard accounts.                                                          |

Any sub-field may be `null` if that part of the user's state is empty or the underlying query failed.

## Batch — up to 2,500 wallets per request

For copy trading platforms and multi-user dashboards, use the batch variant to pull many wallets at once.

```bash theme={null}
curl -X POST \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "users": [
      "0x711d5ee8df7f0075f5393f7c9197248e961542b1",
      "0xacd89cFCB82Ae1f843467D56b58796bb928C9E1A"
    ]
  }' \
  https://hyper.polynode.dev/v2/batch/portfolio-states
```

### Request body

| Field   | Type      | Required | Description                                                              |
| ------- | --------- | -------- | ------------------------------------------------------------------------ |
| `users` | string\[] | yes      | Wallet addresses (max 2,500 per request)                                 |
| `key`   | string    | no       | API key (optional if passed via header)                                  |
| `dry`   | boolean   | no       | If true, return stub responses for capacity testing without live queries |

### Response

Keyed by wallet address. Each value has the same shape as the single-user endpoint.

```json theme={null}
{
  "0x711d5ee8df7f0075f5393f7c9197248e961542b1": {
    "perp": {"...": "..."},
    "spot": {"...": "..."},
    "openOrders": [],
    "abstraction": "default"
  },
  "0xacd89cFCB82Ae1f843467D56b58796bb928C9E1A": {
    "perp": null,
    "spot": null,
    "openOrders": null,
    "abstraction": null
  }
}
```

### Dry-run mode

Pass `"dry": true` to get a response with the correct shape but stub values. Useful for building and testing your parser without generating real load.

```bash theme={null}
curl -X POST \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"users":["0x711d5ee8df7f0075f5393f7c9197248e961542b1"],"dry":true}' \
  https://hyper.polynode.dev/v2/batch/portfolio-states
```

Dry response:

```json theme={null}
{
  "0x711d5ee8df7f0075f5393f7c9197248e961542b1": {
    "_dry": true,
    "abstraction": null,
    "openOrders": [],
    "perp": {
      "_dry": true,
      "assetPositions": [],
      "marginSummary": {"accountValue": "0.0"}
    },
    "spot": {"_dry": true, "balances": []}
  }
}
```

### Limits

| Limit                   | Value |
| ----------------------- | ----- |
| Max wallets per request | 2,500 |
| Body size cap           | 2 MB  |

If you need more than 2,500 at a time, use [`/v2/batch/clearinghouse-states`](/rest/user-data/batch-queries) which supports up to 10,000 (perp positions only, no spot or open orders).
