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.
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 instead. If you need hundreds or thousands of specific wallets, use /v2/batch/clearinghouse-states. 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).
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.
curl -H "x-api-key: YOUR_KEY" \
https://hyper.polynode.dev/v2/perp-snapshot/metadata
Response:
{
"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
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):
{
"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.
{
"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.
{
"snapshotTimestamp": 1776229734105,
"userCount": 27315,
"balances": {
"0x000000000005dfe874f01071d0e05f99178a5cfc": {
"balances": [
{
"coin": "USDC",
"token": 0,
"total": "30529.26968461",
"hold": "313.85604084"
}
]
}
}
}
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
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.