For the complete documentation index, see llms.txt. This page is also available as Markdown.

Bundle

KOL bundle / side-wallet detection on Solana, grouped per token.

Bundle Stream — KOL Bundle / Side-Wallet Detection (WebSocket)

get

Real-time WebSocket stream of KOL bundles. CabalSpy detects wallets that a KOL controls or coordinates with — "side wallets" that buy the same token in the same Jito bundle or the same block as the KOL — and delivers them grouped per token, each with a full live position (bought, sold, held, unrealized PnL, remaining value).

Solana only. A bundle only exists because a KOL bought the token, so the token is always tracked and its market cap is always available — which is why positions and unrealized PnL can be computed for the bundle wallets too.

Whole-token delivery

You always receive the whole token, not a single bundle. Every message carries the complete current picture for one token: the bundles list holds all bundles detected in that token (a token can have several, each with a different KOL), and each bundle holds all of its wallets. When anything changes, the entire token is re-sent, so you simply replace your view of that token with the latest message — no need to merge partial updates.

Each bundle carries its own KOL

A token can contain bundles from several different KOLs. Every entry in bundles therefore has its own kol_wallet and kol_profile, and the KOL is also included inside that bundle's bundle_wallets list with is_kol: true and the same position fields as the side wallets. Take the KOL identity from each bundle's own kol_wallet / kol_profile — there is no token-level KOL, because a token can have many.

Confidence, not two event types

Confirmed side wallets and structural leads are merged into one shape, distinguished by confidence: low | medium | high | verified. verified means Jito-confirmed (jito_confirmed: true, with a bundle_id); lower tiers are on-chain footprint leads (adjacent in block, matching fee, recurrence) that are not Jito-confirmed. Each bundle also carries a human-readable proof and a verify_hint. A wallet's transaction_type is buy or sell; there is no separate sell event.

Two subscription modes — this controls how much you receive (and pay)

Every delivered message counts as one credit. The mode you subscribe with decides how many messages you get:

  • mode: "full" (default) — you receive the token again on every relevant change, INCLUDING marketcap ticks, so unrealized_pnl_* and remaining_* stay live to the second. Ideal for a live holder/positions table, but chatty: an active token can produce thousands of updates (and thus thousands of credits) per hour.

  • mode: "events" — you receive the token only on real events: a new bundle is detected, or a bundle wallet buys or sells. Marketcap-driven updates are NOT sent. Positions are still included, computed at the moment of the event. This is the economical choice when you only need to know that a bundle exists and when wallets trade. Example: 3 bundles and 10 sells on a token cost 13 credits instead of thousands.

Combine mode with the token selector freely: one token + full (live table), one token + events (cheap event feed), * + full (everything live — very high volume), * + events (every new bundle network-wide, events only).

Message events

  • init — one-time snapshot of all known bundles for the token at subscribe time, rebuilt from CabalSpy's store (survives restarts; positions recomputed with the current market cap). Sent in both modes.

  • kol_bundle — an update. In full mode this fires on new detections, trades, AND marketcap moves. In events mode it fires ONLY on new detections and trades.

Connect

Open a WebSocket to wss://stream.cabalspy.xyz with your API key as a query parameter (?apiKey=YOUR_KEY) or a Bearer header (Authorization: Bearer YOUR_KEY). You receive a {"type":"connected"} welcome.

Subscribe

{ "op":"subscribe", "stream":"bundle", "blockchain":"solana", "token":"<mint>", "mode":"events" }. Bundles are always token-scoped. Use "*" to receive bundles across all tokens. A concrete mint returns an init snapshot first. Omit mode (or set "full") for live marketcap-driven updates. The server replies with a subscribed ack echoing the filters (including the resolved mode).

Unsubscribe

{ "op":"unsubscribe", "stream":"bundle", "token":"<mint>" } — stops all updates for that token.

List / Ping

{ "op":"subscriptions" } lists active subscriptions; { "op":"ping" } returns a pong.

Envelope

Every message: { "success":true, "channel":"bundle.solana", "event":"init|kol_bundle", "data":{ ... }, "meta":{ ... } }.

Authorizations
AuthorizationstringRequired

Authorization: Bearer YOUR_KEY

Body

Client -> server. Subscribe to a token's bundles; token-scoped. Filters persist until unsubscribe.

opstring · enumRequiredExample: subscribePossible values:
streamstring · enumRequiredExample: bundlePossible values:
blockchainstring · enumOptional

Must be solana.

Possible values:
tokenstringRequired

A mint to watch one token, or "*" for all tokens.

Example: 2yeMv8fRYmLTmCDJJsdF7sNBFuPP2BunRkKRpUQbpump
modestring · enumOptional

'events' = only real events (new bundle, buy, sell); no marketcap updates; cheapest. 'full' = adds live marketcap-driven position updates (uPNL/remaining stay live); higher credit usage.

Default: fullPossible values:
channelstring · nullableOptional

Alternative to blockchain+token: bundle.solana. or bundle.solana for all. (Pass mode as a separate field.)

Responses
200

init and kol_bundle messages. (The connection also delivers a connected welcome, a subscribed ack per subscribe, and error messages — see schemas.)

application/json

One bundle message — init snapshot or live kol_bundle update. ALWAYS the whole token: bundles contains every bundle detected in the token, each with its own KOL and wallets. Replace your view of the token with each message.

successbooleanOptionalExample: true
channelstringOptionalExample: bundle.solana
eventstring · enumOptionalPossible values:
get/bundle
200

init and kol_bundle messages. (The connection also delivers a connected welcome, a subscribed ack per subscribe, and error messages — see schemas.)

Last updated