Robinhood Balances API — Wallet Portfolios & History
Query wallet balances on Robinhood with Bitquery GraphQL. The EVM.Balances cube returns computed balances with built-in aggregates — amount, USD value, first/last change time, and update count — grouped by whatever dimensions you select: one wallet's full portfolio, a batch of wallets, or network-wide per-currency totals, all in single calls that would take thousands of eth_getBalance / balanceOf RPCs. For token-centric holder rankings and counts, use the dedicated Token Holders API.
Every query on this page was executed against the production endpoint before publishing.
To query or stream data outside the Bitquery IDE, you need an API access token.
Follow the steps here: How to generate Bitquery API token ➤
- Robinhood Token Holders API
- Robinhood Token Supply API
- Robinhood Transfers
- Robinhood Trades (for prices to value non-ETH holdings)
- Robinhood Events API
On this page: Concepts · Portfolio · As-of-date · Single token · Multi-address · Wallet profile · Currency totals · FAQ
Why query balances here instead of an RPC loop
Node RPC (eth_getBalance / balanceOf calls) | Bitquery Balances | |
|---|---|---|
| Whole portfolio | One call per token you already know about | One call returns every token the wallet holds |
| Token holders | Impossible without indexing all transfers yourself | One sortable query on the Holders API |
| History | Archive node + block-pinned calls | Block.Date.till gives the balance as of any date |
| Extras | — | USD value, first/last change time, update count |
Datasets, grouping, and selectWhere
- Use
dataset: combined— balances are computed from history, and combined guarantees the full picture. - Grouping follows your selection. Filter/select
Balance.Addressto get per-wallet rows; select onlyCurrencyto get network-wide per-currency totals; select both for wallet × token rows. selectWherefilters aggregated results (like SQLHAVING):Amount(selectWhere: { gt: "0" })drops zero/dust rows after the balance is computed. Amount thresholds are strings.AmountInUSDis populated for native ETH; token rows generally return0. USDG is a dollar stablecoin, so itsAmountis effectively USD; value other tokens by joining prices from the Trades API.
All token balances of an address (portfolio)
Everything a wallet holds in one call. The selectWhere keeps only non-zero rows.
{
EVM(network: robinhood, dataset: combined) {
Balances(
where: { Balance: { Address: { is: "0x9c0489b89ae473de6edcb159f21c3019ba730282" } } }
) {
Currency {
Symbol
SmartContract
}
Balance {
Amount(selectWhere: { gt: "0" })
AmountInUSD
}
}
}
}
Balance as of a date (time travel)
Add Block.Date.till to compute the same portfolio as of any date — audits, tax snapshots, "what did this whale hold before the launch". A date before the wallet's first activity returns no rows.
{
EVM(network: robinhood, dataset: combined) {
Balances(
where: {
Block: { Date: { till: "2026-07-20" } }
Balance: { Address: { is: "0x9c0489b89ae473de6edcb159f21c3019ba730282" } }
}
) {
Currency {
Symbol
SmartContract
}
Balance {
Amount(selectWhere: { gt: "0" })
AmountInUSD
}
}
}
}
Native ETH and single-token balances
Filter Currency.Native: true for the ETH balance, or pin one contract for a single token — with the change-history aggregates included.
{
EVM(network: robinhood, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0x9c0489b89ae473de6edcb159f21c3019ba730282" } }
Currency: { Native: true }
}
) {
Currency {
Symbol
Native
}
Balance {
Amount
AmountInUSD
}
}
}
}
{
EVM(network: robinhood, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0x9c0489b89ae473de6edcb159f21c3019ba730282" } }
Currency: { SmartContract: { is: "0x0bd7d308f8e1639fab988df18a8011f41eacad73" } }
}
) {
Currency {
Symbol
SmartContract
}
Balance {
Amount
AmountInUSD
FirstChangeTime
LastChangeTime
UpdateCount
}
}
}
}
Balances for multiple addresses
Batch a watchlist with Address.in — one row per address (per selected currency).
{
EVM(network: robinhood, dataset: combined) {
Balances(
where: {
Balance: {
Address: {
in: [
"0x9c0489b89ae473de6edcb159f21c3019ba730282"
"0xcaf681a66d020601342297493863e78c959e5cb2"
]
}
}
Currency: { Native: true }
}
) {
Balance {
Address
Amount
AmountInUSD
}
}
}
}
Token holders
Holder rankings, counts, whale floors, distribution stats, and dormancy screens have a dedicated cube and page — see the Robinhood Token Holders API.
Wallet profile: first seen, last active, update count
The built-in aggregates turn balances into a wallet profiler: FirstChangeTime (when the wallet first touched each asset), LastChangeTime (most recent activity), and UpdateCount (how many balance changes) — age, dormancy, and activity signals with no extra indexing.
{
EVM(network: robinhood, dataset: combined) {
Balances(
where: { Balance: { Address: { is: "0x9c0489b89ae473de6edcb159f21c3019ba730282" } } }
) {
Currency {
Symbol
SmartContract
}
Balance {
Amount(selectWhere: { gt: "0" })
FirstChangeTime
LastChangeTime
UpdateCount
}
}
}
}
Network-wide per-currency totals
With no address dimension, rows group per currency: Amount becomes the total held across all addresses, with network-level change stats — the full field set of the cube on display.
{
EVM(network: robinhood, dataset: combined) {
Balances(limit: { count: 10 }) {
Currency {
Decimals
Symbol
SmartContract
DelegatedTo
Fungible
HasURI
Name
Native
ProtocolName
}
Balance {
Amount(selectWhere: { gt: "0" })
AmountInUSD
FirstChangeTime
LastChangeTime
UpdateCount
}
}
}
}
Need balance changes as a continuous feed? Bitquery delivers Robinhood token data as Kafka streams (protobuf topic robinhood.tokens.proto) with consumer-group scaling and replay. See Kafka Streaming Concepts.
Use-case patterns
| Goal | Approach |
|---|---|
| Wallet / portfolio page | Portfolio query; poll on an interval for live UX |
| Tax / audit snapshots | Balance as of a date with Block.Date.till |
| Token distribution, rich lists & whales | Token Holders API rankings, counts, and balance floors |
| Wallet profiling (age, dormancy) | First/last change + update count |
| Exchange / custody monitoring | Multi-address batch on a polling schedule |
| Supply-side view | Per-currency totals, or the Token Supply API |
Tips
- Always use
dataset: combinedfor balance queries — balances are computed from full history. - Remember grouping follows selection: add or drop
Balance.Address/Currencyfields to pivot between wallet, token, and network views. - Use
selectWhere(post-aggregation) for balance thresholds; regularwherefilters raw rows before aggregation. AmountInUSDis native-ETH-only in practice — USDG'sAmount≈ dollars; price other tokens via the Trades API.- For holder rankings and counts, use the dedicated Token Holders API — its
Holderscube is built for the token-centric view. - An as-of-date query before a wallet's first activity returns no rows — that's the correct answer, not an error.
FAQ
How do I get all token balances of a Robinhood address?
Query EVM.Balances on dataset: combined filtered by Balance.Address, selecting Currency and Balance.Amount — one call returns the full portfolio. Add Amount(selectWhere: {gt: "0"}) to hide dust and emptied positions.
How do I get the balance at a past date?
Add Block: { Date: { till: "YYYY-MM-DD" } } to any balance query — the cube recomputes balances as of that date. See time travel.
How do I list the top holders of a token?
Use the dedicated Token Holders API — its Holders cube returns sortable holder rankings, holder counts, distribution stats, and dormancy screens.
Why is AmountInUSD 0 for my token balances?
USD enrichment covers native ETH; token rows generally return 0. USDG is a dollar stablecoin (read Amount as USD), and other tokens can be valued by joining prices from the Trades API.
Can I stream balances in real time?
Balances is a query cube — poll it on your interval for live UX. For continuous balance-change feeds at firehose scale, Bitquery delivers Robinhood token data over Kafka streams.
Is this a replacement for eth_getBalance?
For anything beyond a single known token it's strictly stronger: whole portfolios, holder lists, holder counts, historical as-of-date balances, and change aggregates come from single queries instead of RPC loops over an archive node.