CRIUS Docs
API status Get API key
Holders & wallets

Get a wallet's holdings and PnL on Robinhood Chain

Get a Robinhood Chain wallet's tokens with USD value, ETH balance, realized and unrealized PnL, win rate, gas spent and wallet tags in one call. Real example.

Updated 2 min read
Short answer

Call GET /v1/robinhood/wallet/{address}?window=30d (Starter plan, 5 credits). It returns holdings[] (token, balance, value_usd, price_confidence, per-token pnl), native_balance in ETH, and a pnl summary over the window (realized_usd, unrealized_usd, total_usd, win_rate_pct, trades, volume_usd, gas_spent_usd), plus account_type and profile.tags.

A wallet profile is everything a Robinhood Chain address holds and has earned: its tokens with their USD value, its ETH balance, its realized and unrealized PnL over a window, its win rate and gas spent, and what kind of account it is. Crius reads the balances on-chain at one block and computes PnL from every trade attributed to the wallet, so a portfolio app or a wallet-scoring tool gets the whole picture in one call.

Get the profile in one call

CHARGE's creator: 0.71 ETH, two fake USDG tokens, no trades

What does the wallet that launched Charge AI (0x3ac82d45ff9e4963cefbc3f74dbe293f34c927ca) hold, and has it traded in the last 30 days?

GET/v1/robinhood/wallet/0x3ac82d45ff9e4963cefbc3f74dbe293f34c927ca
curl "https://api.crius.sh/v1/robinhood/wallet/0x3ac82d45ff9e4963cefbc3f74dbe293f34c927ca" \
-H "x-api-key: $CRIUS_API_KEY"
Real response 200 Captured Oct 28, 2026 · 84 lines (arrays trimmed)
{
"data": {
"account_type": "smart_account",
"address": "0x3ac82d45ff9e4963cefbc3f74dbe293f34c927ca",
"delegate": "0x63c0c19a282a1b52b07dd5a65b58948a07dae32b",
"holdings": [
{
"balance": 25,
"pnl": null,
"price_confidence": "low",
"token": {
"address": "0xfaaf8ffa8a29ceb6c85aff8d3961f65ae1bfc775",
"logo": null,
"symbol": "USDG"
},
"value_eth": 0.00000500064,
"value_usd": 0.0117789
},
{
"balance": 25,
"pnl": null,
"price_confidence": "low",
"token": {
"address": "0x06993ae1230d3755b54f25022028daa66772bc3d",
"logo": null,
"symbol": "USDG"
},
"value_eth": 0.00000500061,
"value_usd": 0.0117789
}
],
"holdings_truncated": false,
"holdings_value_usd": 0.0235578,
"is_contract": false,
"label": null,
"native_balance": 0.71473787532832551,
"native_value_usd": 1683.56,
"pnl": {
"avg_hold_time_s": null,
"best_trade": null,
"gas_scope": "all transactions sent by the wallet in the window",
"gas_spent_usd": 0.198772,
"realized_usd": 0,
"tokens_traded": 0,
"tokens_with_known_cost": 0,
"total_usd": 0,
"trades": 0,
"unrealized_usd": 0,
"volume_usd": 0,
"win_rate_pct": null,
"window": "30d",
"worst_trade": null
},
"profile": {
"first_seen_block": 91351250,
"first_seen_ts": 1792283372000,
"fresh": false,
"funded_by": {
"address": "0xd782268f600403843484b70710daee6846fc0db8",
"amount_eth": 0.008148386337868892,
"block": 87601233,
"label": "bridge:Relay solver",
"ts": 1791903516300
},
"history": "complete",
"tags": [
"dev",
"smart_account"
],
"tx_count": 14,
"wallet_age_days": 10.8994
}
},
"meta": {
"balances_block": 100406864,
"block": 100406864,
"block_age_ms": 1301,
"block_ts": 1793225084000,
"chain": "robinhood",
"finalized_block": 100397649,
"lag_ms": 59,
"safe_block": 100401329
}
}

What this tells you

  • account_type: "smart_account" with delegate: "0x63c0c19a282a1b52b07dd5a65b58948a07dae32b": an EIP-7702 wallet whose code delegates to that contract. is_contract is false and profile.tags is ["dev", "smart_account"]: it created a launchpad token.
  • native_balance: 0.71473787532832551 ETH, worth native_value_usd: 1683.56. That’s nearly all of its value.
  • Both holdings say symbol: "USDG", but neither is USDG. Real USDG is 0x5fc5360d0400a0fd4f2af552add042d716f1d168; these are 0xfaaf8ffa8a29ceb6c85aff8d3961f65ae1bfc775 and 0x06993ae1230d3755b54f25022028daa66772bc3d. 25 of each are worth value_usd: 0.0117789 at price_confidence: "low", and pnl is null: they were sent to the wallet, not bought. Always identify tokens by address.
  • pnl.window: "30d" (the default): trades: 0, tokens_traded: 0, total_usd: 0 and win_rate_pct: null. It still paid gas_spent_usd: 0.198772, because gas_scope is “all transactions sent by the wallet in the window”, not only trades.
  • profile.funded_by is 0xd782268f600403843484b70710daee6846fc0db8, labeled bridge:Relay solver, with 0.008148386337868892 ETH: the wallet’s first ETH came over the Relay bridge. profile.tx_count: 14.
  • meta.balances_block: 100406864: the ETH and token balances were read on-chain at that block.

How PnL is calculated

Per token, using the USD value of each trade when it happened (average cost):

  • Realized = USD received from sells − tokens sold × average buy price.
  • Unrealized = balance × current price − cost of the balance at the average buy price.
  • The pnl summary adds both over every token traded in the window (1d, 7d, 30d by default, or all).

An unrealized loss in practice, from the holder snapshot: 0xe683eb5c66b0c55c54ce45d46a3bf0a69d809c8f held 29,879,481 CHARGE that cost it cost_basis_usd: 515.975 and were worth value_usd: 180.252 at that moment: an unrealized PnL of −$335.724.

Tokens a wallet sold more of than it bought (some arrived by transfer) have no known cost: they’re left out of the totals and the win rate, and tokens_with_known_cost says how many were counted. The details and edge cases are in How PnL works.

What the fields mean

FieldMeaning
account_type, delegateeoa, smart_account (EIP-7702, with the contract it delegates to) or contract.
labelKnown name of the address (an exchange, a bridge, an app wallet), or null.
native_balance, native_value_usdETH balance and its USD value.
holdings[]Tokens with a balance, most valuable first (up to 200): token (address, symbol, logo), balance, value_usd, value_eth, price_confidence, pnl.
holdings[].price_confidenceHow far to trust value_usd: high, medium (price pool under $10k liquidity), low (thin pool) or none (no price).
holdings_value_usd, holdings_truncatedTotal value of the token holdings; true when the address touched too many tokens to price them all.
pnl.realized_usd, unrealized_usd, total_usdPnL over the window.
pnl.win_rate_pctShare of tokens with known cost that ended in profit.
pnl.trades, tokens_traded, tokens_with_known_cost, volume_usdActivity in the window.
pnl.best_trade, worst_trade, avg_hold_time_sThe tokens with the highest and lowest PnL, and the average time from first to last trade per token.
pnl.gas_spent_usd, gas_scopeGas paid in the window, for every transaction the wallet sent.
profile.tagsdev (created a launchpad token), fresh (under a day old), smart_account, contract, or the app for app wallets (fomo).
profile.funded_byThe wallet's first funder: address, label, amount_eth, block, ts.
profile.tx_count, historyTransactions sent, and whether the whole history is indexed.

Use it in your app

  1. Get a Starter key. /wallet/{address} needs the Starter plan and costs 5 credits per call. Send it in the x-api-key header.

  2. Hide spam. Add min_value_usd=1 (or more) so airdropped lookalike tokens don’t clutter the portfolio, and match tokens by token.address, never by symbol.

  3. Pick the window your users expect. window=7d for a weekly card, all for lifetime PnL. Show tokens_with_known_cost next to the win rate so readers know what it’s based on.

  4. Go deeper when needed. Each trade is in wallet trades, and who funded the wallet in connected wallets.

import os, requests
wallet = "0x3ac82d45ff9e4963cefbc3f74dbe293f34c927ca"
r = requests.get(
f"https://api.crius.sh/v1/robinhood/wallet/{wallet}",
params={"window": "7d", "min_value_usd": 1},
headers={"x-api-key": os.environ["CRIUS_API_KEY"]},
)
d = r.json()["data"]
p = d["pnl"]
print(f"{d['account_type']} {d['profile']['tags']}: {d['native_balance']} ETH (${d['native_value_usd']})")
print(f"{p['window']} PnL ${p['total_usd']} on {p['trades']} trades, win rate {p['win_rate_pct']}%")
for h in d["holdings"]:
print(h["token"]["symbol"], h["token"]["address"], h["balance"], f"${h['value_usd']}", h["price_confidence"])

Frequently asked questions

How is wallet PnL calculated?

Per token, with average cost in USD at the time of each trade. Realized PnL is what the sells returned minus the cost of the tokens sold at the wallet's average buy price; unrealized PnL is the current value of what it still holds minus its cost. The pnl summary adds these up over the tokens traded in the window. Gas is reported separately in gas_spent_usd, not subtracted.

How do I get every token a wallet holds?

/wallet/{address} lists up to 200 holdings with a balance, most valuable first, each checked against the token's balanceOf. Add min_value_usd=1 to hide dust and spam tokens. The ETH balance is separate, in native_balance and native_value_usd.

What does `win_rate_pct` mean?

The share of tokens traded in the window that ended in profit (realized plus unrealized PnL above zero), counting only tokens whose cost is known (tokens_with_known_cost). It's per token, not per trade. It's null when the wallet traded nothing in the window.

Why does a holding have `pnl: null`?

The wallet never bought that token, or sold more than it bought: it arrived by transfer or airdrop, so there is no cost to measure against. That's typical of spam tokens sent to active wallets.

Which plan does the wallet profile need?

The Starter plan or higher, 5 credits per call. See Plans & limits.

Get your free Crius API key

Every example on this page works with a free key: higher rate limits than the anonymous plan, holders, wallets and the WebSocket stream. No card needed.

  • Robinhood Chain (4663) only, from our own archive nodes
  • REST + WebSocket
  • Pay on-chain or by card