Skip to main content
The live holder table for a token. On subscribe you get a snapshot of every tracked holder with a full position, then live updates as they trade and as the market cap moves. Positions carry bag percentage, unrealized PnL, remaining value and the market cap at entry. When you subscribe to a specific token, CabalSpy first seeds its history from the database so the initial snapshot is complete, then streams live. This stream runs on Solana, BNB, Base, Ethereum and Robinhood. The event shape is identical on every chain, only the native currency changes.

Endpoint

Connect to wss://stream.cabalspy.xyz.

Authentication

Provide your API key as a query parameter, wss://stream.cabalspy.xyz?apiKey=YOUR_KEY, or as a header, Authorization: Bearer YOUR_KEY. Invalid keys are closed with code 1008.

Chains and wallet types

Each chain tracks a different set of holder types, and reports values in its own native currency. Leaving wallet_types out subscribes you to every type that chain supports. Asking for a type a chain does not track is rejected with an error naming the types it does track, so ETH accepts only kol. Leaving blockchain out defaults to solana, which keeps existing integrations working unchanged. On EVM chains, contract and wallet addresses are matched case-insensitively and are returned lowercased.

Subscribe

To start receiving data, send a subscribe message after the connection opens. At a minimum you choose a token to watch and which holder types you care about.
Subscribe to one token on Solana
Subscribe to one token on BNB
The token field decides what you watch. Use a token mint address (Solana) or contract address (EVM) to follow one token, or the value ”*” to follow every tracked token at once. Following one token also gives you an initial snapshot of its current holders, ”*” does not.
Follow every token
string
required
The operation. Use subscribe to start.
string
required
Set to holder for this stream.
string
Chain. One of solana, bnb, base, eth, rh. Defaults to solana.
string
required
Which token to watch. Either a token mint or contract address for one token, or ”*” for all tracked tokens. A single address also returns a starting snapshot of its holders.
array
Which holder types to include. See the table above. Defaults to every type the chain supports.
string
default:"full"
How much you want to receive. See the modes below.
integer
Optional. Only used with mode full. See the modes below.

Choosing a mode

The mode decides whether you also receive live price driven updates, not just trades. This is the main control over how many messages, and how many credits, you use. With mode full you can slow down the market cap updates to save credits. Set mc_interval to a number of seconds from 1 to 30, and you get at most one price update per token in that window. Leave mc_interval out to get every update live.
Full, but at most one price update every 5 seconds
Events only, no price updates at all
Setting mc_interval together with mode events does nothing, because events never sends price updates in the first place.

Unsubscribe and other operations

To stop receiving a token, send the same chain and token with op unsubscribe.
Unsubscribe
To see what you are currently subscribed to, send op subscriptions. To check the connection is alive, send op ping and you get a pong back.
List your subscriptions

Events

The stream emits three event types. init on subscribe, holder_update on each trade, and position_update when the market cap moves (subject to mode and mc_interval).
string
init, holder_update or position_update.
object

token

string
Token mint or contract address.
string
The chain this token lives on.
string
Token symbol.
string
Token name.
number
Total supply, or null.
integer
Token decimals, or null.
number
Market cap in the chain native currency, or null when no price is known yet.
number
Market cap in USD.
string
The native currency the market cap is denominated in. SOL, BNB or ETH.
number
Token price in the native currency.
number
Token price in USD.
number
Price of the chain native currency in USD, used for every conversion in this payload.
number
Same value as native_price_usd. Kept for backwards compatibility, despite the name it carries BNB or ETH on those chains. Prefer native_price_usd.
string
Pool or bonding curve address, or null.
boolean
True while the token still trades on a bonding curve, false once it has migrated to a regular AMM. Null when the launchpad is not recognised. Bonding curves exist on every chain, for example pump.fun on Solana, four.meme on BNB and moonshot on Base.
number
Bonding curve completion percentage. Solana only, null on EVM chains.

position

Every holder carries a position with these fields. The fields ending in _sol are named for historical reasons and carry the chain native currency, so BNB on BNB Chain and ETH on Base, Ethereum and Robinhood. Use market_cap_currency from the token block to label them.
number
Tokens currently held.
number
Peak tokens held.
number
Total tokens bought.
number
Total tokens sold.
number
Percent of peak holding still held.
number
Percent of supply held.
number
Current value of the remaining bag in the native currency.
number
Current value of the remaining bag in USD.
number
Total invested in the native currency.
number
Total invested in USD.
number
Largest single buy in the native currency.
integer
Number of buys.
integer
Number of sells.
number
Total sold value in the native currency.
number
Total sold value in USD.
boolean
Whether the wallet has sold any amount.
number
Realized PnL in the native currency, total sold minus total bought.
number
Realized PnL in USD.
number
Market cap in the native currency when the wallet first bought, frozen.
number
Entry market cap in USD, frozen.
number
Unrealized PnL on the remaining bag in the native currency.
number
Unrealized PnL in USD.
number
Unrealized PnL percentage.
string
Timestamp of the first buy.
string
ISO timestamp of the last activity.
unrealized_pnl and remaining are only filled while a current market cap for the token is known. If a token has not traded since the stream started, these stay null until its first price arrives.

Billing

Each delivered event counts against your plan. In mode full a busy token can produce frequent position_update events as the market cap moves, use mc_interval to throttle them or mode events to receive only trades.

Heartbeat

The server sends WebSocket pings and expects pong, which standard clients answer automatically. You can also send op ping at any time.