Trader profile with metrics for every window
Everything known about one trader on one chain: capital tier, behaviour labels, the two scores with the reasons behind them, and metrics once per window so a client switches window without another round trip.
rebuild_skipped true means the zeroes are a decision rather than a gap — the wallet is classified as machinery nobody can copy. human_known false means the timing evidence was too thin to have an opinion, which caps the score and is not the same as a wallet judged mid-range.
Path Parameters
chain slug (ton) or numeric chain id (950000)
1 <= length <= 32the wallet address
1 <= length <= 128Header Parameters
payment methods the client can use, comma-separated, case-insensitive. With x402 in the list, a spent keyless budget answers 402 with the x402 challenge instead of 429.
base64 x402 v2 payment payload for this request. A paid request skips the keyless budget and is settled only when it answers 2xx. The v1 header X-PAYMENT is accepted too.
Response Body
application/json
application/problem+json
application/problem+json
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
curl -X GET "https://example.com/chains/string/wallets/string"{ "address": "string", "chain": { "slug": "hyperliquid", "chain_id": 0 }, "tier": "string", "type": "unknown", "labels": [ { "kind": 0, "name": "string", "confidence": 0.1, "token_address": "string" } ], "human_known": true, "rebuild_skipped": true, "rebuild_skip_reason": "string", "copy_eligible": true, "cluster_id": 0, "first_seen_at": "string", "first_onchain_at": "string", "last_active_at": "string", "age_is_estimated": true, "user_score": { "value": 0, "status": "unknown" }, "scammer_score": { "value": 0, "band": "none" }, "signals": [ { "kind": "string", "title": "string", "detail": "string", "subject": "string", "points": 0.1, "occurrences": 0, "last_seen": "string", "direction": "string", "target": "string" } ], "metrics": [ { "window": "1d", "realized_pnl_usd": 0.1, "unrealized_pnl_usd": 0.1, "total_pnl_usd": 0.1, "rated_pnl_usd": 0.1, "gross_profit_usd": 0.1, "gross_loss_usd": 0.1, "invested_usd": 0.1, "volume_usd": 0.1, "roi": 0.1, "win_rate": 0.1, "trade_win_rate": 0.1, "median_roi": 0.1, "profit_factor": 0.1, "avg_trade_usd": 0.1, "avg_hold_seconds": 0, "trades": 0, "winning_trades": 0, "losing_trades": 0, "tokens_traded": 0, "closed_positions": 0, "open_positions": 0, "rated_positions": 0, "excluded_transfer_only": 0, "excluded_untracked": 0, "excluded_no_outcome": 0 } ]}Chain and DEX protocol boards GET
Precomputed rankings of the chains we index, and of the venues inside one chain. Every row carries its raw metrics beside its dimension scores, so a client can sort on any figure and ignore the composite entirely. `scope=protocols` is one board of DEXes and launchpads together. Every pair counts in exactly one row: the launchpad it was created on when it has one, otherwise the DEX that owns its factory. A launchpad trading on Uniswap pools is its own row, and its volume is never part of Uniswap's. `category` labels each row (`dex`, `launchpad`, `perps`, `aggregator`), `infra` names the protocols its pools trade on, and `metrics.hosted_volume_24h` shows the volume other venues trade on a row's pools without ranking it. Pools no one can name — including v4 pools under a hook with no known brand — stay out of the rows and inside the share denominator, so the named shares fall short of one by exactly that amount. Nothing here is computed on the request: the response is drawn from a snapshot taken on a fixed cadence, and `snapshot_at` says exactly how old it is. Rows the board refused to rank appear in `excluded` with a reason rather than going silently missing. With `seasonal=true` the window is a season instead of the live rolling day. A closed season is frozen and never changes; a running one still moves.
Open and closed positions of a wallet GET
One row per token the wallet traded, averaging every entry and exit cycle together. When a per-cycle view is wanted, read `/rounds` instead. `basis_is_incomplete` marks a position that received tokens the indexer could not price, so its PNL is a floor rather than a figure. Each row carries the traded token's `token_score` and `token_status`; statuses `999` and `1000` are terminal, and a position in one of those is a position in a condemned token whatever the score says.