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

# Perp Snapshot

> Full positioning of every active trader on HyperLiquid in one call

Returns the current clearinghouse state — positions, margin, account value, funding, and liquidation price — for every active trader on HyperLiquid in a single response. Refreshed every 2-3 seconds.

## When to use this

Reach for the snapshot endpoints when you need a point-in-time view of **every active wallet** on HyperLiquid at once:

* **Copy trading platforms** watching thousands of leader wallets simultaneously
* **Whale tracking dashboards** scanning for large positions or sudden changes
* **Leaderboards** ranking traders by account value or PnL
* **Portfolio analytics** computing aggregate leverage, open interest, or concentration across the whole market
* **Risk monitors** watching the liquidation landscape across all users

If you only need one wallet at a time, use [`/v2/user/state`](/rest/user-data/user) instead. If you need hundreds or thousands of specific wallets, use [`/v2/batch/clearinghouse-states`](/rest/user-data/batch-queries). Snapshot endpoints are the right call when you want **everyone**.

## Endpoints

| Endpoint                                  | Purpose                                                    |
| ----------------------------------------- | ---------------------------------------------------------- |
| `GET /v2/perp-snapshot/metadata`          | Tiny metadata — poll cheaply, fetch full only when fresh   |
| `GET /v2/perp-snapshot`                   | Full snapshot of every active trader's clearinghouse state |
| `GET /v2/spot-snapshot/metadata`          | Metadata for spot snapshot                                 |
| `GET /v2/spot-snapshot`                   | Spot balances for every user with non-empty spot holdings  |
| `GET /v2/account-value-snapshot/metadata` | Metadata for account value snapshot                        |
| `GET /v2/account-value-snapshot`          | accountValue and withdrawable only — small and fast        |

## Authentication

All endpoints require an API key via the `x-api-key` header (or `?key=` query param).

## Metadata-first polling

The full snapshot is 34 MB. Polling it at high frequency burns bandwidth. Always poll the metadata endpoint first — it returns in under 20ms — and only fetch the full response when `snapshotTimestamp` changes.

```bash theme={null}
curl -H "x-api-key: YOUR_KEY" \
  https://hyper.polynode.dev/v2/perp-snapshot/metadata
```

Response:

```json theme={null}
{
  "snapshotTimestamp": 1776229734159,
  "userCount": 28828,
  "totalQueried": 28828,
  "queryMs": 4224,
  "sizeBytes": 34785713
}
```

| Field               | Description                                                              |
| ------------------- | ------------------------------------------------------------------------ |
| `snapshotTimestamp` | Unix milliseconds when this snapshot was produced. Changes each refresh. |
| `userCount`         | Number of wallets in the snapshot with non-null state.                   |
| `totalQueried`      | Total active wallets considered for this snapshot.                       |
| `queryMs`           | How long the snapshot took to produce. Informational.                    |
| `sizeBytes`         | Full response size before compression.                                   |

## Full perp snapshot

```bash theme={null}
curl --compressed -H "x-api-key: YOUR_KEY" \
  https://hyper.polynode.dev/v2/perp-snapshot
```

Always pass `--compressed` (or `Accept-Encoding: gzip`). The payload shrinks from 34 MB to roughly 6.4 MB on the wire.

Example response (truncated to one wallet — the real response contains \~28,000):

```json theme={null}
{
  "snapshotTimestamp": 1776229734159,
  "userCount": 28828,
  "positions": {
    "0x000000000005dfe874f01071d0e05f99178a5cfc": {
      "marginSummary": {
        "accountValue": "557.607491",
        "totalNtlPos": "2625.890250",
        "totalRawUsd": "-2068.282759",
        "totalMarginUsed": "525.178050"
      },
      "withdrawable": "32.235491",
      "assetPositions": [
        {
          "type": "oneWay",
          "position": {
            "coin": "HYPE",
            "szi": "-150.0",
            "entryPx": "17.505",
            "positionValue": "2625.89025",
            "unrealizedPnl": "-0.107491",
            "leverage": {"type": "cross", "value": 5},
            "liquidationPx": "20.8891",
            "marginUsed": "525.17805"
          }
        }
      ],
      "time": 1776229734000
    }
  }
}
```

The `positions` object is keyed by wallet address. Each value has the same shape as the `clearinghouseState` response you'd get from HyperLiquid's info API for a single user — drop-in compatible with existing code.

## Account value snapshot

Only need `accountValue` and `withdrawable` per user? Use `/v2/account-value-snapshot` — it's 12x smaller because it strips positions.

```json theme={null}
{
  "snapshotTimestamp": 1776229734159,
  "userCount": 28828,
  "accounts": {
    "0x000000000005dfe874f01071d0e05f99178a5cfc": {
      "accountValue": "557.607491",
      "withdrawable": "32.235491"
    }
  }
}
```

Perfect for leaderboards and TVL calculations where you don't care about per-position detail.

## Spot snapshot

`/v2/spot-snapshot` returns every user with non-empty spot token holdings.

```json theme={null}
{
  "snapshotTimestamp": 1776229734105,
  "userCount": 27315,
  "balances": {
    "0x000000000005dfe874f01071d0e05f99178a5cfc": {
      "balances": [
        {
          "coin": "USDC",
          "token": 0,
          "total": "30529.26968461",
          "hold": "313.85604084"
        }
      ]
    }
  }
}
```

## Performance

Measured on production with a representative snapshot:

| Endpoint               | Uncompressed | Gzipped | Typical response time |
| ---------------------- | ------------ | ------- | --------------------- |
| perp-snapshot/metadata | 110 B        | 110 B   | \~220ms               |
| perp-snapshot          | 34.8 MB      | 6.4 MB  | \~360ms               |
| account-value-snapshot | 2.8 MB       | 600 KB  | \~54ms                |
| spot-snapshot          | 14.3 MB      | \~3 MB  | \~150ms               |

Always use compression. The server supports gzip and zstd.

## Polling example

```python theme={null}
import asyncio, aiohttp

async def watch(api_key):
    headers = {"x-api-key": api_key, "Accept-Encoding": "gzip"}
    last_ts = 0

    async with aiohttp.ClientSession() as session:
        while True:
            async with session.get(
                "https://hyper.polynode.dev/v2/perp-snapshot/metadata",
                headers=headers
            ) as r:
                meta = await r.json()

            if meta["snapshotTimestamp"] != last_ts:
                async with session.get(
                    "https://hyper.polynode.dev/v2/perp-snapshot",
                    headers=headers
                ) as r:
                    snap = await r.json()
                last_ts = snap["snapshotTimestamp"]
                print(f"Fresh snapshot: {snap['userCount']} users")
                # Process snap["positions"] here

            await asyncio.sleep(1)

asyncio.run(watch("pn_live_..."))
```

Poll metadata at 1 Hz (essentially free) and only fetch the full snapshot when it updates.
