vike
API EndpointsOn-chain

/wallets/{address}/exchange-usage

Which centralised exchanges a wallet sent to and received from over a window, with USD, transfer counts, first and last contact and label confidence.

GET https://data.vike.io/v1/onchain/wallets/{address}/exchange-usage

Which centralised exchanges a wallet sent to and received from over a window (default 365 days), computed per request from the wallet's transfers joined to the addresses the chain's label table marks as exchanges. Each row of exchanges gives the entity, sent_usd (wallet to exchange) and recv_usd (exchange to wallet) in plain dollars, sent_share (the exchange's part of ALL the wallet's outgoing USD), transfer counts, first and last contact, how many of the exchange's addresses were involved, and label_confidence and label_sources. activity totals the wallet's priced transfers with every counterparty, exchange or not, so a share can be checked against its denominator.

An observed pattern and a lower bound, not a verdict

pattern is "sweeps_to_single_cex" when at least 90% of the wallet's outgoing USD in the window went to one exchange over at least three outgoing transfers; pattern_basis gives the numbers. It describes the transfers and does not say the address is a deposit address or that the exchange operates it. Exchange figures are a lower bound: an exchange address we have not labelled is invisible here.

Only priced transfers count (value_usd above zero), and native rows are top-level sends, so a payout routed through a contract call shows only if it emits token transfers. hyperevm has labels for only a few hundred wallets, so an empty exchanges there says little. A wallet with no priced transfer in the window returns found: false and activity: null. A very active wallet over a long window is a 400 whose message says to narrow window: the read is capped at 20 seconds.

cURL
# which exchanges a wallet used over the last year, and whether it sweeps to one of them
curl -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage"

# the last 90 days only, which is also the way out of a "wallet too active" 400
curl -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage?window=90d"

# all recorded history on BSC, where labels cover far fewer exchange addresses than on Ethereum
curl -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/wallets/0x40c9b7d91762f9c715478876310c554f4dc10435/exchange-usage?chain=bsc&window=all"

# just the exchanges and how much went each way
curl -s -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage" \
  | jq '.exchanges[] | {entity, sent_usd, recv_usd}'
addresspathrequired
Wallet address, 0x-prefixed hex
chainqueryoptional
ethereum | bsc | base | hyperevm. Default ethereum. hyperevm has few labels, so a miss there says little
windowqueryoptional
30d | 90d | 180d | 365d | all. Default 365d. A very active wallet over a long window is a 400 naming this parameter: narrow it

A response for a wallet that received from Binance eight times and sent back to it five times, read from the production tables on 2026-10-19. All of its outgoing USD went to one exchange across five transfers, so the pattern is set. label_confidence counts the six Binance addresses by the label pipeline's own grade, and label_sources says two came from a third-party provider and two from our own heuristic (an address can count in both).

Example response
{
  "address": "0x556e9d5d9e64638edde632bbd4810c9fd0d88397",
  "chain": "ethereum",
  "window": "365d",
  "found": true,
  "activity": {
    "sent_usd": 300110.90278,
    "recv_usd": 299998.250152,
    "transfers": 22,
    "counterparties": 13
  },
  "exchanges": [
    {
      "entity": "binance",
      "sent_usd": 300110.90278,
      "recv_usd": 299998.24,
      "sent_share": 1.0,
      "transfers": 13,
      "sent_transfers": 5,
      "recv_transfers": 8,
      "first_seen": "2025-12-25T12:28:11Z",
      "last_seen": "2026-10-19T10:10:11Z",
      "addresses": 6,
      "label_confidence": {
        "high": 1,
        "medium": 4,
        "unrated": 1
      },
      "label_sources": {
        "provider_a": 2,
        "heuristic": 2
      }
    }
  ],
  "pattern": "sweeps_to_single_cex",
  "pattern_basis": {
    "entity": "binance",
    "sent_share": 1.0,
    "sent_transfers": 5,
    "threshold": "at least 90% of the wallet's outgoing USD in the window went to one exchange, over at least 3 outgoing transfers",
    "meaning": "Observed in this window's transfers. It is not a statement that this address is a deposit address, or that the exchange operates it."
  },
  "coverage": {
    "scope": "Priced transfers only (value_usd > 0, overflow = 0) over the window. Native rows are top-level sends, so an exchange payout made through a contract call shows only if it emits token transfers.",
    "labels": "An exchange is a counterparty the chain's label table marks wallet_type 'cex'. An exchange address we have not labelled is invisible here, so every exchange figure is a lower bound. label_confidence is the pipeline's classification_confidence (unrated = none set); label_sources counts labelled addresses by origin (provider_a = a third-party provider's label, heuristic = our predicted label; an address can count in both). A label is the chain's own consensus entity (resolved_entity) with the pipeline's classification_confidence, not a certainty.",
    "note": "sent_share is the exchange's part of ALL outgoing priced USD in the window, labelled exchange or not."
  }
}
Example response
{  "address": "0x556e9d5d9e64638edde632bbd4810c9fd0d88397",  "chain": "ethereum",  "window": "365d",  "found": true,  "activity": {    "sent_usd": 300110.90278,    "recv_usd": 299998.250152,    "transfers": 22,    "counterparties": 13  },  "exchanges": [    {      "entity": "binance",      "sent_usd": 300110.90278,      "recv_usd": 299998.24,      "sent_share": 1.0,      "transfers": 13,      "sent_transfers": 5,      "recv_transfers": 8,      "first_seen": "2025-12-25T12:28:11Z",      "last_seen": "2026-10-19T10:10:11Z",      "addresses": 6,      "label_confidence": {        "high": 1,        "medium": 4,        "unrated": 1      },      "label_sources": {        "provider_a": 2,        "heuristic": 2      }    }  ],  "pattern": "sweeps_to_single_cex",  "pattern_basis": {    "entity": "binance",    "sent_share": 1.0,    "sent_transfers": 5,    "threshold": "at least 90% of the wallet's outgoing USD in the window went to one exchange, over at least 3 outgoing transfers",    "meaning": "Observed in this window's transfers. It is not a statement that this address is a deposit address, or that the exchange operates it."  },  "coverage": {    "scope": "Priced transfers only (value_usd > 0, overflow = 0) over the window. Native rows are top-level sends, so an exchange payout made through a contract call shows only if it emits token transfers.",    "labels": "An exchange is a counterparty the chain's label table marks wallet_type 'cex'. An exchange address we have not labelled is invisible here, so every exchange figure is a lower bound. label_confidence is the pipeline's classification_confidence (unrated = none set); label_sources counts labelled addresses by origin (provider_a = a third-party provider's label, heuristic = our predicted label; an address can count in both). A label is the chain's own consensus entity (resolved_entity) with the pipeline's classification_confidence, not a certainty.",    "note": "sent_share is the exchange's part of ALL outgoing priced USD in the window, labelled exchange or not."  }}