Skip to main content

Documentation Index

Fetch the complete documentation index at: https://polynode.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

GET https://api.polynode.dev/v2/copy-pnl/snapshot
Returns every wallet currently in your BYOB pool together with their backtest copy-PnL scores across all six time windows (or a chosen subset). One request — no per-period round trips, no client-side stitching. This is the canonical read for any UI that renders stats cards, dashboards, or grids over the entire tracked-wallet set. Pair it with GET /wallets if you need to render the empty-state pool too.

Query parameters

periods
string
default:"7d,14d,30d,60d,90d,180d"
Comma-separated subset of periods to include. Defaults to all six. Useful when you only render a single time window — e.g. ?periods=30d returns ~1/6 the payload.

Response shape

FieldTypeDescription
total_in_poolintWallets currently in your pool
scored_anyintWallets with a score for at least one of the requested periods
errored_anyintWallets whose last refresh attempt failed (heavy whales hitting timeout on long windows)
pending_anyintWallets with no score yet (newly added or queued for the next refresh)
periodsstring[]Echo of the periods returned (matches input or default order)
last_refreshint (unix) | nullWhen the last full refresh cycle completed
walletsarrayOne entry per pooled wallet (see below)

Per-wallet entry

FieldTypeDescription
walletstringLowercased address
periodsobjectMap keyed by period (7d, 14d, …). Each value is the score blob, or null if that specific period is pending
errorobjectOnly present if this wallet’s last refresh errored. { error: string, ts: int }

Per-period score blob

FieldTypeDescription
actual_pnl_usdcnumberCashflow PnL the wallet realized over the period
backtest_copy_pnl_usdcnumberSame trade walk with 2 % slippage on every entry/exit
slippage_amount_usdcnumberDollar friction the copier eats
slippage_cost_rate_pctnumber | nullFriction as % of |actual_pnl| (null when |actual| < $1)
toxic_for_copyingbooltrue when rate > 15 %
trade_countintNumber of fills in the window
partialbooltrue if the underlying walk hit the per-wallet 180 s budget
computed_atint (unix)When this specific score was last refreshed

Examples

Full snapshot (default)

curl -H "x-api-key: $YOUR_KEY" \
  "https://api.polynode.dev/v2/copy-pnl/snapshot"
Response (200 OK, abridged):
{
  "total_in_pool": 108,
  "scored_any": 107,
  "errored_any": 1,
  "pending_any": 0,
  "periods": ["7d", "14d", "30d", "60d", "90d", "180d"],
  "last_refresh": 1777545636,
  "wallets": [
    {
      "wallet": "0x000d257d2dc7616feaef4ae0f14600fdf50a758e",
      "periods": {
        "7d":   { "actual_pnl_usdc":  104635.85, "backtest_copy_pnl_usdc":  101463.76, "slippage_amount_usdc":   3172.09, "slippage_cost_rate_pct":   3.03, "toxic_for_copying": false, "trade_count":    90, "partial": false, "computed_at": 1777544903 },
        "14d":  { "actual_pnl_usdc": -123675.90, "backtest_copy_pnl_usdc": -134838.05, "slippage_amount_usdc":  11162.15, "slippage_cost_rate_pct":   9.03, "toxic_for_copying": false, "trade_count":   458, "partial": false, "computed_at": 1777544903 },
        "30d":  { "actual_pnl_usdc":  317864.92, "backtest_copy_pnl_usdc":  266790.44, "slippage_amount_usdc":  51074.48, "slippage_cost_rate_pct":  16.07, "toxic_for_copying":  true, "trade_count":  2253, "partial": false, "computed_at": 1777544903 },
        "60d":  { "actual_pnl_usdc":  -66101.80, "backtest_copy_pnl_usdc": -181792.53, "slippage_amount_usdc": 115690.73, "slippage_cost_rate_pct": 175.02, "toxic_for_copying":  true, "trade_count":  5916, "partial": false, "computed_at": 1777544903 },
        "90d":  { "actual_pnl_usdc":  289034.81, "backtest_copy_pnl_usdc":  122089.67, "slippage_amount_usdc": 166945.14, "slippage_cost_rate_pct":  57.76, "toxic_for_copying":  true, "trade_count":  8761, "partial": false, "computed_at": 1777544903 },
        "180d": { "actual_pnl_usdc":  665955.87, "backtest_copy_pnl_usdc":  311352.42, "slippage_amount_usdc": 354603.45, "slippage_cost_rate_pct":  53.25, "toxic_for_copying":  true, "trade_count": 18545, "partial": false, "computed_at": 1777544903 }
      }
    }
  ]
}

Subset of periods

curl -H "x-api-key: $YOUR_KEY" \
  "https://api.polynode.dev/v2/copy-pnl/snapshot?periods=7d,30d"
Returns the same shape but with only the requested periods inside each wallets[].periods object. Use this when your UI only renders a single window — payload drops proportionally.

Performance

Pool sizePeriodsPayloadLatency (warm)
100 walletsall 6~150 KB~70 ms
100 wallets1~30 KBunder 30 ms
1000 walletsall 6~1.5 MB~500 ms
1000 wallets1~250 KB~100 ms
All reads come from the precomputed score cache.

Notes

  • scored_any vs scored on the leaderboard. A wallet counts as scored_any here if it has a score for at least one of the requested periods. The leaderboard’s scored is per-requested-period.
  • Per-period null. A wallet may be scored for 30d but null for 180d (heavy whales often time out on long windows). Read each period’s value independently.
  • error is wallet-global. A single error object per wallet covers the most recent refresh failure across any period. Use it to surface “X wallets retrying” in your UI.
  • No pagination. This endpoint always returns the full pool. Use the leaderboard endpoint with limit/offset if you need server-side paging — that’s the trade-off vs the one-shot snapshot.
  • Race-safe with adds. Wallets you add via POST /v2/copy-pnl/wallets show up here immediately, with null periods until the on-add freshening finishes (~30 s).