Discovery and markets API
Filter wallets by trading performance on one chain
Find the wallets on a chain matching stated bounds: minimum realised profit, volume, swaps, distinct tokens or win rate over 1d/1w/30d/1y, behaviour labels excludable.
/api/external/discovery/wallet-screener/{chain}What it returns
A WALLET screener: state the criterion (minimum realised profit, traded volume, swap count, distinct tokens, win rate; and behaviour labels to exclude) and get the wallets that meet it, ranked. The counterpart to screener, which screens TOKENS. Distinct from richest-wallets, realized-pnl-leaders and unrealized-pnl-leaders, which are three FIXED rankings with no caller-supplied bounds at all, and from wallet-labels/wallet-risk, which take a wallet and answer about it. WHAT THE LABELS MEAN, AND WHAT THEY DO NOT: behaviourLabels describes what a wallet DOES (every value observed across 24 labelled rows on four chains was a behaviour or holdings-size term — bot, scammer, sniper, smart trader, whale). It is NOT an identity: nothing here says a wallet is an exchange, a bridge or a treasury, and no identity term appeared once in the measured sample. category is the separate, structural axis and read null on every row measured through this query path — see its own description. The two are deliberately kept apart and are never merged into one field. NO TOTAL IS PUBLISHED, deliberately: the underlying source reports no count of matching wallets (its own count field was measured to be the page size, not the number of matches), so page forward with offset until a page comes back short rather than computing a page count. Every figure on every row belongs to the requested window, which is echoed in the response so a row can never be read window-less.
Chains
- Solana SOL
- BNB Chain BNB
- Ethereum ETH
- Stable STABLE
- Base BASE
- Robinhood Chain RHC
- Arc ARC
Request
Send your key in the x-dex-data-key header. Replace each <placeholder> with a real value.
curl -H "x-dex-data-key: $DEXDATA_API_KEY" \ "https://api.dexdata.io/api/external/discovery/wallet-screener/SOL"
| Parameter | Description |
|---|---|
windowquery · string · optional | The trailing window every filter, every returned figure and the ranking apply to. All four were verified live against the source. CAVEAT ON 1y, measured and published rather than smoothed over: on the two highest-profit rows sampled for that window, realizedProfitUsd came back within 0.0001% of volumeUsd with a winRatePct of 100 and 99.74 — an extreme reading that may be a genuine artefact of how the source aggregates a year. Sample size is two rows at the top of one ranking; treat 1y figures with that in mind.1d1w30d1y |
minRealizedProfitUsdquery · number · optional | Only wallets whose realised profit over window is at or above this, in USD. Verified to genuinely bind (every returned row satisfied it), not merely accepted. |
minVolumeUsdquery · number · optional | Only wallets whose traded notional over window is at or above this, in USD. Verified to genuinely bind. |
minSwapsquery · integer · optional | Only wallets with at least this many swaps over window. Verified to genuinely bind. |
minUniqueTokensquery · integer · optional | Only wallets that traded at least this many distinct tokens over window. Verified to genuinely bind. |
minWinRatePctquery · number · optional | Only wallets whose win rate over window is at or above this, 0-100. Verified to genuinely bind. Read it beside a profit figure, never alone: a high win rate is compatible with a large net loss (many small wins, a few catastrophic ones). |
excludeLabelsquery · string · optional | A comma-separated list of behaviour labels to EXCLUDE, e.g. BOT or BOT,SCAMMER. Verified to genuinely filter, with the control and the treatment measured in a single request: the unfiltered top five wallets by realised profit all carried BOT, and the same query excluding it returned five entirely different wallets carrying none. Values observed live: BOT, SCAMMER, SNIPER, WHALE, MEGA_WEALTHY, SMART_TRADER_TOKENS_OVER_TWO_DAYS_OLD. An unrecognised value is a no-op, not an error. There is deliberately no include-labels counterpart: selecting FOR a label and receiving wallets carrying it establishes nothing a caller could not already ask for with a numeric bound. |
sortByquery · string · optional | Which window figure the ranking is on. Every one of these was verified to genuinely sort (each returns a different, correctly-ordered top page), not merely accepted.realizedProfitUsdvolumeUsdswapswinRateuniqueTokens |
sortOrderquery · string · optional | Ranking direction. Defaults to desc — the largest value first.ascdesc |
limitquery · integer · optional | How many wallets to return. Capped at 100 — the source's own per-call ceiling (enforced after the API-key gate). Defaults to 20. limit ≤ 60 keeps the answer under 32 KB. |
offsetquery · integer · optional | 0-indexed row offset into the ranking. Page forward until a page comes back shorter than limit: no total is available to compute a page count from. |
chainpath · string · required | Every chain this API serves is supported here, each verified to return rows scoped to that chain. A chain outside the enum returns 400. CELO, ARB, OP and SCROLL return 400 here. |
Response fields
A JSON response. Every field is always present; null means the value could not be established, never zero.
| Field | Type | Description |
|---|---|---|
window | string | The window every figure on every row below belongs to — echoed from the request. |
wallets | object[] | Ranked by sortBy/sortOrder. Empty when nothing on this chain matched every bound. A full page does NOT mean more wallets exist, and a short page is the only signal that they do not — there is no total. |
wallets[].wallet | string | The wallet address. |
wallets[].firstTransactionAt | integer | null | Unix SECONDS of the wallet's first recorded transaction. |
wallets[].lastTransactionAt | integer | null | Unix SECONDS of the wallet's most recent recorded transaction. |
wallets[].behaviourLabels | string[] | null | What this wallet DOES, in the source's own vocabulary — bot, scammer, sniper, smart trader, whale and the like. NEVER an identity: nothing here says a wallet is an exchange, a bridge, a treasury or a market maker, and across 24 labelled rows on four chains no identity term appeared once. An EMPTY array is a real reading — the source classified this wallet and gave it no label, which is the majority reading once bots are excluded — and is deliberately different from null, which means the source did not report the field at all. |
wallets[].category | string | null | What this wallet structurally IS, in the source's own closed vocabulary (observed member: NORMIE; the vocabulary also names exchange, pool-authority, staking-vault, burn, locker and token-creator kinds). This is the identity axis, kept strictly apart from behaviourLabels. MEASURED CAVEAT: it read null on all 26 rows returned through this endpoint's own query path across four chains (SOL, ETH, BNB, BASE) — STABLE, RHC and ARC were not among those four — so expect null today — that is the source's own answer, not a field that went unchecked. Published verbatim and never normalised into a fixed enum, which would assert a category the source did not send. |
wallets[].scammerScore | integer | null | The source's own scam score. null means no score, which is NOT a score of zero — measured null on 3 of 5 rows and 90 on another in the same response. Higher is worse. |
wallets[].botScore | integer | null | The source's own automation score. Higher means more bot-like. null means no score, never zero. |
wallets[].volumeUsd | number | null | Total USD notional traded over window. A real 0 is a reading; null means the source said nothing. |
wallets[].realizedProfitUsd | number | null | Profit already taken over window, in USD. Can be negative. Read it beside winRatePct: the two disagree more often than they agree at the extremes. |
wallets[].averageProfitUsdPerTrade | number | null | Mean realised profit per trade over window, in USD. |
wallets[].realizedProfitPct | number | null | Realised profit over window as a PERCENT, not a fraction. Positive means profit. |
wallets[].avgHoldPeriodSec | number | null | Mean SECONDS between opening and closing a position over window. |
wallets[].swaps | integer | null | Swap count over window. A real 0 is a reading. |
wallets[].uniqueTokens | integer | null | Distinct tokens traded over window. |
wallets[].winRatePct | number | null | Share of profitable closed positions over window, 0-100. The source counts a closed position only when its profit or loss exceeds $1, so a wallet whose positions are all smaller than that reads 0 rather than null. |
wallets[].nativeTokenBalance | number | null | The wallet's balance of the chain's OWN native token (SOL, ETH, BNB …), in whole tokens — already scaled by the source, never raw base units. Verified decimalised on Solana, Ethereum, BNB and Base; not separately verified on the remaining chains. |
Start building with DexData today
Sign in, create a key and make your first call in a minute. Free credits every month, and you only pay for calls that succeed.
Get a free API key