One wallet across every chain it traded

GET
/wallets/{address}/overview

The per-chain profiles merged into one header: lifetime totals, the PNL split per chain with each chain's share, and the most profitable chain.

Chains in scope whose wallet data could not be read are listed in unavailable_chains rather than silently counted as zero — a missing chain and a chain that earned nothing are different claims. Omit chains for every served chain.

Path Parameters

address*string

the wallet address

Length1 <= length <= 128

Query Parameters

chains?array<>

comma-separated chain slugs or ids; omit for every served chain

Itemsitems <= 32
window?string

rolling window the metrics are computed over

Default"30d"

Value in

  • "1d"
  • "7d"
  • "30d"
  • "1y"
  • "all"

Header Parameters

Accept-Payment?string

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.

PAYMENT-SIGNATURE?string

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/wallets/string/overview"
{  "profiles": [    {      "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        }      ]    }  ],  "per_chain": [    {      "chain": {        "slug": "hyperliquid",        "chain_id": 0      },      "realized_pnl_usd": 0.1,      "total_pnl_usd": 0.1,      "share_of_total": 0.1    }  ],  "most_profitable_chain": {    "slug": "hyperliquid",    "chain_id": 0  },  "unavailable_chains": [    {      "slug": "hyperliquid",      "chain_id": 0    }  ],  "lifetime": {    "deployed_usd": 0.1,    "gross_bought_usd": 0.1,    "gross_sold_usd": 0.1,    "realized_pnl_usd": 0.1,    "unrealized_pnl_usd": 0.1,    "total_pnl_usd": 0.1,    "unrealized_available": true  }}

Behaviour labels for many wallets POST

Batch by construction: a transaction table calls this once per page to mark robot, sniper and sandwich makers, where a per-row call would be one request per visible trade. It is the one wallet read that is a `POST`, because a list of up to 200 addresses does not belong in a query string. Addresses absent from the response carry no labels.

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.