/wallets/{address}/balances
Current token balances for a wallet on Ethereum and BSC, read from the chain at request time, with a USD value where the token is priced.
GET https://data.vike.io/v1/onchain/wallets/{address}/balancesCurrent token balances for one wallet, read from the chain when you ask. The candidate token set
comes from our own transfer index; the amounts come from balanceOf on the node, so a balance is
what the contract says it is at that block rather than a figure derived from history.
Two chains, and the list is the answer — not a default
ethereum and bsc are the chains this route can answer for, because they are the two the
transfer index covers and the index is what supplies the candidate tokens. chains_scanned in
the response names what was actually read.
Ask for a chain outside that set and it comes back named in chain_errors — not silently
scanned and empty. A wallet reported as holding nothing because nobody looked is the one answer
this endpoint must never give.
# what a wallet holds right now, keeping only holdings worth at least 3,000 USD
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?min_usd=3000"
# the simplest call: both chains, and an omitted floor resolves to 1 USD rather than 0
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances"
# the complete list, unpriced airdrops included: an explicit 0 is honoured, and a long-lived wallet can return thousands of rows
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?min_usd=0"
# one chain only
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?chains=bsc&min_usd=100"
# an alias works for a chain name: eth, mainnet, bnb and binance are accepted
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?chains=eth,bnb&min_usd=100"
# a chain this route does not scan is named in chain_errors rather than reported as an empty wallet
curl -s -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?chains=base,ethereum&min_usd=3000" \
| jq '{chains_scanned, chain_errors}'
# the ten most valuable priced holdings: the route lists largest USD value first with unpriced ones last, and native ETH and BNB carry no price here, so they sort after every priced holding and fall outside the first ten when there are more; total_usd sums priced holdings only, so read it as a floor
curl -s -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances?min_usd=1" \
| jq '.holdings[:10]'addresspathrequiredchainsqueryoptionalethereum and bsc; the aliases eth, mainnet, bnb and binance are accepted. Omit for both. Any other chain is reported in chain_errors.min_usdqueryoptional1 (USD); an explicit 0 filters nothing and lists every holding. ⚠ Any floor above 0 also excludes holdings we cannot price, since an unpriced holding cannot be shown to clear it. The chain's native coin is the exception: it is always listed, unpriced, whatever the floor.A live response, captured 2026-09-04 for vitalik.eth at min_usd=3000.
{
"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"total_usd": 10532.82,
"chains_scanned": ["ethereum"],
"holdings": [
{
"chain": "ethereum",
"symbol": "ENS",
"name": "Ethereum Name Service",
"address": "0xc18360217d8f7ab5e7c516566761ea12ce7f9d72",
"balance": 1144.0360760636715,
"balance_raw": "1144036076063671431479",
"usd_value": 6843.62,
"usd_price": 5.982
},
{
"chain": "ethereum",
"symbol": "WETH",
"name": "Wrapped Ether",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"balance": 1.461898164019089,
"balance_raw": "1461898164019088870",
"usd_value": 3689.2,
"usd_price": 2523.57
},
{
"chain": "ethereum",
"symbol": "WEI",
"name": "Wei Name Service",
"address": "0x0000000000696760e15f265e828db644a0c242eb",
"balance": 1.0,
"balance_raw": "1",
"usd_value": null,
"usd_price": null
}
]
}usd_value: null is a holding, not an error
A balance is measured; a price is looked up, and most tokens do not have one — 434 of the
tokens traded on Ethereum carry a price feed, out of the hundreds of thousands that exist. A
holding we cannot price is still listed, with usd_value and usd_price both null, because
dropping it would under-report the wallet.
total_usd therefore sums only the priced holdings. Read it as a floor, never as net worth, and
never infer "worthless" from a null — it means unpriced here.
This is why min_usd above 0 drops unpriced holdings, and why it defaults to 1
A floor says "worth at least this much", and an unpriced holding cannot show that. Most
tokens in a long-lived wallet are unpriced airdrops — vitalik.eth carries over seven thousand
of them. A value floor that kept everything it could not price would return all of them and
filter almost nothing.
min_usd=0 is the way to ask for the complete list, and it is honoured: an omitted floor and an
explicit zero are different requests.
balance_raw is the integer the contract returned, as a string. Use it when you need exactness:
balance is that integer divided by the token's decimals and is a float, so it loses precision
on large balances.
The native coin
ETH on ethereum and BNB on bsc are included when non-zero, with address: null — a native
coin has no contract. Neither is priced by this route today, so both carry usd_value: null.
What this route cannot see
A token the wallet holds but which never appeared in our transfer index is invisible here: the
index supplies the candidate list, and balanceOf is only called for tokens on it. That fails
toward omission — a missing row, never a wrong number.
It is the narrower of the two available gaps, and deliberately chosen. Until 2026-09-04 this
route was served by a third-party API; a period when that vendor was unavailable returned
200 with an empty holdings array and total_usd: 0.0, which reads exactly like an empty
wallet. Both shapes are on the changelog.
Related
/wallets/{address}— the wallet summary/wallets/{address}/transactions— the transfer history the candidate list is drawn from- Rate limits · Authentication