Solaris AISolaris AI FlowDocs
Node ReferenceData

CabalSpy

Labeled-wallet intel — KOL, smart-money, and whale trades, PnL, cluster signals, and Solana bundle detection.

View as Markdown

The CabalSpy node queries the CabalSpy API for intel on roughly 2,000 manually labeled wallets across Solana, BNB Chain, Base, and Ethereum. Every wallet carries a category (kol, smart for smart money, or whale), and everything the node returns is scoped to that labeled set: trade tapes, PnL trackers, leaderboards, per-token holder tables with unrealized PnL, cluster signals ("N tracked wallets bought the same token inside a window"), and Solana-only bundle detection (a KOL plus side wallets buying in the same block or Jito bundle, with on-chain proof). CabalSpy's value over generic market data is exactly this labeling: "5 KOLs entered this token in the last hour" is a first-class query rather than something you derive.

Category availability varies by chain: Solana has all three categories, BNB and Base have KOL and smart money, Ethereum is KOL-only. Historical data goes back to February 2025.

Prerequisites

A CabalSpy API key is required. Register free at apidashboard.cabalspy.xyz/register (no credit card), copy the key from the dashboard, and add it as a CabalSpy credential in Connections. The free plan includes 10,000 credits per month; every request costs 10 credits, so that is 1,000 requests at up to 5 requests per second. Credits reset on the 1st of each month.

Operations

Most operations take a Blockchain (solana, bnb, base, eth; defaults to Solana) and many take a Wallet Type (kol, smart, whale). Where the type is optional, omitting it means "all categories" (the leaderboard defaults to KOL).

Signals

getSignals: live cluster detections — N tracked wallets moving on the same token inside a lookback window. mode picks the detection kind: cluster (wallets buying the same token), entry (wallets entering), or exit (wallets exiting). Tune with Min Wallets (default 3), Min Buy (per wallet, in the chain's native currency), and Hours (default 1). This is the flagship trigger operation: put it behind a cron trigger and route {cabalspyResponse.data.signals} into a condition or notification node.

getSignalsHistory: historical cluster signals for backtesting. Each row records the token, wallet count, the day it triggered, and would_have_fired — whether the signal would have passed the given thresholds. Rows here are flat (no nested token object), unlike getSignals.

getBundles: Solana-only bundle detection for one mint. Returns bundles where a KOL and one or more "side wallets" bought in the same block or Jito bundle, with a confidence score, proof type (same_block, Jito confirmation), the slot, and per-wallet positions. No bundles is a normal 200 with an empty bundles array, so it is safe to poll.

Token

getTokenHolders: tracked wallets holding a mint, sorted by amount held, with per-holder unrealized PnL, remaining value, entry market cap, and bag % (share of their peak bag still held). The live-position fields (unrealized_pnl_*, entry_market_cap*) are Solana-only and null on other chains.

getTokenTransactions: trades by tracked wallets on one mint, newest first, each with the trader's profile and their holdings after the trade.

getTokenStats: aggregate flow for a mint — total buy/sell volume, net flow, buying pressure (0 to 100), first/latest entry — plus a per-trader breakdown under data.traders.

Wallet

Wallet operations require a tracked wallet address; an untracked one returns a 404 (not_found).

getWalletTracker: full profile for one wallet over a period — realized PnL, win-rate distribution, active tokens with remaining bags, a realized-PnL chart, and recent trades.

getWalletHistory: lifetime stats (total PnL, win rate, best/worst trade) plus a per-token overview and a paginated trade log.

getWalletHoldings: live on-chain balances for a tracked wallet (no cost basis). Note the double nesting: tokens are under data.active_holdings.tokens, amounts are numeric strings, and the native coin uses the literal token_address: "native". When CabalSpy is still warming the balance read, the API returns a loading: true placeholder; the node retries a few times automatically and, if it is still loading, returns the placeholder with loading still true so a workflow can branch on it.

getPnlCalendar: day-by-day realized PnL calendar under data.months, with per-month totals and win/loss streaks. Day keys use DD-MM-YY format.

getWalletConnections: wallets that traded the same tokens as this one over the last 30 days, sorted by shared token count, with an overlap_score (0 to 1).

lookupWallet: is this address tracked? Searches every chain and category (no blockchain field). An untracked address is a normal 200 with found: false and no profile fields — check {cabalspyResponse.data.found} before reading anything else.

Discovery

getLeaderboard: tracked wallets ranked by trading volume over a period, with per-wallet period stats and win-rate distribution. Type defaults to KOL upstream.

listWallets: the raw directory of tracked wallets for a chain and category, with names, avatars, and social links.

getAnalytics: cohort aggregates, selected by mode: most_traded tokens, top_performers, win_rate distribution, or volume_trend. List modes nest rows under data.data (double nesting); win_rate returns flat fields instead of an array.

Trade tape

getLatestTransactions: the global live tape of tracked-wallet trades, newest first. Optionally filter to one mint.

getTransactionsTimerange: same tape, restricted to the last N minutes (max 60; larger values are capped upstream).

getTransactionCount / getTransactionVolume: how many trades / how much volume tracked wallets did in a window. Minutes and hours are summed (total max 24h); leave both empty for the full available window. volume_usd can be null when no USD value could be derived.

Configuration

FieldTypeRequiredDescription
blockchainstringNo (default solana)solana | bnb | base | eth. Not used by lookupWallet (all chains) or getBundles (Solana-only)
typestringPer opkol | smart | whale. Required on list/tape/signal/analytics ops; optional filter on token ops and the leaderboard
addressstringWallet opsTracked wallet address
mintstringToken/bundle opsToken mint; optional filter on the trade-tape ops
modestringgetSignals, getAnalyticsSignals: cluster | entry | exit. Analytics: most_traded | top_performers | win_rate | volume_trend
periodstringNo6h | 1d | 7d | 30d (leaderboard/tracker default 1d, analytics 7d)
minWalletsnumberNoSignals: minimum wallets in a cluster (default 3)
minValuenumberNogetSignals: minimum per-wallet buy in native currency
hoursnumberNogetSignals lookback (default 1); also the hours part of count/volume windows
minutesnumberNoTimerange window (max 60) or the minutes part of count/volume windows
daysnumberNogetSignalsHistory lookback
limitnumberNo1 to 500. Defaults to 50 on list operations (the API otherwise returns the entire list)

Output

Every operation returns the standard envelope, with the raw CabalSpy payload untouched under .data:

{
  "success": true,
  "operation": "getSignals",
  "blockchain": "solana",
  "data": { "signals": [ /* raw CabalSpy rows */ ] },
  "pagination": { "limit": 50, "total": 1, "has_more": false, "next_cursor": null },
  "meta": { "request_id": "req_...", "cached": false, "version": "1.0.0" }
}

CabalSpy places pagination inconsistently — inside data.pagination on the wallet list operations, next to data elsewhere; the node hoists the sibling form to the top of the envelope as shown. Reference fields downstream with the response name (default cabalspyResponse), for example {cabalspyResponse.data.signals[0].token.mint} after getSignals or {cabalspyResponse.data.leaderboard[0].period_stats.realized_pnl_usd} after getLeaderboard.

Two upstream quirks worth knowing when templating: the same concept can change field names between operations (tx_signature vs signature, token_name vs token_symbol), and fields suffixed _sol (like unrealized_pnl_sol) carry the chain's native currency even on BNB/Base/ETH.

On this page