CRIUS Docs
API status Get API key
Holders & wallets

Find holders who held through a run (holder cohorts)

Find wallets that bought a Robinhood Chain token early and held through the run, with hold time, entry market cap, sells and PnL per wallet. Real example.

Updated 3 min read
Short answer

Call GET /v1/robinhood/token/{address}/holders/cohort?from=…&to=… (Starter plan, 10 credits). Set a size threshold (min_usd, min_balance or min_pct), continuous=true to require holding for the whole window and reset_on to choose what breaks it. Each wallet comes back with hold_time_s, entry_mcap_usd, sells_in_window, resets and pnl_usd.

A holder cohort is the set of wallets that held a token through a window, for example from the moment the market cap crossed $50k until now. Crius replays every balance change in the window and, for each wallet, tells you when it started holding, how long it held, the market cap when it got in, whether it sold, and its PnL. It’s how you find “diamond hands” (wallets that bought early and didn’t sell into the pump), and the opposite: who took profit and when.

Get the cohort in one call

Who held CHARGE from $50k market cap to now

Charge AI (0x7b8892cea949bc60d494681d1bc3ea96071ab0b8) first crossed $50k market cap two hours after launch. Which wallets held from that moment until now?

GET/v1/robinhood/token/0x7b8892cea949bc60d494681d1bc3ea96071ab0b8/holders/cohort?from=mcap:50000&to=now&limit=5
curl "https://api.crius.sh/v1/robinhood/token/0x7b8892cea949bc60d494681d1bc3ea96071ab0b8/holders/cohort?from=mcap:50000&to=now&limit=5" \
-H "x-api-key: $CRIUS_API_KEY"
Real response 200 Captured Oct 28, 2026 · 125 lines (arrays trimmed)
{
"data": {
"criteria": {
"continuous": false,
"exclude": [],
"min_balance": null,
"min_hold_s": null,
"min_pct": null,
"min_usd": null,
"reset_on": "sell"
},
"holders": [
{
"address": "0xfee5fee50000062bd986e86502c5acdf989067a0",
"balance_at_from": 5758.56,
"balance_now": 47534.9,
"entry_mcap_usd": 51583.8,
"hold_time_s": 1234652,
"min_balance_in_window": 5758.56,
"pnl_usd": null,
"qualified_since_block": 88461359,
"qualified_since_ts": 1791990426900,
"reset_history": [],
"resets": 0,
"sells_in_window": 0,
"tags": [
"contract"
],
"value_usd_now": 0.183244
},
{
"address": "0xb823bd7738b61547221f54bb3410b94326aae1eb",
"balance_at_from": 497321,
"balance_now": 497321,
"entry_mcap_usd": 51583.8,
"hold_time_s": 1234652,
"min_balance_in_window": 497321,
"pnl_usd": -22.1233,
"qualified_since_block": 88461359,
"qualified_since_ts": 1791990426900,
"reset_history": [],
"resets": 0,
"sells_in_window": 0,
"tags": [],
"value_usd_now": 1.91714
},
{
"address": "0x38c16e94e79383a5906449fc84477c1a7b19b613",
"balance_at_from": 8344519,
"balance_now": 0.00000000214748,
"entry_mcap_usd": 51583.8,
"hold_time_s": 1234652,
"min_balance_in_window": 0.00000000214748,
"pnl_usd": -298.108,
"qualified_since_block": 88461359,
"qualified_since_ts": 1791990426900,
"reset_history": [],
"resets": 0,
"sells_in_window": 0,
"tags": [],
"value_usd_now": 0.00000000000000827841
},
{
"address": "0x8e56f6476d1361cdc6e75798c83354e70d033f23",
"balance_at_from": 57.0322,
"balance_now": 57.0322,
"entry_mcap_usd": 51583.8,
"hold_time_s": 1234652,
"min_balance_in_window": 57.0322,
"pnl_usd": -0.00219735,
"qualified_since_block": 88461359,
"qualified_since_ts": 1791990426900,
"reset_history": [],
"resets": 0,
"sells_in_window": 0,
"tags": [
"smart_account"
],
"value_usd_now": 0.000219856
},
{
"address": "0xfd2a475d7ce02ec077867d72177063b5c2ab01b6",
"balance_at_from": 429.912,
"balance_now": 429.912,
"entry_mcap_usd": 51583.8,
"hold_time_s": 1234652,
"min_balance_in_window": 429.912,
"pnl_usd": -0.396922,
"qualified_since_block": 88461359,
"qualified_since_ts": 1791990426900,
"reset_history": [],
"resets": 0,
"sells_in_window": 0,
"tags": [],
"value_usd_now": 0.00165728
}
],
"never_reached_threshold": 0,
"qualified": 224,
"reset_out": 942,
"started_qualified": 229,
"window": {
"from": {
"at": "mcap:50000",
"block": 88461359,
"ts": 1791990426900
},
"to": {
"at": "now",
"block": 100406815,
"ts": 1793225079000
}
}
},
"meta": {
"block": 100406816,
"block_age_ms": 1088,
"block_ts": 1793225079000,
"chain": "robinhood",
"finalized_block": 100397649,
"lag_ms": 86,
"next_cursor": "5",
"safe_block": 100401329
}
}

What this tells you

  • window.from resolved mcap:50000 to block 88461359 at ts: 1791990426900 (2026-10-14 15:07 UTC); window.to is now, block 100406815.
  • started_qualified: 229 wallets held at the $50k crossing, qualified: 224 qualify at the end of the window, and reset_out: 942 held at some point in the window but no longer qualify.
  • The five listed wallets all have qualified_since_block: 88461359, resets: 0 and sells_in_window: 0: they held from the crossing to the end, hold_time_s: 1234652 (about 14.3 days). entry_mcap_usd: 51583.8 is the market cap at that block’s price.
  • 0xb823bd7738b61547221f54bb3410b94326aae1eb never touched its position (balance_at_from and balance_now both 497321) and sits at pnl_usd: -22.1233: holding through the run doesn’t mean profit when the token later fell.
  • 0x38c16e94e79383a5906449fc84477c1a7b19b613 went from 8,344,519 tokens to balance_now: 0.00000000214748 with sells_in_window: 0. It moved its tokens out by transfer, which the default reset_on: "sell" doesn’t count, and with no threshold (criteria.min_usd: null) a dust balance still qualifies. A real query should set min_usd.
  • 0xfee5fee50000062bd986e86502c5acdf989067a0 is tagged contract and has pnl_usd: null: it never bought or sold the token on a DEX, so there is no cost to measure against.

How a wallet qualifies

A wallet qualifies while its balance is above your threshold. Choose one:

  • min_usd: the balance’s value at each block’s price, for example min_usd=50.
  • min_balance: a token amount.
  • min_pct: a share of supply.

Without any of them, any non-zero balance qualifies, as in the example.

A reset breaks a wallet’s holding streak. reset_on decides what counts:

reset_onA wallet resets when
sell (default)it sells on a DEX or launchpad, or drops below the threshold
any_decreaseits balance goes down for any reason (sell or transfer out), or it drops below the threshold
below_thresholdonly when it drops below the threshold
noneonly when its balance reaches zero

After a reset, a wallet that still qualifies starts a new streak (its qualified_since_block moves to the reset, and reset_history records it). With continuous=true, any reset, or not qualifying at from, removes it from the result and counts it in reset_out.

Other filters: min_hold_s (a minimum hold time), entered_before (a point: only wallets that first qualified before it), exclude (infra, dev, snipers) and sort (hold_time, the default, longest first; balance; entry_mcap). from and to take the same points as snapshots: block:N, ts:MS, mcap:USD, or the labels launch, graduation, ath, now (see historical holders).

What the fields mean

FieldMeaning
qualifiedWallets that qualify at the end of the window (with continuous=true: held the whole window).
started_qualifiedWallets that qualified at from.
reset_outWallets that qualified at some point in the window but not at the end, or broke continuity.
never_reached_thresholdWallets that held in the window but never above the threshold.
holders[].qualified_since_block, qualified_since_tsStart of the wallet's current streak.
holders[].hold_time_sSeconds from the streak's start to to.
holders[].entry_mcap_usdMarket cap at the streak's start.
holders[].balance_at_from, balance_now, min_balance_in_windowBalance at from, at to, and the lowest in between.
holders[].sells_in_window, resets, reset_historySells in the window, the number of resets and when they happened (block, time, reason, balance after).
holders[].value_usd_now, pnl_usdValue at to, and sells plus current value minus buys. null when the wallet never traded the token.
criteriaThe definition used, echoed back.

Use it in your app

  1. Define a diamond hand for your users. A typical one: at least $50 (min_usd=50), held since a point (from=mcap:10000), never sold (continuous=true&reset_on=sell), not the dev or a sniper (exclude=infra,dev,snipers).

  2. Show the evidence. entry_mcap_usd and hold_time_s are what readers trust: “in since a $10k market cap, held 14 days”. Add pnl_usd when it’s known.

  3. Use the counters as a conviction score. qualified against started_qualified says how many early holders stayed. In the example, more wallets lost qualification during the window (942) than held at its start (229).

  4. Get a Starter key. The cohort endpoint needs the Starter plan and costs 10 credits per call; cache results per window, since a closed window never changes.

// Wallets that held at least $50 of CHARGE from a $10k market cap to now, without selling.
const token = "0x7b8892cea949bc60d494681d1bc3ea96071ab0b8";
const q = new URLSearchParams({
from: "mcap:10000", to: "now", min_usd: "50",
continuous: "true", reset_on: "sell", exclude: "infra,dev,snipers", limit: "50",
});
const res = await fetch(`https://api.crius.sh/v1/robinhood/token/${token}/holders/cohort?${q}`, {
headers: { "x-api-key": process.env.CRIUS_API_KEY },
});
const { data } = await res.json();
console.log(`${data.qualified} of ${data.started_qualified} early holders never sold`);
for (const h of data.holders) {
const days = (h.hold_time_s / 86400).toFixed(1);
console.log(h.address, `in at $${h.entry_mcap_usd} mcap`, `${days} d`, `PnL $${h.pnl_usd ?? "?"}`);
}

Frequently asked questions

How do I find diamond-hand holders of a token?

Ask for the cohort over the run with a strict definition: /holders/cohort?from=mcap:10000&to=now&min_usd=50&continuous=true&reset_on=sell&exclude=infra. Only wallets that held at least $50 at the start and never sold or dropped below $50 until now come back, sorted by how long they held.

What is the difference between `continuous=true` and the default?

By default a wallet qualifies if it meets the threshold at the end of the window, even if it joined late or sold and bought back (its hold time then starts at its last reset). With continuous=true it must already qualify at from and never reset until to; everyone else is counted in reset_out.

Does a transfer to another wallet count as selling?

Not with the default reset_on=sell: only sells on a DEX or launchpad reset a holder. Use reset_on=any_decrease to also break on transfers out, or a min_usd threshold so a wallet that moved its tokens away drops out (below_threshold).

How do I find early buyers who are still holding?

Use entered_before: from=launch&to=now&entered_before=mcap:20000 keeps only wallets that first qualified before the market cap crossed $20k. Add exclude=snipers,dev to leave out the launch snipers and the creator.

Which plan does the cohort endpoint need?

The Starter plan or higher, 10 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