MadeOnSolMade on Sol
Pricing
Try freeGet real-time feedsSign in
MadeOnSolMade on Sol

Solana and Robinhood Chain intelligence — KOL wallet tracking, deployer intelligence, all-DEX trade streams, and a developer API. Discover, compare, and build.

Product

  • Solana Data API
  • Robinhood Chain API
  • Robinhood Chain x402
  • MCP Servers & SDKs
  • x402 for AI Agents
  • Pricing
  • Enterprise / For Businesses

Solutions

  • Trading Bots
  • Wallet Tracking
  • Copy Trading
  • Token Scanners
  • Trading Terminals
  • DEX Data
  • Smart Money
  • Token Risk
  • AI Agents
  • View all solutions

Developers

  • API Docs
  • WebSocket Streaming
  • Changelog
  • API Status
  • Latency Benchmarks
  • Data Integrity
  • Data Dictionary
  • Methodology

Resources

  • All Tools
  • Compare Tools
  • Best Trading Bots
  • Best DEXs
  • Best Wallets
  • Best Analytics
  • Best DeFi
  • Best Snipers
  • Blog
  • Blog Archive
  • Signal Scorecard
  • Tool Uptime
  • Community
  • Submit a Tool
  • Advertise

Company

  • About
  • Contact
  • Security
  • Privacy
  • Terms
  • DPA
  • Disclaimer

© 2026 MadeOnSol

MadeOnSol — eenmanszaak, Hulshout, Belgium · KBO/BTW BE 1039.535.538 (art. 56bis, no VAT charged)

Runs on our own dedicated EU servers — self-hosted data stack, own Robinhood Chain node · security

Follow us on XPowered by:constant·k — Private Solana RPC Services
API Documentation

Solana & Robinhood Chain intelligence · API reference

The full reference.
Every endpoint, every payload.

REST, webhooks, and WebSocket streams over the same KOL, deployer, alpha-wallet, and DEX firehose data. Authenticated with a single msk_ bearer key or — for agents — paid per call via x402. Free tier ships the full response shape on 40+ endpoints; 189 operations in total.

Get free API key Try it live, no signup

Weighing us against another provider? Compare us vs Birdeye, Helius, Moralis →

Base URL madeonsol.com/api/v1·Auth header Authorization: Bearer msk_…·JSON in, JSON out

What ships in v1

The surface area, the venues, the SDKs, the push latency.

145+
REST endpoints

189 documented operations · 30 WS channels

14
DEX programs

Pump · Raydium · Jupiter · …

14
Official packages

7 Solana + 7 Robinhood Chain

Push
WS + webhooks

Pro/Ultra · latency on /benchmarks

openapi.json ↗

Start

Try it liveQuick startStarter kitsAuthenticationTransportsTier comparison

Endpoints

CatalogLatencyKOL TrackerDeployer HunterAlpha WalletsToolsWallet TrackerWalletCopy-TradePrice AlertsBulk exports

Robinhood Chain

RHC endpoints

Real-time

WebhooksPayload formatWebSocket streams

Reference

Deployer tiersErrorsVersioningSDKsFAQ
Pricing →Get API key →Changelog →

Try it live

Try the live API. No signup.

Free demo

Try the live API. No signup.

Public demo key. 20 calls/hour per IP, 3 read-only endpoints, live feeds 5-min delayed (like the free tier — paid keys are real-time). Want 40+ endpoints and 200 calls/day? Free key, one click →

Demo API key

msk_demo_try_the_solana_api_2026

Paste into your terminal

curl -H "Authorization: Bearer msk_demo_try_the_solana_api_2026" "https://madeonsol.com/api/v1/kol/feed?limit=3"
Works onGET /kol/feedGET /deployer-hunter/alertsGET /alpha/leaderboard
Get unlimited free key

Quick start

Ship in five minutes.

Free key, one curl call, optional SDK.

1Step

Grab a free key

Sign in at /developer. 200 calls/day, 40+ endpoints, no payment to start.

2Step

Make the first call

Authorization header, REST, JSON in / JSON out.

curl -H "Authorization: Bearer msk_…" \
  "https://madeonsol.com/api/v1/kol/feed?limit=5"
3Step

Or install an SDK

TypeScript or Rust — same endpoints, same msk_ auth.

npm install madeonsol
# or
cargo add madeonsol
4Step

Go push, not poll

On Pro/Ultra use WebSocket or webhooks for <1 s delivery.

Starter kits

Or clone a working bot. Run in five minutes.

Open-source (MIT) example projects — free-key runnable, one dependency or fewer. Fork them into your own thing.

🤖GitHub →

Paper-trade live smart money

kol-copytrade-bot-starter

Opens a virtual position when a tracked KOL buys, closes when they sell. Free tier polls /kol/feed (5-min delayed); PRO streams kol:trades over WebSocket (<3s).

🔍GitHub →

Scored rug reports in Telegram

rug-check-telegram-bot

Paste a mint → transparent 0–100 risk score with named factors (PRO) or early-buyer quality (free). Zero dependencies.

🚨GitHub →

Proven-deployer launch alerts

deployer-alert-discord-bot

Discord embeds when a tracked pump.fun / bonk deployer launches or bonds a token. Free-key-safe polling, one webhook URL.

MIT-licensed. Grab a free key and each runs in five minutes — the free tier is genuinely usable (live feeds run 5 min behind), PRO unlocks real-time.

Authentication

Two ways to identify yourself.

API key for humans and apps. x402 for autonomous agents paying per call.

Recommended

MadeOnSol API key

Get a free key at /developer — instant, no payment to start. Free tier: 200 calls/day, 40+ endpoints.

curl -H "Authorization: Bearer msk_your_api_key" \
  "https://madeonsol.com/api/v1/kol/feed?limit=5"

Windows PowerShell: use curl.exe (bare curl is an Invoke-WebRequest alias).

Agent-native

x402 micropayments

No key. The agent's Solana wallet IS the identity. Pay per call for KOL, deployer, and wallet data — plus the trade-decision calls an agent makes at the moment of a buy: token risk score, buyer quality, live token snapshot, and the machine-readable Signal Scorecard. See /x402 for the full protocol.

# Receive 402 → sign USDC → retry with proof → data
curl https://madeonsol.com/api/x402/kol/feed?limit=5

$0.005–$0.02 per call · settles in ~1s · failed payments don't charge.

Transports

Pick the protocol that fits the workload.

Same data — four delivery shapes.

REST · key

Pull when you ask

Dashboards, batch jobs, anything human-paced. The default.

Auth
msk_… bearer
Latency
Request-response
Tier
Free · Pro · Ultra
x402 · per call

Pay on demand

Autonomous AI agents with a Solana wallet but no account.

Auth
USDC signature
Latency
~1s settle
Tier
No tier · pay per call
Webhook · push

Events come to you

Long-running bots, alerts, copy-trade execution.

Auth
HMAC-SHA256
Latency
Pushed on event
Tier
Pro · Ultra
WebSocket · stream

Persistent firehose

Low-latency decisions, all-DEX coverage, agent loops.

Auth
non-expiring stream token
Latency
Live stream
Tier
Pro · Ultra (firehose: Ultra)

Tier comparison

What each tier unlocks.

Every tier ships the full response shape. Paid gates are per-user infra (webhooks, WS, rules) and ULTRA-only data depth.

FeatureBasicFreePro€43/moUltra€131/moBusiness€400/mo
Daily requests20010,000100,000500,000
Burst rate limit60/min300/min600/min3,000/min
Wallet addressesFullFullFullFull
TX signaturesIncludedIncludedIncludedIncluded
KOL feed · leaderboard · profile · PnL · timingFullFullFullFull
KOL coordination detection—FullFullFull
KOL hot / trending / pairs20/page (paginate)20/page (paginate)50/page + wallets50/page + wallets
KOL compare4 wallets4 wallets5 wallets5 wallets
Scout leaderboard · coordination history—FullFullFull
Deployer leaderboard · profile · tokens · trajectoryFullFullFullFull
Deployer alerts1-50/page, cursor + offset1-50/page, cursor + offset1-50/page, cursor + offset1-50/page, cursor + offset
Deployer multiplier statsFullFullFullFull
Alpha leaderboard100/page100/page500 window + bot signals500 window + bot signals
Alpha profile · linked wallets——FullFull
Token cap table—Top 10Top 20Top 20
Token holders census—Top 10Top 50Top 100
Token buyer qualityFullFullFullFull
Token risk/safety score + per-factor breakdown—✓✓✓
Wallet tracker watchlist—50 wallets100 wallets500 wallets
Wallet tracker history—FullFullFull
Copy-trade rules—3 × 5 wallets20 × 50 wallets100 × 250 wallets
KOL coordination push alerts—5 rules20 rules100 rules
First-touch subscriptions——1050
Price alerts (MC dip/recovery)—5 alerts25 alerts125 alerts
Webhooks—31030
WebSocket streaming—2 conn3 conn10 conn
token:prices mints per connection—25100250
Wallet tracker real-time (WS)——IncludedIncluded
DEX firehose (all-DEX WS)——2 conn5 conn
Free tier ships the full REST response shape on 40+ endpoints — real wallets, full TX signatures, full precision. Paid gates are per-user infra (webhooks, WS, rule engines), ULTRA-only data depth, and freshness: live feeds (KOL feeds, deployer alerts, graduations, first-touches) are delayed 5 minutes on Free — real-time on PRO+ and x402. Leaderboards and token search are real-time on every tier; wallet PnL needs Pro.
Upgrade to Pro — €43/mo →Ultra — €131/mo →Business (€400/mo) & Enterprise →

Endpoints

One reference for every route.

All 189 endpoints, grouped by capability. Each card has parameters, defaults, and a real response example.

ShowChips show the minimum plan; higher plans always pass.

Catalog

189 endpoints, one scan.

Click a row to jump to the full reference card below.

MethodEndpointGroupAccess
GET/kol/walletsKOL Wallet RosterKOLFREE
GET/kol/feedKOL Trade FeedKOLFREE
GET/kol/leaderboardKOL PnL LeaderboardKOLFREE
GET/kol/{wallet}KOL Wallet ProfileKOLFREE
GET/kol/coordinationKOL Coordination DetectorKOLPRO
GET/kol/tokens/{mint}KOL Token FlowKOLFREE
GET/kol/pairsKOL Affinity PairsKOLFREE
GET/kol/{wallet}/timingKOL Timing ProfileKOLFREE
GET/kol/tokens/hotKOL Momentum TokensKOLFREE
GET/kol/tokens/trendingKOL Trending TokensKOLFREE
GET/kol/{wallet}/pnlKOL Wallet PnLKOLFREE
GET/kol/tokens/{mint}/entry-orderKOL Token Entry OrderKOLFREE
GET/kol/compareKOL Wallet CompareKOLFREE
GET/kol/alerts/recentKOL Live Alert FeedKOLPRO
GET/kol/first-touchesKOL First-Touch SignalKOLFREE
GET/kol/scouts/leaderboardScout KOL LeaderboardKOLPRO
GET/kol/coordination/historyCoordination HistoryKOLPRO
POST/kol/first-touches/subscriptionsCreate First-Touch Webhook SubscriptionKOLULTRA
GET/kol/first-touches/subscriptionsList First-Touch SubscriptionsKOLULTRA
GET/kol/first-touches/subscriptions/{id}Get First-Touch SubscriptionKOLULTRA
PATCH/kol/first-touches/subscriptions/{id}Update First-Touch SubscriptionKOLULTRA
DELETE/kol/first-touches/subscriptions/{id}Delete First-Touch SubscriptionKOLULTRA
GET/kol/coordination/alertsList Coordination Alert RulesKOLPRO
POST/kol/coordination/alertsCreate Coordination Alert RuleKOLPRO
GET/kol/coordination/alerts/{id}Get Coordination Alert RuleKOLPRO
PATCH/kol/coordination/alerts/{id}Update Coordination Alert RuleKOLPRO
DELETE/kol/coordination/alerts/{id}Delete Coordination Alert RuleKOLPRO
GET/deployer-hunter/statsGlobal Deployer StatsDeployerFREE
GET/deployer-hunter/leaderboardDeployer LeaderboardDeployerFREE
GET/deployer-hunter/{wallet}Deployer ProfileDeployerFREE
GET/deployer-hunter/{wallet}/tokensDeployer Token HistoryDeployerFREE
GET/deployer-hunter/alertsDeployer Alert FeedDeployerFREE
GET/deployer-hunter/alert-statsAlert Performance StatsDeployerFREE
GET/deployer-hunter/best-tokensBest Performing Alert TokensDeployerFREE
GET/deployer-hunter/recent-bondsRecent Bonding Curve GraduationsDeployerFREE
GET/deployer-hunter/{wallet}/trajectoryDeployer TrajectoryDeployerFREE
GET/deployer-hunter/{wallet}/historyDeployer Reputation HistoryDeployerPRO
GET/deployer-hunter/{wallet}/as-ofDeployer Reputation At A DateDeployerPRO
GET/deployer-hunter/{wallet}/rewardsDeployer Creator-Fee RewardsDeployerPRO
GET/alpha/leaderboardAlpha Wallet LeaderboardAlphaFREE
GET/alpha/{wallet}Alpha Wallet ProfileAlphaULTRA
GET/alpha/{wallet}/linkedAlpha Linked WalletsAlphaULTRA
GET/tokens/{mint}/kol-consensusKOL Consensus SnapshotAlphaPRO
GET/tokens/{mint}/peak-historyToken Peak MC HistoryAlphaPRO
GET/tokens/{mint}/cap-tableToken Cap TableAlphaPRO
GET/tokens/{mint}/top-tradersToken Top TradersAlphaPRO
GET/tokens/{mint}/holdersToken Holders & ConcentrationAlphaPRO
GET/tokens/{mint}/locksToken Locks & VestingAlphaPRO
GET/tokens/surgesToken Surges & RevivalsAlphaPRO
GET/tokens/locksNew Token Locks FeedAlphaPRO
GET/tokens/unlocksUpcoming Token UnlocksAlphaPRO
GET/tokens/{mint}/fee-sharesCreator-Fee Sharing (pump.fun)AlphaPRO
GET/tokens/fee-claimsFee-Claim Feed (pump.fun)AlphaPRO
GET/tokens/{mint}/bundleToken Bundle IntelligenceAlphaFREE
GET/tokens/{mint}/buyer-qualityToken Buyer Quality ScoreAlphaFREE
GET/tokens/searchToken Search (symbol / name → mint)AlphaFREE
GET/tokens/{mint}/riskToken Risk / Safety ScoreAlphaPRO
GET/tokens/{mint}/candlesToken OHLCV CandlesAlphaPRO
GET/tokens/{mint}/flowToken Trade FlowAlphaPRO
GET/tokens/{mint}/tradesToken Trade TapeAlphaPRO
GET/tokens/{mint}/poolsToken Liquidity MapAlphaPRO
GET/tokens/{mint}/depthToken Depth / Price ImpactAlphaPRO
POST/tokens/batch/riskBatch Token Risk ScoreAlphaPRO
POST/tokens/batch/buyer-qualityToken Buyer Quality (Batch)AlphaFREE
GET/signalsSignal Scorecard CatalogAlphaFREE
GET/signals/{name}/performanceSignal Scorecard (efficacy)AlphaFREE
GET/tools/searchTools Directory SearchToolsFREE
GET/token/{mint}Token IntelligenceToolsFREE
POST/token/batchToken Intelligence (Batch)ToolsFREE
GET/statusAPI StatusToolsFREE
GET/meAccount & Quota (v1.7)ToolsFREE
GET/manifestsDataset ManifestsToolsFREE
GET/tokensToken Directory (v1.7, PRO+)ToolsPRO
GET/tokens/almost-bondedAlmost-Bonded Tokens (PRO+)ToolsPRO
GET/wallet-tracker/watchlistList WatchlistWallet TrackerPRO
POST/wallet-tracker/watchlistAdd WalletWallet TrackerPRO
DELETE/wallet-tracker/watchlist/{address}Remove WalletWallet TrackerPRO
PATCH/wallet-tracker/watchlist/{address}Update Wallet LabelWallet TrackerPRO
GET/wallet-tracker/tradesWallet Trade HistoryWallet TrackerPRO
GET/wallet-tracker/summaryWallet Stats SummaryWallet TrackerPRO
GET/wallet/{address}Wallet Stats + EnrichmentsWalletPRO
GET/wallet/{address}/flagsPoint-In-Time Wallet FlagsWalletPRO
POST/wallet/batch/tradesBatch Wallet TradesWalletPRO
POST/wallet/batch/classifyBatch Wallet ClassifyWalletPRO
GET/wallet/{address}/pnlWallet PnL (FIFO)WalletPRO
GET/wallet/{address}/positionsOpen PositionsWalletPRO
GET/wallet/{address}/holdingsVerified HoldingsWalletULTRA
GET/wallet/{address}/tradesPaginated TradesWalletPRO
POST/copytrade/subscriptionsCreate Copy-Trade RuleCopy-TradePRO
GET/copytrade/subscriptionsList Copy-Trade RulesCopy-TradePRO
GET/copytrade/subscriptions/{id}Get Copy-Trade RuleCopy-TradePRO
PATCH/copytrade/subscriptions/{id}Update Copy-Trade RuleCopy-TradePRO
DELETE/copytrade/subscriptions/{id}Delete Copy-Trade RuleCopy-TradePRO
GET/copytrade/signalsSignal HistoryCopy-TradePRO
GET/price-alertsList Price AlertsPrice AlertsPRO
POST/price-alertsCreate Price AlertPrice AlertsPRO
GET/price-alerts/{id}Get Price AlertPrice AlertsPRO
PATCH/price-alerts/{id}Update Price AlertPrice AlertsPRO
DELETE/price-alerts/{id}Delete Price AlertPrice AlertsPRO
GET/price-alerts/eventsPrice Alert Event HistoryPrice AlertsPRO
GET/sniper/recentRecent pre-confirm deploys (Pro + Ultra)Sniper AlertsPRO
GET/sniper/by-deployer/{wallet}Sniper feed for a specific deployer (Ultra)Sniper AlertsULTRA
GET/sniper/watchlistList custom deployer watchlist (Ultra)Sniper AlertsULTRA
POST/sniper/watchlistAdd to watchlist (Ultra)Sniper AlertsULTRA
DELETE/sniper/watchlist/{wallet}Remove from watchlist (Ultra)Sniper AlertsULTRA
GET/rhc/kol/feedRHC KOL Trade FeedRobinhood ChainFREE
GET/rhc/kol/leaderboardRHC KOL LeaderboardRobinhood ChainFREE
GET/rhc/kol/hot-tokensRHC KOL Hot TokensRobinhood ChainFREE
GET/rhc/kol/coordinationRHC KOL Coordination DetectorRobinhood ChainFREE
GET/rhc/kol/first-touchesRHC KOL First TouchesRobinhood ChainFREE
GET/rhc/kol/{wallet}RHC KOL ProfileRobinhood ChainFREE
GET/rhc/tradesRHC DEX Trade TapeRobinhood ChainPRO
GET/rhc/tokens/{address}/tradesRHC Token Trade TapeRobinhood ChainFREE
GET/rhc/tokensRHC Token DiscoveryRobinhood ChainPRO
GET/rhc/tokens/newRHC Newest TokensRobinhood ChainFREE
GET/rhc/tokens/recentRHC Recent Tokens (alias)Robinhood ChainFREE
GET/rhc/equitiesRHC Tokenized Equities (stocks & ETFs)Robinhood ChainFREE
GET/rhc/tokens/{address}RHC Token DetailRobinhood ChainFREE
POST/rhc/token/batchRHC Token BatchRobinhood ChainFREE
GET/rhc/tokens/{address}/candlesRHC 1-Minute OHLC CandlesRobinhood ChainPRO
GET/rhc/tokens/{address}/kol-consensusRHC KOL ConsensusRobinhood ChainPRO
GET/rhc/tokens/{address}/buyer-qualityRHC Buyer QualityRobinhood ChainFREE
POST/rhc/tokens/batch/buyer-qualityRHC Batch Buyer QualityRobinhood ChainFREE
GET/rhc/tokens/{address}/bundleRHC Launch-Bundle DetectionRobinhood ChainFREE
GET/rhc/tokens/{address}/top-tradersRHC Top TradersRobinhood ChainPRO
GET/rhc/tokens/{address}/flowRHC Cohort FlowRobinhood ChainPRO
GET/rhc/tokens/{address}/peak-historyRHC Peak HistoryRobinhood ChainPRO
GET/rhc/tokens/{address}/riskRHC Token Risk (EVM-native, live)Robinhood ChainPRO
GET/rhc/tokens/{address}/early-buyersRHC Early BuyersRobinhood ChainPRO
GET/rhc/tokens/{address}/holdersRHC Holders & ConcentrationRobinhood ChainPRO
GET/rhc/lp-eventsRHC Liquidity Removals (rug signal)Robinhood ChainPRO
GET/rhc/tokens/{address}/lp-eventsRHC Token Liquidity RemovalsRobinhood ChainFREE
GET/rhc/tokens/locksRHC Token Locks & Vesting FeedRobinhood ChainPRO
GET/rhc/tokens/{address}/locksRHC Token Locks (per token)Robinhood ChainPRO
GET/rhc/tokens/unlocksRHC Upcoming UnlocksRobinhood ChainPRO
GET/rhc/deployer-hunter/leaderboardRHC Deployer LeaderboardRobinhood ChainFREE
GET/rhc/deployer-hunter/statsRHC Deployer Hunter StatsRobinhood ChainFREE
GET/rhc/deployer-hunter/alertsRHC Deployer AlertsRobinhood ChainFREE
GET/rhc/deployer-hunter/recent-bondsRHC Recent GraduationsRobinhood ChainFREE
GET/rhc/deployer-hunter/best-tokensRHC Best Tokens from Reputable DeployersRobinhood ChainFREE
GET/rhc/deployer-hunter/{address}RHC Deployer DetailRobinhood ChainFREE
GET/rhc/deployer-hunter/{address}/tokensRHC Deployer TokensRobinhood ChainFREE
GET/rhc/deployer-hunter/{address}/historyRHC Deployer Token HistoryRobinhood ChainPRO
GET/rhc/deployer-hunter/{address}/trajectoryRHC Deployer TrajectoryRobinhood ChainFREE
GET/rhc/alpha-walletsRHC Alpha WalletsRobinhood ChainPRO
GET/rhc/wallet/{address}RHC Wallet ProfileRobinhood ChainPRO
GET/rhc/wallet/{address}/pnlRHC Wallet PnLRobinhood ChainPRO
GET/rhc/wallet/{address}/positionsRHC Wallet PositionsRobinhood ChainPRO
GET/rhc/wallet/{address}/tradesRHC Wallet TradesRobinhood ChainPRO
GET/rhc/wallet-tracker/summaryRHC Wallet TrackerRobinhood ChainPRO
GET/rhc/wallet-tracker/watchlistList RHC WatchlistRobinhood ChainPRO
POST/rhc/wallet-tracker/watchlistAdd RHC WalletRobinhood ChainPRO
PATCH/rhc/wallet-tracker/watchlist/{address}Update RHC Wallet LabelRobinhood ChainPRO
DELETE/rhc/wallet-tracker/watchlist/{address}Remove RHC WalletRobinhood ChainPRO
GET/rhc/wallet-tracker/tradesRHC Watchlist Trade FeedRobinhood ChainPRO
GET/rhc/copytrade/subscriptionsList RHC Copy-Trade RulesRobinhood ChainPRO
POST/rhc/copytrade/subscriptionsCreate RHC Copy-Trade RuleRobinhood ChainPRO
GET/rhc/copytrade/subscriptions/{id}Get RHC Copy-Trade RuleRobinhood ChainPRO
PATCH/rhc/copytrade/subscriptions/{id}Update RHC Copy-Trade RuleRobinhood ChainPRO
DELETE/rhc/copytrade/subscriptions/{id}Delete RHC Copy-Trade RuleRobinhood ChainPRO
GET/rhc/copytrade/signalsRHC Signal HistoryRobinhood ChainPRO
GET/rhc/price-alertsList RHC Price AlertsRobinhood ChainPRO
POST/rhc/price-alertsCreate RHC Price AlertRobinhood ChainPRO
GET/rhc/price-alerts/{id}Get RHC Price AlertRobinhood ChainPRO
PATCH/rhc/price-alerts/{id}Update RHC Price AlertRobinhood ChainPRO
DELETE/rhc/price-alerts/{id}Delete RHC Price AlertRobinhood ChainPRO
GET/rhc/price-alerts/eventsRHC Price Alert EventsRobinhood ChainPRO
GET/rhc/kol/coordination/alertsList RHC Coordination RulesRobinhood ChainPRO
POST/rhc/kol/coordination/alertsCreate RHC Coordination RuleRobinhood ChainPRO
GET/rhc/kol/coordination/alerts/{id}Get RHC Coordination RuleRobinhood ChainPRO
PATCH/rhc/kol/coordination/alerts/{id}Update RHC Coordination RuleRobinhood ChainPRO
DELETE/rhc/kol/coordination/alerts/{id}Delete RHC Coordination RuleRobinhood ChainPRO
GET/rhc/kol/first-touches/subscriptionsList RHC First-Touch SubscriptionsRobinhood ChainULTRA
POST/rhc/kol/first-touches/subscriptionsCreate RHC First-Touch SubscriptionRobinhood ChainULTRA
GET/rhc/kol/first-touches/subscriptions/{id}Get RHC First-Touch SubscriptionRobinhood ChainULTRA
PATCH/rhc/kol/first-touches/subscriptions/{id}Update RHC First-Touch SubscriptionRobinhood ChainULTRA
DELETE/rhc/kol/first-touches/subscriptions/{id}Delete RHC First-Touch SubscriptionRobinhood ChainULTRA
POST/webhooksCreate WebhookWebhook mgmtPRO
GET/webhooksList WebhooksWebhook mgmtPRO
GET/webhooks/{id}Webhook Detail + Delivery LogWebhook mgmtPRO
PATCH/webhooks/{id}Update WebhookWebhook mgmtPRO
DELETE/webhooks/{id}Delete WebhookWebhook mgmtPRO
POST/webhooks/testTest WebhookWebhook mgmtPRO
POST/stream/tokenGet WebSocket TokenStreamingPRO
WSwss://madeonsol.com/ws/v1/streamWebSocket StreamingStreamingSee card
WSwss://madeonsol.com/ws/v1/dex-streamDEX Firehose — Real-time DEX Trade Stream (Ultra)StreamingULTRA
GET/stream/sessionsList Active Stream SessionsStreamingPRO
DELETE/stream/sessions/{id}Terminate a Stream SessionStreamingPRO
GET/exportsBulk Parquet ExportsBulk exportsBUSINESS
Every row links to the detailed reference card below. Machine-readable spec: /api/v1/openapi.json.

Latency

From shred to your bot in seconds.

Where the seconds come from — and where they don't.

Stage 1/benchmarks

gRPC detection

Constant-K Nexus · two regions

Two-region dual-stream gRPC fans out every confirmed swap (plus shreds for new deploys). We pick the first-to-arrive per slot. Detection latency is measured live on /benchmarks.

Stage 2~3–10 ms p50

Enrichment

Decode · price · MC · tier · denorm

Decode the DEX program, attach KOL/deployer/alpha tags, stamp market cap, write to Postgres + pg_notify. Measured in production 2026-09-19: KOL trade decode to NOTIFY 3 ms p50, new deploy 10 ms p50.

Stage 3not yet timed

Push to you

WebSocket · webhook · REST cache

Subscribers get the event via the ws-streaming service. Webhook deliveries kick off in parallel with HMAC signing. This hop is not instrumented yet, so we publish no number for it.

End-to-end: paid tiers (and x402 pay-per-call) get KOL trades and deployer alerts as soon as they are processed; measured detection latency is published on /benchmarks. On the free tier, live feeds are delayed 5 minutes (responses carry delay, as_of and an X-Data-Delay header). Leaderboards and token search stay real-time on every tier; wallet PnL needs Pro.

KOL Tracker

KOL trades, leaderboard, coordination.

Real-time wallet activity from 1,100+ tracked Solana KOLs across 14 DEX programs spanning 8 venues.

GET/kol/walletsFREE

KOL Wallet Roster

The tracked-wallet roster every /kol/* route is keyed on — 1,100+ Solana KOLs with name, X profile, strategy tag, and follower counts. Roster only — performance numbers live in /kol/leaderboard and /kol/{wallet}. Search by name (`q`) or filter to one `strategy`. Available on every tier, including free — it's the key space, not data. The Robinhood Chain roster is /rhc/kol/leaderboard.

Parameters

NameTypeDefaultDescription
limitinteger200Max results (1-500)
offsetinteger0Pagination offset (0-5000)
activestringtrue"true", "false", or "all"
qstring—Search by name (substring, case-insensitive, 1-40 chars)
strategystring—Filter by exact strategy_tag (e.g. scalper)

Example Response

{
  "wallets": [
    {
      "wallet_address": "CyaE1VxvBrahnPWkqm5VsdCvyS2QmNht2UFrKJHga54o",
      "name": "Cented",
      "twitter_url": "https://x.com/Cented7",
      "avatar_url": null,
      "strategy_tag": "scalper",
      "twitter_followers": 41145,
      "follow_count": 0,
      "is_active": true,
      "tracked_since": "2026-03-19T12:44:55.646647+00:00"
    }
  ],
  "count": 1,
  "total": 1142,
  "limit": 200,
  "offset": 0,
  "has_more": true,
  "filters": {
    "active": "true",
    "q": null,
    "strategy": null
  }
}
GET/kol/feedFREE

KOL Trade Feed

Real-time trade feed from 1,100+ tracked Solana KOL wallets. Every buy and sell detected within seconds across Pump.fun, Raydium, Jupiter, Orca, and more.

Parameters

NameTypeDefaultDescription
limitinteger50Number of trades (1-100)
beforeISO datetime—Cursor — return trades strictly older than this timestamp. Pass `next_before` from previous response.
sinceISO datetime—Poll cursor — only trades strictly newer than this timestamp. Pass `next_since` from the previous response; if count === limit page down with `before` until you pass your previous since.
includestring—"token" embeds the /token/{mint} snapshot on each row as `token` (at most 20 distinct mints per page; the rest carry token:null and are listed in `include_truncated`)
actionstring—Filter: "buy" or "sell"
kolstring—Filter by KOL wallet address
min_solnumber—Minimum SOL size per trade
min_mc_usdnumber—Lower bound on market_cap_usd_at_trade (trades with unknown MC drop out when set)
max_mc_usdnumber—Upper bound on market_cap_usd_at_trade (must be ≥ min_mc_usd)
token_age_max_mininteger—Max token age in minutes at time of trade
exclude_sellsbooleanfalseDrop sell-side trades
min_kol_winratenumber—Minimum 7d winrate of the KOL (0-100)
strategystring—"scalper", "day_trader", "swing_trader", "hodler", or "mixed"

Example Response

{
  "trades": [
    {
      "wallet_address": "CyaE1Vxv...ga54o",
      "kol_name": "Cented",
      "kol_twitter": "https://x.com/Cented7",
      "kol_strategy_tag": "scalper",
      "kol_auto_strategy_tag": "scalper",
      "kol_winrate_7d": 61.5,
      "kol_winrate_30d": 57.2,
      "kol_early_entry_pct_30d": 42,
      "kol_is_heating_up": true,
      "kol_percentile_pnl_7d": 88,
      "kol_percentile_winrate_7d": 74,
      "token_mint": "tca3tbFf...pump",
      "token_name": "Hands Off Coin",
      "token_symbol": "Hands Off",
      "token_image_url": "https://.../hands-off.png",
      "launchpad": "pumpfun",
      "token_age_minutes": 14,
      "action": "buy",
      "sol_amount": 5.27,
      "token_amount": 19389235.04,
      "market_cap_usd_at_trade": 28430,
      "price_usd_at_trade": 0.0000284,
      "tx_signature": "4fu8vvsF...v1sb",
      "deployer": {
        "wallet": "7dEx...4pQ8",
        "tier": "good",
        "bonding_rate": 0.41
      },
      "deployer_tier": "good",
      "traded_at": "2026-03-25T04:18:43+00:00"
    }
  ],
  "count": 1,
  "data_age_seconds": 3,
  "next_before": "2026-03-25T04:18:43+00:00",
  "next_since": "2026-03-25T04:18:43+00:00",
  "since": null,
  "stream": {
    "channel": "kol:trades",
    "url": "wss://madeonsol.com/ws/v1/stream",
    "token_endpoint": "POST /api/v1/stream/token",
    "subscribe": {
      "type": "subscribe",
      "channels": [
        "kol:trades"
      ]
    }
  }
}
GET/kol/leaderboardFREE

KOL PnL Leaderboard

Ranked leaderboard of KOL wallets by realized PnL in SOL — plus alternative sort axes (winrate, ROI, profit factor, early-entry share, consistency). Ranking windows: today, 7d, 30d, 90d, 180d.

Parameters

NameTypeDefaultDescription
periodstring7dTime period: "today", "7d", "30d", "90d", or "180d"
limitinteger50Number of KOLs (1-100)
offsetinteger0Pagination offset (0-10000)
sortstringpnl"pnl", "winrate", "volume", "avg_roi", "profit_factor", "early_entry_pct", or "consistency"
strategystring—Filter by strategy tag
min_winratenumber—Minimum winrate cutoff (0-100)

Example Response

{
  "leaderboard": [
    {
      "name": "Cented",
      "wallet": "CyaE1Vxv...ga54o",
      "pnl": 1672.8,
      "buy_count": 2960,
      "sell_count": 1525,
      "volume": 8748.72,
      "median_hold_minutes_30d": 47,
      "percentile_early_entry_30d": 82
    },
    {
      "name": "Marcell",
      "wallet": "FixmSpsB...7X",
      "pnl": 630.97,
      "buy_count": 154,
      "sell_count": 51,
      "volume": 3457.54,
      "median_hold_minutes_30d": 120,
      "percentile_early_entry_30d": 61
    }
  ],
  "period": "7d"
}
GET/kol/{wallet}FREE

KOL Wallet Profile

Detailed profile for a specific KOL wallet. Includes PnL stats, trade history, buy/sell counts, total volume, full mv_kol_scores peer-rank block, and optional per-token PnL breakdown via ?include=pnl_by_token,recent_winners,recent_losers.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredSolana wallet address of the KOL
includestring—Comma-separated: "pnl_by_token", "recent_winners", "recent_losers"

Example Response

{
  "kol": {
    "name": "Cented",
    "wallet": "CyaE1Vxv...ga54o",
    "twitter_url": "https://x.com/Cented7"
  },
  "stats": {
    "pnl": 25.71,
    "buy_count": 78,
    "sell_count": 22,
    "volume": 167.89,
    "win_rate": 62.5
  },
  "recent_trades": [
    "..."
  ],
  "pnl_by_token": [
    {
      "token_mint": "tca3tbFf...pump",
      "token_symbol": "HANDS",
      "pnl": 12.4,
      "result": "win"
    }
  ]
}
GET/kol/coordinationPRO

KOL Coordination Detector

Detect tokens being traded by multiple KOLs within a time window. Surfaces coordination signals — when 3+ KOLs converge on the same token, it's often significant. PRO/ULTRA only (BASIC keys receive 403).

Parameters

NameTypeDefaultDescription
periodstring24hTime window: "1h", "6h", "24h", or "7d"
min_kolsinteger3Minimum KOLs trading the same token (2-50)
limitinteger20Max results (1-50)
min_avg_winratenumber—Require cluster avg winrate_7d >= N (0-100)
unique_strategiesboolean—true — require the cluster to span 2+ distinct KOL strategies

Example Response

{
  "coordination": [
    {
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "token_name": "Pepe Reborn",
      "kol_count": 5,
      "total_buys": 12,
      "total_sells": 3,
      "net_sol_flow": 47.82,
      "signal": "accumulating",
      "kols": [
        {
          "name": "Cented",
          "wallet": "CyaE...ga54o"
        },
        {
          "name": "Marcell",
          "wallet": "Fixm...7X"
        }
      ]
    }
  ],
  "period": "24h",
  "min_kols": 3
}
GET/kol/tokens/{mint}FREE

KOL Token Flow

Get all KOL trading activity for a specific token. Returns an aggregate summary (total bought/sold, net flow, accumulating/distributing signal) plus a per-KOL breakdown.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredSolana token mint address

Example Response

{
  "token_mint": "9aK2rFy1...pump",
  "summary": {
    "kol_count": 4,
    "total_bought_sol": 82.5,
    "total_sold_sol": 34.7,
    "net_flow_sol": 47.8,
    "signal": "accumulating"
  },
  "kols": [
    {
      "name": "Cented",
      "wallet": "CyaE1Vxv...ga54o",
      "buy_count": 3,
      "sell_count": 1,
      "total_bought": 25,
      "total_sold": 10.2,
      "net_sol": -14.8,
      "position": "net_buyer",
      "first_trade": "2026-03-24T10:00:00Z",
      "last_trade": "2026-03-25T04:18:00Z"
    }
  ]
}
GET/kol/pairsFREE

KOL Affinity Pairs

Discover which KOLs frequently co-trade the same tokens. Returns pairs ranked by shared token count with agreement rate (both bought within 2 hours). ULTRA adds the list of shared token mints per pair.

Parameters

NameTypeDefaultDescription
periodstring7dTime period: "7d" or "30d"
min_sharedinteger3Minimum shared tokens to qualify (1-20)
limitinteger20Number of pairs (1-50)

Example Response

{
  "pairs": [
    {
      "kol_a": {
        "name": "Murad",
        "wallet": "7QZG...LPZT"
      },
      "kol_b": {
        "name": "traderpow",
        "wallet": "2Dh5...w6"
      },
      "shared_token_count": 7,
      "agreement_rate": 85.71,
      "shared_tokens": [
        "EPjF...Dt1v",
        "7vfC...rXs2"
      ]
    }
  ],
  "period": "7d",
  "min_shared": 3
}
GET/kol/{wallet}/timingFREE

KOL Timing Profile

Entry/exit behavioral analytics for a specific KOL. Hold duration, exit speed distribution (% closed within 1h/6h/24h), average trade sizes, and hour-of-day activity pattern.

Parameters

NameTypeDefaultDescription
walletstring—KOL wallet address (base58, path param)
periodstring30dTime period: "7d" or "30d"

Example Response

{
  "kol": {
    "name": "Murad",
    "wallet": "7QZG...LPZT"
  },
  "timing": {
    "tokens_traded": 42,
    "positions_closed": 28,
    "avg_hold_minutes": 312.5,
    "median_hold_minutes": 180,
    "pct_closed_1h": 21.4,
    "pct_closed_6h": 57.1,
    "pct_closed_24h": 85.7,
    "avg_buy_size_sol": 2.45,
    "avg_sell_size_sol": 3.12,
    "most_active_hours": [
      14,
      15,
      20
    ]
  },
  "period": "30d"
}
GET/kol/tokens/hotFREE

KOL Momentum Tokens

Tokens with accelerating KOL buy interest — early signal before full coordination triggers. Compares recent KOL buy rate (last 25% of period) to baseline. Acceleration > 1.0 means buying is speeding up. ULTRA adds full KOL wallet addresses per token.

Parameters

NameTypeDefaultDescription
periodstring6hTime period: "1h" or "6h"
min_kolsinteger1Minimum KOL buyers (1-20)
limitinteger20Number of tokens (1-50)
min_avg_winratenumber—Require avg winrate_7d of buyers >= N (0-100)
unique_strategiesinteger—Require >= N distinct strategies among buyers

Example Response

{
  "hot_tokens": [
    {
      "token_mint": "EPjF...Dt1v",
      "token_symbol": "PEPE",
      "token_name": "Pepe on Sol",
      "kols_total": 5,
      "kols_recent": 3,
      "acceleration": 2.4,
      "total_buy_sol": 45.2,
      "total_sell_sol": 12.1,
      "net_flow": 33.1,
      "first_kol_buy_age_minutes": 42,
      "kols": [
        {
          "name": "Murad"
        },
        {
          "name": "traderpow"
        }
      ]
    }
  ],
  "period": "6h",
  "min_kols": 1
}
GET/kol/tokens/trendingFREE

KOL Trending Tokens

Tokens ranked by raw KOL buy volume — a pure capital-flow signal showing where KOL money is going right now. Supports 7 time windows from 5 minutes to 12 hours. ULTRA adds full KOL wallet addresses per token.

Parameters

NameTypeDefaultDescription
periodstring1hTime window: "5m", "15m", "30m", "1h", "2h", "4h", or "12h"
min_kolsinteger1Minimum KOL buyers (1-20)
limitinteger20Number of tokens (1-50)

Example Response

{
  "trending": [
    {
      "token_mint": "EPjF...Dt1v",
      "token_symbol": "Wcoin",
      "token_name": "chasing that w",
      "buy_volume_sol": 133.76,
      "sell_volume_sol": 111.79,
      "net_flow_sol": 21.98,
      "buy_count": 24,
      "sell_count": 18,
      "kol_count": 10,
      "latest_buy_age_minutes": 2,
      "kols": [
        {
          "name": "OGAntD"
        },
        {
          "name": "Silver"
        },
        {
          "name": "West"
        }
      ]
    }
  ],
  "period": "1h",
  "min_kols": 1
}
GET/kol/{wallet}/pnlFREE

KOL Wallet PnL

Deep per-wallet PnL breakdown. Returns summary stats (realized PnL, win rate, profit factor, max drawdown, avg ROI, hold times), daily PnL equity curve, and per-token closed positions. ULTRA adds open positions (tokens bought but not yet sold).

Parameters

NameTypeDefaultDescription
walletstring (path)requiredKOL wallet address (base58)
periodstring30dTime period: "7d", "30d", "90d", or "180d"

Example Response

{
  "kol": {
    "name": "OGAntD",
    "wallet": "215n...gQjP",
    "strategy_tag": "day_trader"
  },
  "summary": {
    "realized_pnl_sol": -27.39,
    "win_count": 92,
    "loss_count": 52,
    "win_rate": 63.89,
    "profit_factor": 0.913,
    "max_drawdown_sol": 129.41,
    "avg_roi_pct": 4.65,
    "avg_hold_minutes": 1149.9
  },
  "pnl_curve": [
    {
      "date": "2026-03-19",
      "day_pnl": 4.17,
      "cumulative_pnl": 4.17,
      "trades": 9
    },
    {
      "date": "2026-03-20",
      "day_pnl": 24.95,
      "cumulative_pnl": 29.12,
      "trades": 15
    }
  ],
  "closed_positions": [
    {
      "token_symbol": "BONK",
      "pnl_sol": 43.47,
      "roi_pct": 180.5,
      "hold_minutes": 320,
      "result": "win"
    }
  ],
  "period": "30d"
}
GET/kol/tokens/{mint}/entry-orderFREE

KOL Token Entry Order

Ranked order of KOL first-buyers for a specific token — who entered first and how quickly others followed. Each entry includes seconds_after_first relative to the first KOL entry and percentile ranks (percentile_pnl_7d, percentile_winrate_7d).

Parameters

NameTypeDefaultDescription
mintstring (path)requiredSolana token mint address
limitinteger50Max ranked entries (1-100)

Example Response

{
  "token_mint": "9aK2rFy1...pump",
  "entries": [
    {
      "rank": 1,
      "wallet_address": "CyaE1Vxv...ga54o",
      "kol_name": "Cented",
      "sol_amount": 8.42,
      "token_amount": 24218991.1,
      "traded_at": "2026-03-25T04:18:43+00:00",
      "seconds_after_first": 0,
      "tx_signature": "4fu8vvsF...v1sb",
      "strategy_tag": "sniper",
      "winrate_7d": 68.2,
      "early_entry_pct_30d": 72.1,
      "percentile_pnl_7d": 94.3
    }
  ],
  "count": 1
}
GET/kol/compareFREE

KOL Wallet Compare

Side-by-side comparison of 2-5 KOL wallets — strategy tag, 7d/30d winrates, ROI, profit factor, early-entry %, PnL percentiles, cold/heating-up flags, and 30d overlap tokens (bought by 2+ of the wallets). Max 4 wallets; ULTRA allows 5.

Parameters

NameTypeDefaultDescription
walletsstringrequiredComma-separated list of 2-5 wallet addresses

Example Response

{
  "profiles": [
    {
      "wallet_address": "CyaE1Vxv...ga54o",
      "name": "Cented",
      "strategy_tag": "swinger",
      "winrate_7d": 61.4,
      "winrate_30d": 58.7,
      "roi_30d": 18.4,
      "profit_factor_30d": 1.82,
      "early_entry_pct_30d": 44.1,
      "pnl_30d": 412.5,
      "percentile_pnl_30d": 96.7,
      "is_heating_up": true
    }
  ],
  "overlap": [
    {
      "token_mint": "EPjF...Dt1v",
      "token_symbol": "PEPE",
      "wallets": [
        "CyaE1Vxv...ga54o",
        "FixmSpsB...7X"
      ],
      "first_buy_at": "2026-04-14T08:22:00Z",
      "last_buy_at": "2026-04-14T09:12:00Z"
    }
  ],
  "count": 2
}
GET/kol/alerts/recentPRO

KOL Live Alert Feed

Unified live KOL alert stream — consensus clusters (3+ KOLs buying same token), fresh-token KOL buys (token <30 min old, KOL winrate ≥50), and heating-up wallets (percentile jump). Sorted by detected_at DESC then severity.

Parameters

NameTypeDefaultDescription
windowstring6hLookback window: "1h", "6h", or "24h"
typesstring—Comma-separated: "consensus_cluster", "fresh_token_kol_buy", "heating_up"
limitinteger30Max alerts (1-100)

Example Response

{
  "alerts": [
    {
      "type": "consensus_cluster",
      "severity": "high",
      "detected_at": "2026-04-18T08:42:11Z",
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "details": {
        "kol_count": 5,
        "buy_span_seconds": 142,
        "net_sol_flow": 47.8
      }
    },
    {
      "type": "fresh_token_kol_buy",
      "severity": "medium",
      "detected_at": "2026-04-18T08:39:44Z",
      "token_mint": "4HxQKdTT...pump",
      "wallet_address": "CyaE1Vxv...ga54o",
      "kol_name": "Cented",
      "details": {
        "token_age_minutes": 12,
        "kol_winrate_7d": 64.1
      }
    }
  ],
  "count": 2,
  "window": "15m"
}
GET/kol/first-touchesFREE

KOL First-Touch Signal

Every "first KOL buy on a token mint" event — the moment a tracked KOL is the first of the cohort to touch a token. Filterable by scout tier (S/A/B/C from mv_kol_scout_score), KOL winrate, token age, mint suffix. 38d backtest: top scouts attract ≥3 follow-on KOLs within 4h ~50% of the time vs ~14% baseline. Median lead time before second KOL is 12s — for trading, use the kol:first_touches WS channel instead of polling.

Parameters

NameTypeDefaultDescription
limitinteger50Number of events (1-100, BASIC capped at 20)
sinceISO datetime—Polling cursor — events strictly newer than this
beforeISO datetime—Pagination cursor — events strictly older than this
kolstring—Single KOL wallet (32-44 base58 chars)
min_kol_winrate_7dnumber—0-100
min_scout_tierstring—"S", "A", "B", or "C". Requires n_first_touches_30d ≥ 30.
min_n_touchesinteger30Lower the minimum sample size for scout scoring
strategystring—"scalper", "day_trader", "swing_trader", "hodler", or "mixed"
token_age_max_mininteger—Only events on tokens younger than N minutes
min_first_buy_solnumber—Minimum size of the first KOL buy in SOL
mint_suffixstring—Suffix-filter the token mint (e.g. "pump")
presetstring—"scout" = min_scout_tier=B + min_n_touches=30 + token_age_max_min=60. "fresh_launch" = token_age_max_min=15.
includestring—"followers_4h" attaches retrospective follower count for events ≥4h old

Example Response

{
  "events": [
    {
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "token_name": "Pepe Reborn",
      "token_image_url": "https://...",
      "first_buy_at": "2026-04-26T07:18:42Z",
      "sol_amount": 1.234,
      "token_amount": 4567890.12,
      "tx_signature": "5mmHpg35...",
      "token_age_minutes": 7,
      "first_kol": {
        "name": "Jijo",
        "twitter_url": "https://x.com/jijo",
        "winrate_7d": 67.5,
        "strategy": "scalper",
        "scout_tier": "S",
        "scout_score": 51.1,
        "n_first_touches_30d": 331
      }
    }
  ],
  "count": 1,
  "next_before": "2026-04-26T07:18:42Z",
  "data_age_seconds": 4
}
GET/kol/scouts/leaderboardPRO

Scout KOL Leaderboard

Ranked leaderboard of KOLs by scout score — how often a KOL's first touch on a token attracts a swarm of follow-on KOLs. S-tier scouts attract 3+ follow-on KOLs within 4h ~50% of the time. Filterable by scout tier, sortable by score, first-touch count, or swarm rate. PRO+.

Parameters

NameTypeDefaultDescription
limitinteger50Number of results (1-100)
scout_tierstring—Filter by tier: "S", "A", "B", or "C"
sortstringswarm_3plus_pct"scout_score", "n_first_touches_30d", "swarm_3plus_pct", or "swarm_5plus_pct"

Example Response

{
  "scouts": [
    {
      "wallet": "9xKv...3bPq",
      "name": "Jijo",
      "avatar_url": null,
      "twitter_url": "https://x.com/jijo",
      "scout_tier": "S",
      "first_touches_30d": 331,
      "avg_followers_4h": 3.4,
      "swarm_3plus_pct": 52.1,
      "swarm_5plus_pct": 27.8,
      "computed_at": "2026-08-18T06:00:00Z"
    }
  ],
  "count": 1
}
GET/kol/coordination/historyPRO

Coordination History

Past coordination clusters with outcomes — did the token pump after KOLs converged? Returns clusters with entry MC, peak MC after detection, and outcome classification (hit, miss, pending). Useful for backtesting coordination signals and measuring signal quality over time.

Parameters

NameTypeDefaultDescription
limitinteger50Number of clusters (1-100)
sinceISO datetime—Only clusters detected after this timestamp
min_scoreinteger—Minimum coordination_score (0-100)

Example Response

{
  "clusters": [
    {
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "kol_count": 5,
      "coordination_score": 82,
      "detected_at": "2026-05-20T08:42:11Z",
      "entry_mc_usd": 28430,
      "peak_mc_usd_after": 423000,
      "mc_multiplier": 14.9,
      "outcome": "hit",
      "time_to_peak_minutes": 47
    }
  ],
  "count": 1
}
POST/kol/first-touches/subscriptionsULTRA

Create First-Touch Webhook Subscription

ULTRA only. Create a webhook subscription that delivers kol:first_touch events matching your filters as HMAC-SHA256-signed POSTs. Up to 10 active subscriptions per ULTRA user. Returns webhook_secret ONCE — store it for signature verification.

Parameters

NameTypeDefaultDescription
namestring—Optional label
filtersobject{}{ kol?, mint_suffix?, min_first_buy_sol?, min_scout_tier?, min_n_touches? }
delivery_modestringwebsocket"websocket", "webhook", or "both"
webhook_urlstring—HTTPS URL — required when delivery_mode includes "webhook"

Example Response

{
  "subscription": {
    "id": "a3f17b22-...",
    "name": "S-tier scouts on pump tokens",
    "filters": {
      "min_scout_tier": "S",
      "mint_suffix": "pump"
    },
    "delivery_mode": "webhook",
    "webhook_url": "https://my.bot/hooks/scout",
    "is_active": true,
    "created_at": "2026-04-26T08:00:00Z"
  },
  "webhook_secret": "<32-byte hex — shown once>",
  "note": "Save the webhook_secret — it will not be shown again. ..."
}
GET/kol/first-touches/subscriptionsULTRA

List First-Touch Subscriptions

ULTRA only. Every first-touch subscription you own — filters, delivery mode, MC band, is_active. The webhook secret is never returned here (only once, at creation). ULTRA: 10 subscriptions, BUSINESS: 50.

Example Response

{
  "subscriptions": [
    {
      "id": "a3f17b22-...",
      "name": "S-tier scouts on pump tokens",
      "filters": {
        "min_scout_tier": "S",
        "mint_suffix": "pump"
      },
      "delivery_mode": "webhook",
      "webhook_url": "https://my.bot/hooks/scout",
      "min_mc_usd": null,
      "max_mc_usd": null,
      "is_active": true,
      "created_at": "2026-04-26T08:00:00Z",
      "updated_at": "2026-04-26T08:00:00Z"
    }
  ]
}
GET/kol/first-touches/subscriptions/{id}ULTRA

Get First-Touch Subscription

ULTRA only. Fetch one subscription by UUID. Scoped to your account — a subscription you don't own returns 404.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredSubscription ID

Example Response

{
  "subscription": {
    "id": "a3f17b22-...",
    "name": "S-tier scouts on pump tokens",
    "filters": {
      "min_scout_tier": "S"
    },
    "delivery_mode": "webhook",
    "is_active": true
  }
}
PATCH/kol/first-touches/subscriptions/{id}ULTRA

Update First-Touch Subscription

ULTRA only. Partial update — send only the fields you want changed (name, filters, delivery_mode, webhook_url, is_active, min_mc_usd/max_mc_usd; null clears an MC bound). No new webhook secret is issued; to rotate one, delete and recreate.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredSubscription ID
namestring | null—Label (≤64 chars)
filtersobject—{ kol?, mint_suffix?, min_first_buy_sol?, min_scout_tier?, min_n_touches? }
delivery_modestring—"websocket", "webhook", or "both"
webhook_urlstring | null—HTTPS URL
is_activeboolean—Pause / resume without deleting
min_mc_usdnumber | null—MC floor in USD (null clears)
max_mc_usdnumber | null—MC ceiling in USD (null clears)

Example Response

{
  "subscription": {
    "id": "a3f17b22-...",
    "is_active": false,
    "updated_at": "2026-05-01T10:00:00Z"
  }
}
DELETE/kol/first-touches/subscriptions/{id}ULTRA

Delete First-Touch Subscription

ULTRA only. Permanently delete a subscription. 404 if it isn't yours.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredSubscription ID

Example Response

{
  "deleted": true,
  "id": "a3f17b22-..."
}
GET/kol/coordination/alertsPRO

List Coordination Alert Rules

List your KOL-coordination push-alert rules — active and inactive. A rule fires when at least `min_kols` distinct tracked KOLs converge on the same token inside a rolling window. PRO/ULTRA only (PRO: 5 rules, ULTRA: 20 rules).

Example Response

{
  "rules": [
    {
      "id": "c1a2e0f4-...-e9",
      "name": "4+ KOLs, 15m",
      "min_kols": 4,
      "window_minutes": 15,
      "min_score": 0,
      "include_majors": false,
      "cooldown_min": 30,
      "score_jump_break": 20,
      "delivery_mode": "websocket",
      "webhook_url": null,
      "min_mc_usd": null,
      "max_mc_usd": null,
      "is_active": true,
      "created_at": "2026-06-01T09:00:00Z",
      "updated_at": "2026-06-01T09:00:00Z"
    }
  ]
}
POST/kol/coordination/alertsPRO

Create Coordination Alert Rule

Create a KOL-coordination push-alert rule. Fires when ≥ `min_kols` distinct tracked KOLs buy the same token within `window_minutes`. Returns `webhook_secret` once if webhook delivery is configured. PRO/ULTRA only (PRO: 5 rules, ULTRA: 20 rules).

Parameters

NameTypeDefaultDescription
namestring—Optional label (max 64 chars)
min_kolsinteger5Distinct KOLs required to converge (2-50)
window_minutesinteger15Rolling convergence window (1-60)
min_scoreinteger0Minimum coordination score to fire (0-100)
include_majorsbooleanfalseInclude major/blue-chip tokens (excluded by default)
cooldown_mininteger30Per-token cooldown between fires (1-1440 min)
score_jump_breakinteger20Re-fire during cooldown if score jumps by this much (0-100)
delivery_modestringwebsocket"websocket", "webhook", or "both"
webhook_urlstring—HTTPS URL — required when delivery_mode includes webhook
min_mc_usdnumber—Only fire if the triggering trade's entry MC ≥ this (USD)
max_mc_usdnumber—Only fire if the triggering trade's entry MC ≤ this (USD)

Example Response

{
  "rule": {
    "id": "c1a2e0f4-...-e9",
    "name": "4+ KOLs, 15m",
    "min_kols": 4,
    "window_minutes": 15,
    "delivery_mode": "webhook",
    "webhook_url": "https://my.bot/hooks/coord",
    "is_active": true,
    "created_at": "2026-06-01T09:00:00Z"
  },
  "webhook_secret": "<32-byte hex — shown once>",
  "note": "Save the webhook_secret — it will not be shown again."
}
GET/kol/coordination/alerts/{id}PRO

Get Coordination Alert Rule

Fetch a single coordination alert rule by ID. Returns 404 if not found or not owned by the caller. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
idstring (UUID)requiredRule ID — path parameter

Example Response

{
  "rule": {
    "id": "c1a2e0f4-...-e9",
    "name": "4+ KOLs, 15m",
    "min_kols": 4,
    "window_minutes": 15,
    "min_score": 0,
    "delivery_mode": "websocket",
    "is_active": true,
    "created_at": "2026-06-01T09:00:00Z",
    "updated_at": "2026-06-01T09:00:00Z"
  }
}
PATCH/kol/coordination/alerts/{id}PRO

Update Coordination Alert Rule

Update a coordination alert rule — accepts any field from Create (all optional) plus `is_active`. Send only the fields you want to change. Pass `min_mc_usd`/`max_mc_usd` as null to clear a bound. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
idstring (UUID)requiredRule ID — path parameter
is_activeboolean—Enable or disable the rule
min_kolsinteger—Distinct KOLs required (2-50)
min_scoreinteger—Minimum coordination score (0-100)
delivery_modestring—"websocket", "webhook", or "both"
webhook_urlstring—HTTPS URL (or null to clear)
min_mc_usdnumber—MC floor in USD (null clears)
max_mc_usdnumber—MC ceiling in USD (null clears)

Example Response

{
  "rule": {
    "id": "c1a2e0f4-...-e9",
    "min_kols": 5,
    "min_score": 40,
    "is_active": false,
    "updated_at": "2026-06-02T10:00:00Z"
  }
}
DELETE/kol/coordination/alerts/{id}PRO

Delete Coordination Alert Rule

Permanently delete a coordination alert rule. Returns 404 if not found or not owned by the caller. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
idstring (UUID)requiredRule ID — path parameter

Example Response

{
  "deleted": true
}

Deployer Hunter

Pump.fun deployer reputation.

1.2M+ Pump.fun deployers indexed, 85K+ profiled and tier-graded — real-time launch alerts, bonding history, multiplier stats.

GET/deployer-hunter/statsFREE

Global Deployer Stats

Global deployer hunter statistics: tracked deployer count, signals today, bond rate, and tier distribution (elite/good/rising). Available to all tiers.

Example Response

{
  "tracked_count": 6717,
  "signals_today": 42,
  "bonds_detected": 1893,
  "bond_rate": 28.2,
  "tiers": {
    "elite": 20,
    "good": 62,
    "rising": 119
  }
}
GET/deployer-hunter/leaderboardFREE

Deployer Leaderboard

Ranked list of deployers by bonding rate, recent performance, or total bonds. Full pagination and complete wallet addresses on all tiers.

Parameters

NameTypeDefaultDescription
tierstring—Filter: "elite", "good", "moderate", "rising", or "cold"
sortstringbonding_rateSort: "bonding_rate", "recent_bond_rate", "total_bonded", "last_deploy_at"
limitinteger20Max results (1-50)
offsetinteger0Pagination offset

Example Response

{
  "deployers": [
    {
      "wallet_address": "7xKv...9mPQ",
      "tier": "elite",
      "total_tokens_deployed": 18,
      "total_bonded": 12,
      "bonding_rate": 66.7,
      "recent_bond_rate": 80,
      "recent_outcomes": "BBBDBBBDBB"
    }
  ],
  "total": 20,
  "limit": 20,
  "offset": 0
}
GET/deployer-hunter/{wallet}FREE

Deployer Profile

Full deployer profile with stats, tier classification, outcome history, and Pump.fun token data.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredSolana wallet address of the deployer

Example Response

{
  "deployer": {
    "wallet_address": "7xKv...9mPQ",
    "tier": "elite",
    "total_tokens_deployed": 18,
    "total_bonded": 12,
    "bonding_rate": 66.7,
    "recent_outcomes": "BBBDBBBDBB"
  },
  "pump_tokens": [
    {
      "mint": "abc1...pump",
      "name": "Token A",
      "symbol": "TOKA",
      "bondingCurvePercentage": 100
    }
  ]
}
GET/deployer-hunter/{wallet}/tokensFREE

Deployer Token History

Paginated token history for a deployer with peak market cap and bond timing.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredSolana wallet address
limitinteger20Max results (1-50)
offsetinteger0Pagination offset

Example Response

{
  "tokens": [
    {
      "token_mint": "abc1...pump",
      "token_name": "Token A",
      "token_symbol": "TOKA",
      "deployed_at": "2026-03-20T12:00:00Z",
      "bonded_at": "2026-03-20T12:45:00Z",
      "time_to_bond_minutes": 45,
      "peak_market_cap": 285000
    }
  ],
  "total": 12,
  "limit": 20,
  "offset": 0
}
GET/deployer-hunter/alertsFREE

Deployer Alert Feed

Real-time alerts when tracked deployers launch new tokens. Enriched with deployer reputation (tier, best_token_peak_mc), the deployer's SOL balance at alert time (`deployer_sol_balance`, null for alerts before 2026-06-21), and KOL buy cross-reference. Cursor-paginated via `before` (preferred over `offset` at scale) — limit 1-50 per call, cursor and offset pagination on every tier.

Parameters

NameTypeDefaultDescription
sinceISO datetime—Only alerts after this timestamp
beforeISO datetime—Cursor — only alerts strictly older than this timestamp. Pass `next_before` from previous response.
limitinteger20Max results (1-50)
offsetinteger0Legacy offset pagination (prefer `before` for polling)
tierstring—Filter by deployer tier: elite, good, moderate, rising, or cold.
alert_typestring—Filter by alert_type (e.g. new_deploy, bonded)
prioritystring—"high", "medium", or "low"
min_kol_buysinteger—Only alerts where at least N KOLs bought (1-100)
token_mintstring—Scope to one token's alert history — combine with alert_type=bonded to check if/when a specific token bonded

Example Response

{
  "alerts": [
    {
      "id": 918342,
      "token_mint": "def2...pump",
      "token_name": "New Token",
      "token_symbol": "NEW",
      "alert_type": "new_deploy",
      "title": "Elite deployer launched NEW",
      "message": "7xKv...9mPQ (elite, 71% bond rate) deployed a new token on pump.fun",
      "priority": "high",
      "created_at": "2026-03-28T14:30:00Z",
      "market_cap_at_alert": 6120,
      "deployer_sol_balance": 42.5301,
      "launchpad": "pumpfun",
      "deployers": {
        "wallet_address": "7xKv...9mPQ",
        "tier": "elite",
        "total_tokens_deployed": 17,
        "total_bonded": 12,
        "instant_bonds": 3,
        "bonding_rate": 0.71,
        "recent_outcomes": "BBFBBBBFBB",
        "recent_bond_rate": 0.8,
        "best_token_peak_mc": 2850000,
        "runner_rate": 0.45,
        "runner_tokens": 5,
        "labeled_tokens": 11,
        "avg_time_to_bond_minutes": 38.5
      },
      "kol_buys": {
        "count": 2,
        "total_sol": 7.4,
        "kols": [
          "Cented",
          "Gake"
        ]
      }
    }
  ],
  "limit": 20,
  "offset": 0,
  "next_before": "2026-03-28T14:30:00Z",
  "data_age_seconds": 42
}
GET/deployer-hunter/alert-statsFREE

Alert Performance Stats

Alert performance metrics: bond rate, multiplier distribution (% hitting 2x, 5x, 10x, 50x), and per-tier breakdown.

Parameters

NameTypeDefaultDescription
periodstringallTime period: "7d", "30d", or "all"

Example Response

{
  "period": "all",
  "total_alerts": 1247,
  "total_bonded": 352,
  "bond_rate": 28.2,
  "multiplier_distribution": {
    "2x": 65.3,
    "5x": 41.2,
    "10x": 22.7,
    "50x": 4.8
  },
  "by_tier": {
    "elite": {
      "alerts": 89,
      "bonded": 26,
      "bond_rate": 29.2
    },
    "good": {
      "alerts": 412,
      "bonded": 98,
      "bond_rate": 23.8
    }
  }
}
GET/deployer-hunter/best-tokensFREE

Best Performing Alert Tokens

Top tokens by market cap multiplier from deployer alerts. See which alerted tokens performed best. Up to 20 results.

Parameters

NameTypeDefaultDescription
periodstring7dTime period: "7d", "30d", or "all"
limitinteger5Max results (1-20)

Example Response

{
  "tokens": [
    {
      "token_mint": "ghi3...pump",
      "token_name": "Moon Token",
      "mc_at_alert": 5000,
      "peak_market_cap": 750000,
      "mc_multiplier": 150,
      "deployer_tier": "elite"
    }
  ],
  "period": "7d",
  "limit": 5
}
GET/deployer-hunter/recent-bondsFREE

Recent Bonding Curve Graduations

Latest tokens that graduated the Pump.fun bonding curve with deployer info. Use `since` for incremental polling — response returns `next_since` cursor.

Parameters

NameTypeDefaultDescription
limitinteger20Max results (1-50)
sinceISO datetime—Only bonds strictly newer than this timestamp. Pass `next_since` from the previous response to avoid re-fetching the same rows.
tierstring—Filter by deployer tier: elite, good, moderate, rising, or cold
peak_mc_mininteger—Only bonds that reached at least this peak market cap (USD)

Example Response

{
  "tokens": [
    {
      "token_mint": "jkl4...pump",
      "token_name": "Bonded Token",
      "token_symbol": "BOND",
      "bonded_at": "2026-03-28T13:15:00Z",
      "time_to_bond_minutes": 23,
      "peak_market_cap": 420000,
      "deployers": {
        "wallet_address": "7xKv...9mPQ",
        "tier": "elite",
        "bonding_rate": 66.7
      }
    }
  ],
  "limit": 20
}
GET/deployer-hunter/{wallet}/trajectoryFREE

Deployer Trajectory

Deployer skill curve showing performance evolution over time. Current and longest streaks, rolling 10-token bond rate windows, improvement trend, deployment cadence, and recovery speed.

Parameters

NameTypeDefaultDescription
walletstring—Deployer wallet address (base58, path param)

Example Response

{
  "deployer": {
    "wallet_address": "7xKv...9mPQ",
    "total_tokens_deployed": 45,
    "bonding_rate": 0.267,
    "recent_bond_rate": 0.4,
    "tier": "good"
  },
  "trajectory": {
    "current_streak": {
      "type": "bond",
      "count": 3
    },
    "longest_bond_streak": 5,
    "longest_fail_streak": 8,
    "trend": "improving",
    "avg_days_between_deploys": 2.3,
    "avg_recovery_tokens": 3.1,
    "total_tokens_analyzed": 45
  }
}
GET/deployer-hunter/{wallet}/historyPRO

Deployer Reputation History

A deployer's daily reputation time-series — one snapshot per day of how their stats looked AT THAT POINT, so you can backtest "was this deployer elite at the time it launched token X?" without look-ahead bias. Each snapshot carries the tier, tracking status, cumulative totals, and bond rates the deployer had on that date, letting you reconstruct their reputation as it actually was rather than as it looks today after later launches. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredDeployer wallet address (base58)
limitinteger90Number of daily snapshots to return, most recent first (1-365)

Example Response

{
  "is_deployer": true,
  "wallet": "7xKv...9mPQ",
  "snapshots": [
    {
      "date": "2026-07-05",
      "tier": "elite",
      "is_tracked": true,
      "total_deployed": 18,
      "total_bonded": 12,
      "bonding_rate": 0.667,
      "recent_bond_rate": 0.7,
      "avg_peak_mc": 312000,
      "best_token_peak_mc": 750000
    },
    {
      "date": "2026-07-04",
      "tier": "good",
      "is_tracked": true,
      "total_deployed": 17,
      "total_bonded": 11,
      "bonding_rate": 0.647,
      "recent_bond_rate": 0.6,
      "avg_peak_mc": 298000,
      "best_token_peak_mc": 750000
    }
  ]
}
GET/deployer-hunter/{wallet}/as-ofPRO

Deployer Reputation At A Date

A deployer's reputation exactly as it stood on one date — no look-ahead. Returns the latest write-on-change snapshot at or before `date` (default: today, UTC). `carried: true` means the snapshot was recorded before `date` and hadn't changed by then; no snapshot at or before `date` returns `as_of: false, snapshot: null` — we knew nothing about this deployer yet, nothing is synthesized. A wallet that has never deployed returns `is_deployer: false`. Companion to /deployer-hunter/{wallet}/history (the whole series) and /wallet/{address}/flags?as_of= (every flag source). PRO+.

Parameters

NameTypeDefaultDescription
walletpathrequiredDeployer wallet address (base58)
dateYYYY-MM-DDtoday (UTC)The date to answer for

Example Response

{
  "is_deployer": true,
  "wallet": "UVXV1BHPQFBfDS1tSVb48kXFMkeZ7ojfFkfsVFEAgyE",
  "requested_date": "2026-08-01",
  "as_of": true,
  "snapshot": {
    "snapshot_date": "2026-04-29",
    "carried": true,
    "tier": "good",
    "is_tracked": true,
    "total_deployed": 29,
    "total_bonded": 9,
    "bonding_rate": 0.3103,
    "recent_bond_rate": 0.8,
    "avg_peak_mc": 21243,
    "best_token_peak_mc": 77635
  },
  "first_snapshot_date": "2026-04-07",
  "note": "Latest write-on-change snapshot at or before requested_date. carried=true means the state was recorded earlier and had not changed by requested_date."
}
GET/deployer-hunter/{wallet}/rewardsPRO

Deployer Creator-Fee Rewards

Pump.fun creator-fee rewards, answered two ways that are never merged: `collected` is what actually reached the wallet (direct vault claims, social-handle claims, and shareholder payouts on ANY token — including ones it didn't deploy); `attributed` is every fee payout on tokens this wallet DEPLOYED, whoever received it, split to_self / to_others. A deployer whose attributed total dwarfs its collected total is redirecting its fees — to a launch tool, a KOL, or a social handle — and `redirected_pct` is that gap made explicit. Works for any wallet, not just deployers: a non-deployer that receives fee shares still gets its `collected` side. PRO+.

Parameters

NameTypeDefaultDescription
walletpathrequiredSolana wallet address

Example Response

{
  "wallet": "gVDXhoGbePACvSqN7CZBtQXFW9eyJwsgudPEwSydAkx",
  "is_deployer": true,
  "tokens_in_scope": 96,
  "collected": {
    "sol": 19.288,
    "usdc": 0,
    "usd": 2023.49,
    "direct_claims": {
      "sol": 19.288,
      "usd": 2023.49,
      "count": 8
    },
    "social_claims": {
      "sol": 0,
      "usd": 0,
      "count": 0
    },
    "share_payouts": {
      "sol": 0,
      "usd": 0,
      "count": 0,
      "tokens": 0
    }
  },
  "attributed": {
    "sol": 2448.215,
    "usdc": 0,
    "usd": 256842.27,
    "count": 113,
    "to_self": {
      "sol": 0,
      "usd": 0
    },
    "to_others": {
      "sol": 2448.215,
      "usd": 256842.27
    },
    "redirected_pct": 100,
    "tokens_with_payouts": 19,
    "recipients": 21
  },
  "top_tokens": [
    {
      "mint": "EVgwa5CHBVwk6sCTa4QJrVXYBKngZhYqh2a2ZGDApump",
      "quote": "SOL",
      "total": 1604.9,
      "total_usd": 168370.57,
      "payouts": 30,
      "recipients": 1
    }
  ]
}

Alpha Wallets

First-20-buyer scoring.

Scored from 1.5M+ wallets that bought Pump.fun tokens within the first 20 buyers.

Leaderboard requires at least 1 win and positive net PnL to appear. Bot-confidence signals on ULTRA.
GET/alpha/leaderboardFREE

Alpha Wallet Leaderboard

Leaderboard of statistically profitable wallets scored from 1.5M+ early buyers tracked across Pump.fun tokens. Returns wallets ranked by win rate, realized PnL, or ROI. Bot wallets can be excluded. Up to 100 results per page on every tier (offset pagination); ULTRA widens the ranked window to 500 wallets and adds behavioral signals (bot_confidence, bundle_rate, buy_size_stddev, active_hours).

Parameters

NameTypeDefaultDescription
periodstringallTime period: "7d", "30d", or "all"
min_tokensinteger5Minimum tokens traded to qualify (1–20)
sortstringwin_rateSort by: "win_rate", "pnl", or "roi"
exclude_botsbooleantrueExclude medium/high bot-confidence wallets

Example Response

{
  "leaderboard": [
    {
      "rank": 1,
      "wallet": "7xKv...9mPQ",
      "tokens_traded": 12,
      "wins": 9,
      "losses": 3,
      "win_rate": 0.75,
      "net_pnl_sol": 42.3,
      "total_sol_bought": 95,
      "total_sol_sold": 137.3,
      "roi": 0.445,
      "last_seen": "2026-04-10T14:22:00Z"
    }
  ],
  "total": 1,
  "period": "all",
  "sort": "win_rate",
  "min_tokens": 5,
  "exclude_bots": true
}
GET/alpha/{wallet}ULTRA

Alpha Wallet Profile

Full alpha profile for a single wallet. Returns per-token trade breakdown from early buyer data, aggregate stats, and a bot_signals array explaining the confidence rating (signals that triggered the classification). ULTRA only — BASIC/PRO receive HTTP 403.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredSolana wallet address (base58)

Example Response

{
  "wallet": "7xKv...9mPQ",
  "summary": {
    "tokens_traded": 12,
    "wins": 9,
    "losses": 3,
    "win_rate": 0.75,
    "net_pnl_sol": 42.3,
    "bundle_rate": 0.08,
    "buy_size_stddev": 0.12,
    "active_hours": 14,
    "bot_confidence": "low"
  },
  "positions": [
    {
      "token_symbol": "BONK",
      "pnl_sol": 18.4,
      "roi_pct": 92,
      "result": "win",
      "first_buy_at": "2026-04-01T08:00:00Z"
    }
  ],
  "bot_signals": [
    {
      "signal": "consistent_buy_size",
      "detail": "stddev=0.12 SOL — not fixed-amount"
    }
  ]
}
GET/alpha/{wallet}/linkedULTRA

Alpha Linked Wallets

Find wallets behaviorally linked to a target wallet — these are wallets that co-bought 3+ of the same tokens within a 2-second window. Likely the same actor split across wallets, or a coordinated group. Returns similarity scores. ULTRA only — BASIC/PRO receive HTTP 403.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredSolana wallet address (base58)

Example Response

{
  "wallet": "7xKv...9mPQ",
  "linked_wallets": [
    {
      "wallet_address": "CDiw...XsT9",
      "shared_tokens": 9,
      "similarity_score": 0.81
    },
    {
      "wallet_address": "65NR...oh7B",
      "shared_tokens": 5,
      "similarity_score": 0.45
    }
  ],
  "total": 2
}
GET/tokens/{mint}/kol-consensusPRO

KOL Consensus Snapshot

Aggregated KOL consensus view for a token mint — how many KOLs are accumulating vs distributing, net SOL flow, conviction score, and per-KOL stance breakdown. Useful for gauging whether smart money is bullish or bearish on a specific token right now.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredSolana token mint address (base58)

Example Response

{
  "token_mint": "9aK2rFy1...pump",
  "token_symbol": "PEPE2",
  "consensus": {
    "accumulating_kols": 7,
    "distributing_kols": 2,
    "net_sol_flow": 47.82,
    "conviction_score": 78,
    "signal": "accumulating"
  },
  "kols": [
    {
      "name": "Cented",
      "stance": "accumulating",
      "net_sol": 12.4
    },
    {
      "name": "Marcell",
      "stance": "accumulating",
      "net_sol": 8.7
    }
  ]
}
GET/tokens/{mint}/peak-historyPRO

Token Peak MC History

Historical peak market cap snapshots for a token — ATH market cap, timestamps of each peak, drawdown from ATH, and recovery windows. Useful for gauging whether a token has already peaked or is re-approaching highs. Shows the full MC trajectory from first-seen to present.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredSolana token mint address (base58)

Example Response

{
  "token_mint": "9aK2rFy1...pump",
  "token_symbol": "PEPE2",
  "ath_mc_usd": 750000,
  "ath_at": "2026-05-18T14:22:00Z",
  "current_mc_usd": 423000,
  "drawdown_from_ath_pct": 43.6,
  "peaks": [
    {
      "mc_usd": 285000,
      "peaked_at": "2026-05-15T08:00:00Z",
      "drawdown_pct": 62
    },
    {
      "mc_usd": 750000,
      "peaked_at": "2026-05-18T14:22:00Z",
      "drawdown_pct": 43.6
    }
  ],
  "first_seen_at": "2026-05-14T10:00:00Z"
}
GET/tokens/{mint}/cap-tablePRO

Token Cap Table

First 10–20 non-deployer early buyers for a token mint, enriched with historical win rates, realized PnL, bot confidence, KOL identity, and bundle flags. Each buyer also carries their in-token exit/PnL: realized_pnl_sol (SOL profit taken on this mint), total_sol_bought / total_sol_sold, first_sell_at (null if never sold), and still_holding — so you can see which smart-money buyers have already cashed out vs are still in. Includes a summary block with buyer_quality_score. PRO: top 10 with full wallets. ULTRA: top 20 with full wallets.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)

Example Response

{
  "mint": "EPjF...Dt1v",
  "buyers": [
    {
      "rank": 1,
      "wallet": "7xKv...9mPQ",
      "first_buy_sol": 2.5,
      "first_buy_at": "2026-04-01T10:00:00Z",
      "is_bundle": false,
      "is_kol": true,
      "kol_name": "Cented",
      "bot_confidence": "low",
      "historical_win_rate": 0.72,
      "historical_pnl_sol": 38.4,
      "historical_tokens": 15,
      "realized_pnl_sol": 12.8,
      "total_sol_bought": 2.5,
      "total_sol_sold": 15.3,
      "first_sell_at": "2026-04-01T11:42:00Z",
      "still_holding": true
    }
  ],
  "summary": {
    "known_alpha_wallets": 6,
    "known_kols": 2,
    "bundle_buyers": 1,
    "buyer_quality_score": 74,
    "confidence": "medium",
    "signal": "positive"
  }
}
GET/tokens/{mint}/top-tradersPRO

Token Top Traders

Every wallet that traded this mint, ranked by realized SOL PnL (or ROI) — the most profitable traders on the token, early or late. Uses the same average-cost-basis method as /wallet/{address}/pnl, so a wallet's realized_pnl_sol matches across endpoints. Each trader is enriched with reputation flags (is_kol, is_alpha_tracked, bot_confidence, historical win rate) so you can tell smart money from a bot round-trip. Distinct from cap-table (first ~20 early buyers by entry order). PRO: top 25. ULTRA: top 100.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)
limitint25Max traders (capped at 25 PRO / 100 ULTRA)
sortstringpnlpnl | roi
window_daysint90Look-back window (1–180)
min_bought_solnumber0.1Drop dust wallets below this bought-SOL

Example Response

{
  "mint": "EPjF...Dt1v",
  "sort": "pnl",
  "window_days": 90,
  "traders": [
    {
      "rank": 1,
      "wallet": "7xKv...9mPQ",
      "trades": 14,
      "buys": 6,
      "sells": 8,
      "bought_sol": 12.5,
      "sold_sol": 41.2,
      "realized_pnl_sol": 28.7,
      "unrealized_pnl_sol": 3.1,
      "total_pnl_sol": 31.8,
      "held_value_sol": 3.1,
      "roi": 2.29,
      "still_holding": true,
      "first_trade_at": "2026-06-01T10:00:00Z",
      "last_trade_at": "2026-06-02T14:20:00Z",
      "is_kol": true,
      "kol_name": "Cented",
      "is_alpha_tracked": true,
      "bot_confidence": "low",
      "historical_win_rate": 0.72,
      "historical_pnl_sol": 38.4,
      "historical_tokens": 15
    }
  ],
  "summary": {
    "returned": 25,
    "known_kols": 3,
    "known_alpha_wallets": 9,
    "net_realized_pnl_sol": 142.6
  }
}
GET/tokens/{mint}/holdersPRO

Token Holders & Concentration

Live holder census read from the ledger at confirmed: every token account of the mint (mint-scoped getProgramAccounts), merged per owner — so holder_count is EXACT (distinct non-zero owners minus pools/curves/burns), not a trade-derived estimate. Ranks 1–100 retained; top1/10/20/50/100 shares over the circulating denominator. Each disclosed owner is labelled from our wallet intelligence (deployer / kol / early_buyer / bundle / bot / dump_cluster — empty means unknown to us, not clean). Excluded owners are NAMED: pool (+ dex, pool_address), bonding_curve (pump.fun / LaunchLab), burn, or program_account when we cannot attribute the PDA; pool_pct / burned_pct / program_pct split the exclusion. Mega-caps the provider refuses fall back to a top-20 view with holder_count null and census_fallback_reason set. Big tokens can take 5–30 s upstream: you get 503 holder_scan_in_progress with Retry-After 20 while the scan finishes into the cache. Amounts are raw u64 strings. PRO shows ranks 1–10, ULTRA 1–50, BUSINESS 1–100; the maths is tier-independent.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)

Example Response

{
  "mint": "RmtM…NDYk",
  "slot": 361248112,
  "holders": [
    {
      "rank": 1,
      "owner": "7xKq…p3Vw",
      "token_accounts": [
        "9Ab2…kL1m"
      ],
      "amount_raw": "48210000000000",
      "amount": 48210000,
      "pct_of_supply": 4.821,
      "pct_of_circulating": 5.18,
      "labels": [
        "early_buyer",
        "bundle"
      ],
      "kol_name": null,
      "early_buyer_rank": 3,
      "bot_confidence": "low",
      "historical_win_rate": null
    }
  ],
  "count": 10,
  "disclosed": 10,
  "excluded": [
    {
      "owner": "DBdt…Qk9e",
      "token_accounts": [
        "3Fh1…yT8u"
      ],
      "amount_raw": "26288000000000",
      "pct_of_supply": 2.6288,
      "reason": "pool",
      "dex": "pumpswap",
      "pool_address": "DBdt…Qk9e"
    },
    {
      "owner": "3b3W…hLWQ",
      "token_accounts": [
        "Hn7z…c2Qa"
      ],
      "amount_raw": "13155000000000",
      "pct_of_supply": 1.3155,
      "reason": "pool",
      "dex": "meteora",
      "pool_address": "3b3W…hLWQ"
    }
  ],
  "concentration": {
    "holder_count": 7724,
    "holder_count_source": "census",
    "token_accounts_nonzero": 7731,
    "supply_raw": "1000000000000000",
    "circulating_raw": "960676000000000",
    "decimals": 6,
    "top1_share": 5.18,
    "top10_share": 21.4,
    "top20_share": 29.7,
    "top50_share": 41.2,
    "top100_share": 49.9,
    "pool_and_program_pct": 6.9324,
    "pool_pct": 3.9444,
    "burned_pct": 0,
    "program_pct": 2.988,
    "deployer_pct": 0,
    "kol_pct": 1.2,
    "early_buyer_pct": 9.8,
    "bundle_pct": 6.1,
    "bot_pct": 2.3,
    "dump_cluster_pct": 0.4,
    "ranked_owners_available": 100
  },
  "source": {
    "method": "getProgramAccounts_census",
    "token_program": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
    "rpc_cap": 100,
    "commitment": "confirmed",
    "scan_ms": 412,
    "census_fallback_reason": null
  }
}
GET/tokens/{mint}/locksPRO

Token Locks & Vesting

Every on-chain token lock / vesting contract on a mint — Streamflow streams, Jupiter Lock vesting escrows, Bonfida token-vesting — decoded from the locker programs' account state, with a LIVE view computed at request time: what is still locked right now, what has unlocked, what is claimable, and the next unlock event. The summary rolls up locked/deposited totals (raw, ui, usd, % of supply), the 7d/30d forward unlock schedule, distinct lockers, and how many active contracts the sender can still cancel — 'did the team lock, how much, until when, and can they pull it'. Token/vesting locks only (LP locks are a different thing). Amounts are base-unit strings; ui/usd/pct are null when decimals/price are unknown. PRO+.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)
statusstring—Optional filter: active | completed | cancelled | closed
programstring—Optional filter: streamflow | jupiter_lock | bonfida_vesting
limitnumber2001–500 rows (summary always covers the whole mint)

Example Response

{
  "mint": "eZBK…pump",
  "token": {
    "symbol": "ENTROPY",
    "decimals": 6,
    "price_usd": 0.0000266,
    "supply": 999120418,
    "facts_resolved": true
  },
  "summary": {
    "lock_count": 4,
    "active_count": 3,
    "by_program": {
      "streamflow": 4
    },
    "by_kind": {
      "lock": 4
    },
    "distinct_lockers": 1,
    "locked": 70460647,
    "locked_usd": 1875.53,
    "locked_pct_of_supply": 7.05,
    "unlocking_7d": 0,
    "unlocking_30d": 0,
    "next_unlock": {
      "at": "2026-12-25T05:00:00Z",
      "kind": "cliff",
      "amount": 20000000,
      "amount_usd": 532.36,
      "lock_account": "825J…4ei1"
    },
    "active_cancelable_by_sender": 0
  },
  "locks": [
    {
      "lock_account": "825J…4ei1",
      "program": "streamflow",
      "kind": "lock",
      "status": "active",
      "sender": "3Vd4…kQ2p",
      "recipient": "3Vd4…kQ2p",
      "name": "Team lock",
      "amount_raw": "20000000000000",
      "amount": 20000000,
      "amount_usd": 532.36,
      "locked": 20000000,
      "unlocked": 0,
      "claimable": 0,
      "cliff_at": "2026-12-25T05:00:00Z",
      "end_at": "2026-12-25T05:00:01Z",
      "period_seconds": 1,
      "continuous": true,
      "cancelable_by_sender": false,
      "transferable": false,
      "next_unlock": {
        "at": "2026-12-25T05:00:00Z",
        "kind": "cliff",
        "amount": 20000000
      },
      "created_at": "2026-08-17T18:44:37Z",
      "tx_signature": "5kZ…Qw"
    }
  ]
}
GET/tokens/surgesPRO

Token Surges & Revivals

Token momentum fires, newest first. surge = a token < 30 min old running vs its LAUNCH market cap — tier early (≤10 min, ≥$12k, ≥3× launch MC), strong (≤30 min, ≥$30k, ≥6× and ≥2× the lowest sample of the last 3 min), breakout (≤2 min, ≥$45k, ≥8×); each tier fires once per mint. revival = a token with no trade candle for ≥24 h (measured across every DEX we price, so graduated Raydium/Meteora tokens count) that started trading again, CONFIRMED by ≥5 buys + ≥$500 buy volume + ≥1.5× the pre-dormancy MC — never by the price mark alone. Every fire carries the burst tape (unique buyers where wallet data exists, null otherwise), KOL involvement, the first-20 early-buyer cohort (bundled / sold / sniper wallets), deployer reputation and risk_flags[] with documented thresholds. Fires ≥65 min old carry their +1 h outcome; stats=1 prints per-tier hit-rates, out-of-sample by construction. Pushed live on the token:surges WebSocket channel and as webhook events token:surge / token:revival. PRO+.

Parameters

NameTypeDefaultDescription
kindstringallsurge | revival
tierstringallearly | strong | breakout (surges only — 400 with kind=revival)
since | beforeISO datetimenoneCursors on fired_at (pagination.next_since / next_before)
mint | launchpad | deployer_tierstringnoneScope to one mint / launchpad (pumpfun, launchlab, pumpswap…) / deployer tier
min_mc_usd | max_mc_usd | min_buysnumbernoneMarket-cap band and buys-on-the-tape floor at fire time
exclude_flagsstringnoneComma list of risk flags; rows carrying ANY are dropped (unknown flag → 400 + known_flags[])
only_cleanbooleanfalseOnly fires with no risk flags
stats | daysboolean | numberfalse | 7Add per-(kind, tier) +1h hit-rates over the last N days (1–30)
limitnumber501–200

Example Response

{
  "events": [
    {
      "id": 4812,
      "kind": "surge",
      "tier": "strong",
      "mint": "9kQu…pump",
      "symbol": "RUNNER",
      "launchpad": "pumpfun",
      "fired_at": "2026-08-28T10:00:00Z",
      "birth_source": "sniper",
      "age_seconds": 450,
      "market_cap_usd": 38400,
      "liquidity_usd": 9100,
      "baseline_mc_usd": 5600,
      "baseline_source": "launch",
      "mc_multiple": 6.857,
      "mc_change_3m_pct": 112.4,
      "tape": {
        "buys": 96,
        "sells": 31,
        "buy_volume_usd": 21300,
        "sell_volume_usd": 6900,
        "unique_buyers": 58,
        "trades_per_wallet": 2.02,
        "wallet_data_available": true
      },
      "kol": {
        "buyers": 2,
        "names": [
          "alpha_scout",
          "degen_dan"
        ]
      },
      "early_buyers": {
        "count": 20,
        "bundled": 0,
        "cohort_sol": 18.4,
        "sold": 3,
        "sniper_wallets": 1
      },
      "deployer": {
        "tier": "good",
        "runner_rate": 0.27,
        "labeled_tokens": 22
      },
      "risk_flags": [],
      "outcome": {
        "mc_usd_1h_after": 51200,
        "peak_mc_usd_1h_after": 74800,
        "mc_1h_multiple": 1.333,
        "peak_1h_multiple": 1.948,
        "priced_after_1h": true
      }
    },
    {
      "id": 4813,
      "kind": "revival",
      "tier": null,
      "mint": "8vdc…pump",
      "symbol": "GHOST",
      "primary_dex": "pumpswap",
      "fired_at": "2026-08-28T10:05:00Z",
      "dormant_hours": 412.6,
      "prev_mc_usd": 22100,
      "market_cap_usd": 61000,
      "mc_vs_prev_multiple": 2.76,
      "peak_mc_usd": 340000,
      "pct_of_peak": 17.94,
      "tape": {
        "buys": 27,
        "sells": 4,
        "buy_volume_usd": 8900,
        "unique_buyers": 19,
        "wallet_data_available": true
      },
      "kol": {
        "buyers": 1,
        "names": [
          "cto_hunter"
        ]
      },
      "early_buyers": {
        "count": 20,
        "bundled": 2,
        "sold": 17,
        "sniper_wallets": 0
      },
      "deployer_tier": "moderate",
      "risk_flags": [
        "early_buyers_exiting"
      ],
      "outcome": null
    }
  ],
  "pagination": {
    "limit": 50,
    "count": 2,
    "has_more": true,
    "next_since": "2026-08-28T10:05:00Z",
    "next_before": "2026-08-28T10:00:00Z"
  },
  "stats": {
    "days": 7,
    "rows": [
      {
        "kind": "surge",
        "tier": "strong",
        "fires": 412,
        "with_outcome": 398,
        "up_1h_pct": 46.5,
        "median_peak_multiple": 1.41,
        "doubled_1h_pct": 18.3
      }
    ]
  },
  "stream": {
    "channel": "token:surges",
    "url": "wss://madeonsol.com/ws/v1/stream"
  },
  "definitions": {
    "surge": {
      "early": {
        "max_age_seconds": 600,
        "min_market_cap_usd": 12000,
        "min_launch_multiple": 3
      }
    },
    "revival": {
      "min_dormant_hours": 24,
      "min_buys": 5,
      "min_buy_volume_usd": 500
    }
  }
}
GET/tokens/locksPRO

New Token Locks Feed

Cross-token feed of NEW lock / vesting contracts, newest first — who just locked tokens, of what mint, how much, until when. Same row shape as /tokens/{mint}/locks plus a token block (symbol, decimals, price, market cap). Poll with since= (cursor = pagination.next_since) or subscribe to the token:locks WebSocket channel for a push the moment the contract lands (with filters.lifecycle:true the channel also pushes claims, cancels, closes, updates and upcoming / available unlocks, since 2026-09-23). Filters: mint, sender, recipient, program, kind, status, min_usd, min_pct_of_supply. PRO+.

Parameters

NameTypeDefaultDescription
sinceISO datetimenoneOnly contracts created after this instant (use pagination.next_since)
beforeISO datetimenonePage back — only contracts created before this instant
mint | sender | recipientstringnoneScope to one mint / locker / beneficiary
program | kind | statusstring—streamflow|jupiter_lock|bonfida_vesting · lock|vesting · active|completed|cancelled|closed
min_usd | min_pct_of_supplynumbernoneDeposited amount floor (needs price / supply)
limitnumber501–100

Example Response

{
  "locks": [
    {
      "lock_account": "825J…4ei1",
      "program": "streamflow",
      "kind": "lock",
      "status": "active",
      "mint": "eZBK…pump",
      "token": {
        "symbol": "ENTROPY",
        "decimals": 6,
        "price_usd": 0.0000266
      },
      "sender": "3Vd4…kQ2p",
      "amount": 20000000,
      "amount_usd": 532.36,
      "amount_pct_of_supply": 2,
      "locked": 20000000,
      "cliff_at": "2026-12-25T05:00:00Z",
      "end_at": "2026-12-25T05:00:01Z",
      "cancelable_by_sender": false,
      "created_at": "2026-08-17T18:44:37Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "count": 1,
    "has_more": true,
    "next_since": "2026-08-17T18:44:37Z",
    "next_before": "2026-08-17T18:44:37Z"
  },
  "stream": {
    "channel": "token:locks",
    "url": "wss://madeonsol.com/ws/v1/stream"
  }
}
GET/tokens/unlocksPRO

Upcoming Token Unlocks

Upcoming unlock EVENTS across all active lock / vesting contracts inside a window — cliffs, periodic releases (hourly or coarser) and final unlocks — i.e. which tokens have locked supply hitting the market this week, how much, from whose lock. One entry per active contract = its next unlock event in the window (event = cliff | period | final | tranche) plus window_amount_* = that contract's total release over the whole window. Continuous per-second streams contribute only their cliff/final events. Sort soonest (default), largest_usd or largest_pct. PRO+.

Parameters

NameTypeDefaultDescription
withinstring7d1h | 6h | 24h | 3d | 7d | 14d | 30d | 90d
mint | program | kindstring—Optional filters to scope the scan
min_usd | min_pct_of_supplynumbernoneFloor on the next-event amount
sortstringsoonestsoonest | largest_usd | largest_pct
limitnumber501–200

Example Response

{
  "window": {
    "within": "7d",
    "from": "2026-08-17T18:47:00Z",
    "to": "2026-08-24T18:47:00Z"
  },
  "unlocks": [
    {
      "unlock_at": "2026-08-24T04:00:00Z",
      "in_seconds": 551580,
      "event": "cliff",
      "amount": 91588000,
      "amount_usd": 6490.74,
      "amount_pct_of_supply": 9.16,
      "window_amount": 91588000,
      "mint": "Epht…FwSg",
      "token": {
        "symbol": "XYZ",
        "decimals": 6,
        "price_usd": 0.0000709
      },
      "lock": {
        "lock_account": "9nQd…Lp3a",
        "program": "streamflow",
        "kind": "lock",
        "sender": "7Hh2…mR1c",
        "locked": 91588000,
        "cliff_at": "2026-08-24T04:00:00Z",
        "cancelable_by_sender": false
      }
    }
  ],
  "pagination": {
    "limit": 50,
    "count": 1,
    "total_in_window": 902,
    "has_more": true
  }
}
GET/tokens/{mint}/fee-sharesPRO

Creator-Fee Sharing (pump.fun)

Who a pump.fun coin's creator fees are redirected to: the on-chain SharingConfig (pump_fees PDA) with each shareholder's bps, is_admin / is_social_pda (fees earmarked for an X account etc.), redirected_bps and social_bps — plus the distribution history (every distribute_creator_fees payout, pro-rata per shareholder), what each recipient has received, past recipients, and the config change log. Config is read from our stream when the mint has ever had a non-default split, otherwise live from chain, so is_default:true (100% to the creator) is a real answer. History starts 2026-08-17. PRO+.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredpump.fun coin mint

Example Response

{
  "mint": "E2rQ…npump",
  "config": {
    "sharing_config": "HY8s…Lw1a",
    "admin": "CBV9…XT4J",
    "status": "Active",
    "is_default": false,
    "redirected_bps": 10000,
    "redirected_pct": 100,
    "social_bps": 0,
    "shareholders": [
      {
        "address": "BYp2…QoY4",
        "share_bps": 10000,
        "share_pct": 100,
        "is_admin": false,
        "is_social_pda": false,
        "social": null,
        "received_raw": "5142699911",
        "received": 5.1427,
        "received_usd": 389.71,
        "payout_count": 1,
        "last_payout_at": "2026-08-17T19:21:18Z"
      }
    ],
    "source": "stream"
  },
  "quote": {
    "symbol": "SOL",
    "decimals": 9,
    "sol_usd": 75.78
  },
  "distributions": {
    "count": 1,
    "total_raw": "5142699911",
    "total": 5.1427,
    "total_usd": 389.71,
    "last_at": "2026-08-17T19:21:18Z"
  },
  "history": [
    {
      "type": "shares_updated",
      "at": "2026-08-17T19:20:02Z",
      "shareholders": [
        {
          "address": "BYp2…QoY4",
          "share_bps": 10000
        }
      ]
    }
  ]
}
GET/tokens/fee-claimsPRO

Fee-Claim Feed (pump.fun)

Every decoded pump.fun fee event, newest first: distribution (creator fees paid out pro-rata to the SharingConfig shareholders — fees redirected to others — with payouts[] per address), social_claim (fees earmarked for a platform identity — platform 2 = X, user_id = platform-native numeric id — claimed to a wallet), shares_created / updated / reset, creator_transferred, creator_claim and holder_distribution (creator fees airdropped pro-rata to token holders; both excluded unless requested). Default 100%-to-creator configs and zero-amount distributions are not stored. since= cursor or WS channel token:fee_claims. PRO+.

Parameters

NameTypeDefaultDescription
typestringall but creator_claim, holder_distributionComma list: distribution, social_claim, shares_created, shares_updated, shares_reset, creator_transferred, creator_claim, holder_distribution
mint | recipient | actorstringnoneScope to a coin / payout recipient / signer
social_platform | social_user_idstringnoneScope to a social identity (2 = X; numeric user id)
min_solnumbernoneAmount floor in SOL
since | beforeISO datetimenoneCursors on the event time
limitnumber501–100

Example Response

{
  "events": [
    {
      "type": "distribution",
      "at": "2026-08-17T19:21:18Z",
      "mint": "E2rQ…npump",
      "amount": 5.1427,
      "amount_usd": 389.71,
      "quote": "SOL",
      "payouts": [
        {
          "address": "BYp2…QoY4",
          "share_bps": 10000,
          "amount": 5.1427,
          "amount_usd": 389.71
        }
      ]
    },
    {
      "type": "social_claim",
      "at": "2026-08-17T16:46:26Z",
      "mint": null,
      "recipient": "9kQz…Ht2c",
      "amount": 42.18,
      "amount_usd": 3196.4,
      "social": {
        "platform": 2,
        "platform_label": "x",
        "user_id": "22895867",
        "pda": "71zp…BmSd"
      }
    }
  ],
  "pagination": {
    "limit": 50,
    "count": 2,
    "has_more": true,
    "next_since": "2026-08-17T19:21:18Z"
  },
  "stream": {
    "channel": "token:fee_claims"
  }
}
GET/tokens/{mint}/bundleFREE

Token Bundle Intelligence

Resolves a token's same-slot bundle cohort — the wallets that bought within a single slot at/near launch (≥3 wallets in one slot flags is_bundle) — and, critically, how much of supply that cohort still holds. Computed from confirmed token_trades, not a shred/mempool feed. The headline field is held_pct_of_supply: the cohort's net held tokens ÷ token supply, clamped to 0–1. bundle_kind is atomic_tx (all buys in one transaction), same_slot (multiple txs, one slot), or none. Caveats: buy_volume is cumulative buy volume and can exceed supply; tokens_held is a swap-derived net proxy (buys minus sells), not a holder-account census. All tiers, field-gated: BASIC gets the scalar bundle block only; PRO adds the top-10 cohort wallets with flags (held_ratio, has_sold, atomic, is_kol); ULTRA adds the full cohort plus KOL/alpha identity (kol_name, win_rate, bot_confidence, tokens_held).

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)

Example Response

{
  "mint": "EPjF...Dt1v",
  "bundle": {
    "wallet_count": 5,
    "bundle_kind": "same_slot",
    "held_ratio": 0.32,
    "held_pct_of_supply": 0.28,
    "fully_exited": false,
    "buy_volume": 41800000,
    "tokens_held": 280000000
  },
  "wallets": [
    {
      "rank": 1,
      "wallet": "7xKv...9mPQ",
      "held_ratio": 0.71,
      "has_sold": false,
      "atomic": true,
      "is_kol": true,
      "kol_name": "Cented",
      "win_rate": 0.68,
      "bot_confidence": "low",
      "tokens_held": 120000000
    },
    {
      "rank": 2,
      "wallet": "3nQd...42aa",
      "held_ratio": 0,
      "has_sold": true,
      "atomic": true,
      "is_kol": false,
      "kol_name": null,
      "win_rate": null,
      "bot_confidence": "high",
      "tokens_held": 0
    }
  ]
}
GET/tokens/{mint}/buyer-qualityFREE

Token Buyer Quality Score

0–100 buyer quality score for a token's early-buyer cohort. Score formula: average win rate of non-bot early buyers × 100, plus KOL bonus (first KOL = +10, each extra = +5, max +20), minus bundle penalties (−5 per bundled buyer in top 10, −15 if >10/20 are bundles), minus bot domination (−20 if >50% are high-confidence bots). Returns score, confidence, signal, and full breakdown (alpha_wallet_count, kol_count, bundle_buyer_count, avg_historical_win_rate, bot_dominated, dump_cluster_count, recycled_early_buyer_count). dump_cluster_count = first-20 buyers on the rolling dump-cluster list (wallets whose recent first-20 appearances are exclusively on tokens that peaked <15 min after deploy — out-of-sample, 3+ such wallets predicted a sub-15-min peak 94% of the time vs 61% base). recycled_early_buyer_count = first-20 buyers with 5+ recent first-20 appearances of any kind; a heavily recycled cohort with dump_cluster_count 0 historically leans the other way. Informational fields — they do not move the score. List refreshes daily over a trailing 42-day window. When dump_cluster_count ≥ 1 the response also carries signal_stats.dump_cluster_count — the live out-of-sample efficacy of that value (bucket k>=1 / k>=3 / k>=5, hit_rate, base_rate, lift, sample_n, window_days, as_of, summary) so the raw count is readable. Results cached 5 minutes per mint. For bulk scoring use POST /tokens/batch/buyer-quality.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)

Example Response

{
  "mint": "EPjF...Dt1v",
  "score": 74,
  "confidence": "medium",
  "signal": "positive",
  "cached_at": "2026-04-14T12:00:00Z",
  "breakdown": {
    "alpha_wallet_count": 6,
    "kol_count": 2,
    "bundle_buyer_count": 1,
    "avg_historical_win_rate": 68.5,
    "bot_dominated": false,
    "wallets_with_history": 9,
    "qualified_win_rate_wallets": 7,
    "dump_cluster_count": 3,
    "recycled_early_buyer_count": 4
  },
  "signal_stats": {
    "dump_cluster_count": {
      "value": 3,
      "bucket": "k>=3",
      "outcome": "dump",
      "hit_rate": 0.94,
      "base_rate": 0.61,
      "lift": 1.54,
      "sample_n": 349,
      "window_days": 14,
      "as_of": "2026-04-14T03:00:00Z",
      "summary": "dump_cluster_count=3 (k>=3): 94% of such tokens dumped vs 61% base (1.54× lift), n=349, 14d OOS"
    }
  }
}
GET/tokens/searchFREE

Token Search (symbol / name → mint)

Resolve a ticker or name to a mint. Ranked, not just matched: exact ticker first, then symbol prefix, then name prefix, then trigram-fuzzy — and inside each tier by liquidity, so "bonk" returns the $2M-liquidity Bonk before ten thousand squats named BONK. Every row carries market cap, liquidity, primary DEX and last trade so you can disambiguate in one hop and pass the mint on to /token/{mint}. Searches OUR universe (memecoin / launchpad tokens the price tracker has seen): native SOL and blue-chips are excluded by design and the response says so in a note. Free tier.

Parameters

NameTypeDefaultDescription
qstringrequiredTicker or name fragment (1-64 chars)
limitinteger10Max results (1-50)

Example Response

{
  "q": "bonk",
  "count": 2,
  "results": [
    {
      "mint": "DezXAZ8z...B263",
      "symbol": "BONK",
      "name": "Bonk",
      "match": "exact_symbol",
      "market_cap_usd": 1420000000,
      "liquidity_usd": 2100000,
      "primary_dex": "raydium",
      "last_trade_at": "2026-08-18T09:41:02Z"
    },
    {
      "mint": "7GCihgDB...pump",
      "symbol": "BONKAI",
      "name": "Bonk AI",
      "match": "symbol_prefix",
      "market_cap_usd": 84000,
      "liquidity_usd": 12400,
      "primary_dex": "pumpswap",
      "last_trade_at": "2026-08-18T09:12:44Z"
    }
  ]
}
GET/tokens/{mint}/riskPRO

Token Risk / Safety Score

Transparent 0–100 rug-risk score for a token mint, with a full per-factor breakdown so the score is auditable — not an opaque verdict. Higher = riskier. Returns risk_score, band (safe / caution / danger), factors[] (each with key, label, status, points, and a human-readable detail — including supply_inflation, which flags when on-chain supply has grown above the expected amount, i.e. post-launch minting), the raw inputs the score was computed from, and score_version. inputs.sniper_footprint is the slot-window snipe rollup (slots deploy−1 to deploy+3): buys, buyers, SOL, supply_pct, sniper_wallet_buys, data_available, as_of — informational, it does not move the score, and data_available: false means the mint is outside our capture window, not zero snipes. The top-level dev block is the deployer self-activity read: the dev's exact self-buy in the create transaction (buy_sol / buy_tokens / buy_supply_pct), post-create buys and sells on their own mint (bought_tokens_after, sold_tokens, sold_sol, first_sell_at / last_sell_at), and live on-chain truth — holdings_tokens / holdings_supply_pct, wallet_empty ("has the dev already exited?"), each with its observation time (holdings_observed_at, activity_rollup_through), and transfer_status: none_detected | suspected | unknown — a balance below what the dev's own trades explain is only ever SUSPECTED (a sell on an uncaptured venue looks identical), and misaligned observations are unknown (transferred_out is its deprecated boolean view). dev is null for mints that pre-date the deploy pipeline (dev_status says why). Score v2 (2026-09-21): a token-SUPPLY burn no longer earns the LP-burn credit (0 → the same 8 points every token without verified LP evidence gets; not a burn penalty) — LP custody is not observed for Solana pools, so lp_burn is warn unless verified; missing required creator information never yields safe, even for well-known tokens; an unknown transfer fee is warn, not "No transfer fee". assessment.status = incomplete lists unknown_inputs and the band is never safe; a failed score-critical lookup is a retryable 503 (risk_inputs_unavailable), never a score. Batch and x402 use the same loader and return identical scores. Unlike a black-box safety check, every point of the score is attributed to a named factor you can inspect and weight yourself. Sent a pool address instead of a mint? A PumpSwap pool is resolved to its mint and answered for the mint, with resolved_from { address, kind: "pool", dex, source } set and `mint` holding the resolved mint. Other non-mint addresses get a named error: 400 wallet_not_mint (points at /wallet/{address}), 400 token_account_not_mint (carries the account's mint + risk_url when readable), 400 pool_not_mint (a Raydium / Meteora / Orca pool — `dex` names it), 404 not_on_chain (no such account on mainnet, checked live), and a real mint we have never seen stays 404 not_tracked. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)

Example Response

{
  "mint": "EPjF...Dt1v",
  "risk_score": 31,
  "band": "caution",
  "factors": [
    {
      "key": "mint_authority",
      "label": "Mint authority",
      "status": "ok",
      "points": 0,
      "detail": "Mint authority revoked — supply can't be inflated."
    },
    {
      "key": "freeze_authority",
      "label": "Freeze authority",
      "status": "danger",
      "points": 18,
      "detail": "Freeze authority NOT revoked — holders' tokens can be frozen."
    },
    {
      "key": "liquidity",
      "label": "Liquidity",
      "status": "ok",
      "points": 0,
      "detail": "Healthy liquidity ($48,200)."
    },
    {
      "key": "liquidity_ratio",
      "label": "Liquidity vs market cap",
      "status": "warn",
      "points": 5,
      "detail": "Liquidity is 3.9% of market cap."
    },
    {
      "key": "transfer_fee",
      "label": "Transfer fee",
      "status": "ok",
      "points": 0,
      "detail": "No transfer fee."
    },
    {
      "key": "lp_burn",
      "label": "LP burn/lock",
      "status": "warn",
      "points": 8,
      "detail": "LP burn/lock status unknown — LP-token custody is not observed for this pool; liquidity may be removable. (A token-supply burn is not LP evidence.)"
    },
    {
      "key": "bundled_open",
      "label": "Launch concentration",
      "status": "ok",
      "points": 0,
      "detail": "Launch wasn't heavily bundled."
    },
    {
      "key": "deployer_reputation",
      "label": "Deployer track record",
      "status": "ok",
      "points": 0,
      "detail": "Deployer bonds 71% of its tokens."
    }
  ],
  "inputs": {
    "mint_authority_revoked": true,
    "freeze_authority_revoked": false,
    "liquidity_usd": 48200,
    "liquidity_to_mc_ratio": 0.039,
    "transfer_fee_bps": 0,
    "is_token_2022": false,
    "token_supply_burn_detected": false,
    "burn_detected": false,
    "lp_burn_status": "unknown",
    "launch_cohort_sol": 6.1,
    "launch_cohort_size": 12,
    "sniper_footprint": {
      "buys": 14,
      "buyers": 9,
      "sol": 12.4,
      "supply_pct": 3.8,
      "sniper_wallet_buys": 4,
      "data_available": true,
      "as_of": "2026-07-10T12:00:00Z"
    },
    "deployer_bonding_rate": 0.71,
    "deployer_total_deployed": 17,
    "deployer_history_status": "established",
    "deployer_reputation_scored": true,
    "kol_signal": "accumulating",
    "is_blacklisted": false,
    "supply_inflation_pct": null
  },
  "assessment": {
    "status": "complete",
    "unknown_inputs": [],
    "not_assessed": [
      "lp_custody"
    ]
  },
  "dev_status": "ok",
  "dev": {
    "wallet": "4qTz...8xNb",
    "launchpad": "pumpfun",
    "deployed_at": "2026-07-11T09:14:02Z",
    "buy_sol": 0.85,
    "buy_tokens": 24183920.5,
    "buy_supply_pct": 2.42,
    "bought_tokens_after": 0,
    "sold_tokens": 24183920.5,
    "sold_sol": 1.12,
    "first_sell_at": "2026-07-11T09:14:09Z",
    "last_sell_at": "2026-07-11T09:14:09Z",
    "holdings_tokens": 0,
    "holdings_supply_pct": 0,
    "wallet_empty": true,
    "holdings_observed_at": "2026-07-11T09:19:31Z",
    "activity_rollup_through": "2026-07-11T09:18:00Z",
    "activity_rollup_ran_at": "2026-07-11T09:19:00Z",
    "expected_tokens_from_trades": 0,
    "transfer_status": "none_detected",
    "transfer_reason": "on-chain balance is consistent with the dev's recorded trades",
    "transferred_out": false
  },
  "coverage": {
    "history_start": 1775984757,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)",
    "in_scope": true,
    "data_observed": true,
    "eligibility": "eligible",
    "eligibility_basis": "persisted_rows",
    "completeness": "not_verified"
  },
  "score_version": "v2",
  "as_of": "2026-07-11T09:20:00Z"
}
GET/tokens/{mint}/candlesPRO

Token OHLCV Candles

Time-series OHLCV candles for a token mint, aggregated from the trade firehose into fixed buckets. Each candle carries open/high/low/close price, USD volume, trade count, and market cap at the bucket. PRO: OHLCV fields, last 30 days of history. ULTRA: adds per-candle net-flow (buy/sell volume + counts, MEV volume) and liquidity (open/close liquidity, high/low market cap) fields, plus full retained history. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)
tfstring1hTimeframe: one of 1m, 5m, 15m, 1h, 4h, 1d
limitnumber200Number of candles to return (1–1500)
fromstringoptionalISO8601 timestamp — only candles at or after this time
tostringoptionalISO8601 timestamp — only candles at or before this time

Example Response

{
  "mint": "EPjF...Dt1v",
  "timeframe": "1h",
  "from": "2026-06-17T00:00:00Z",
  "to": "2026-06-17T02:00:00Z",
  "count": 2,
  "net_flow_included": true,
  "candles": [
    {
      "t": "2026-06-17T00:00:00Z",
      "open": 0.00042,
      "high": 0.00051,
      "low": 0.0004,
      "close": 0.00048,
      "volume_usd": 184200,
      "trades": 1320,
      "market_cap_usd": 480000,
      "buy_volume_usd": 102400,
      "sell_volume_usd": 81800,
      "net_volume_usd": 20600,
      "buy_count": 740,
      "sell_count": 580,
      "volume_mev_usd": 5200,
      "open_liquidity_usd": 92000,
      "close_liquidity_usd": 98500,
      "high_mc_usd": 510000,
      "low_mc_usd": 400000
    },
    {
      "t": "2026-06-17T01:00:00Z",
      "open": 0.00048,
      "high": 0.00049,
      "low": 0.00044,
      "close": 0.00045,
      "volume_usd": 96100,
      "trades": 710,
      "market_cap_usd": 450000,
      "buy_volume_usd": 41300,
      "sell_volume_usd": 54800,
      "net_volume_usd": -13500,
      "buy_count": 305,
      "sell_count": 405,
      "volume_mev_usd": 2100,
      "open_liquidity_usd": 98500,
      "close_liquidity_usd": 95300,
      "high_mc_usd": 490000,
      "low_mc_usd": 440000
    }
  ]
}
GET/tokens/{mint}/flowPRO

Token Trade Flow

Per-token trade-flow aggregate computed straight from the trade firehose — the organic-vs-fake-volume read for a single mint. Returns unique wallets / buyers / sellers, buy & sell counts, total trades, buy / sell / net SOL flow, and trades_per_wallet (a wash-trading proxy: a high trade count spread across very few wallets is the classic synthetic-volume tell). Counts and flows only — no holder or balance data. Read the `coverage` block first: `in_scope: false` means we hold no persisted trades for it — `coverage.eligibility` says why (outside the launchpad write-gate, a lapsed capture window, or a brand-new in-scope mint that has not traded yet) — so the zeros mean "not captured", NOT "no activity". PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)
windowstring1hLookback window: 1h or 24h

Example Response

{
  "mint": "EPjF...Dt1v",
  "window": "24h",
  "from": "2026-06-20T12:00:00Z",
  "coverage": {
    "history_start": 1775984757,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)",
    "in_scope": true
  },
  "unique_wallets": 1840,
  "unique_buyers": 1620,
  "unique_sellers": 910,
  "buy_count": 4210,
  "sell_count": 2680,
  "total_trades": 6890,
  "buy_sol": 1284.42,
  "sell_sol": 902.17,
  "net_sol": 382.25,
  "trades_per_wallet": 3.74
}
GET/tokens/{mint}/tradesPRO

Token Trade Tape

Every captured trade for one token mint, newest first — cursor-paginated raw trades, the backfill complement to the live firehose (seed history, then keep current via the stream). Each trade carries tx_signature, wallet_address, action, sol_amount, token_amount, price_sol/price_usd, early_buyer_rank, slot, and block_time. Default window is full history. The response's coverage block carries the honesty markers: capture starts 2026-04-12 and is pump.fun-pipeline scoped, and `in_scope: false` means no persisted trades (see `coverage.eligibility` for why) — read an empty result as "not captured", NOT "no activity". PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)
limitinteger100Trades per page (1-500)
cursorstring—From next_cursor of previous page
actionstring—Filter: "buy" or "sell"
walletstring—Filter to one wallet's trades on this token
sinceintegerfull historyUnix epoch seconds lower bound
untilintegernowUnix epoch seconds upper bound

Example Response

{
  "mint": "EPjF...Dt1v",
  "trades": [
    {
      "tx_signature": "5Hyj...kMnP",
      "wallet_address": "7xKv...9mPQ",
      "action": "buy",
      "sol_amount": 1.42,
      "token_amount": 4567890.12,
      "price_sol": 3.1e-7,
      "price_usd": 0.0000284,
      "early_buyer_rank": 7,
      "slot": 305418729,
      "block_time": 1747746000,
      "traded_at": "2026-05-20T12:20:00Z"
    }
  ],
  "next_cursor": "MTc0Nzc0NjAwMDoxMjM0NQ==",
  "has_more": true,
  "filters": {
    "action": null,
    "wallet": null,
    "since": 1775984757,
    "until": 1783036800
  },
  "coverage": {
    "history_start": 1775984757,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)",
    "in_scope": true
  }
}
GET/tokens/{mint}/poolsPRO

Token Liquidity Map

Per-venue liquidity map for a token mint — every DEX pool the token trades in (pump.fun bonding curve, PumpSwap, Raydium, Meteora, Orca), which are live vs parked (is_active), and how fragmented liquidity is across them. This is the venue-level breakdown behind the single aggregate liquidity number on /token/{mint}: use it to see whether liquidity is concentrated in one deep pool or scattered across many thin ones, and which venue is primary. Returns pools[] (pool_address, dex, quote_mint, liquidity_usd, last_price_sol, last_swap_at, amm_id, is_active) plus a summary (pool_count, active_pool_count, dex_count, dexes, total_liquidity_usd, primary_pool, primary_dex, top_pool_share_pct — the primary pool's share of total liquidity, a fragmentation read). PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)

Example Response

{
  "mint": "EPjF...Dt1v",
  "pools": [
    {
      "pool_address": "9WzD...aB3k",
      "dex": "PumpSwap",
      "quote_mint": "So11...1112",
      "liquidity_usd": 184200,
      "last_price_sol": 4.2e-7,
      "last_swap_at": "2026-07-05T11:58:00Z",
      "amm_id": "pAMM...4xQ",
      "is_active": true
    },
    {
      "pool_address": "3nQd...42aa",
      "dex": "Raydium",
      "quote_mint": "So11...1112",
      "liquidity_usd": 41800,
      "last_price_sol": 4.1e-7,
      "last_swap_at": "2026-07-05T11:41:00Z",
      "amm_id": "675k...RB8",
      "is_active": true
    },
    {
      "pool_address": "7xKv...9mPQ",
      "dex": "pump.fun",
      "quote_mint": "So11...1112",
      "liquidity_usd": 0,
      "last_price_sol": 3.9e-7,
      "last_swap_at": "2026-07-01T08:12:00Z",
      "amm_id": null,
      "is_active": false
    }
  ],
  "summary": {
    "pool_count": 3,
    "active_pool_count": 2,
    "dex_count": 3,
    "dexes": [
      "PumpSwap",
      "Raydium",
      "pump.fun"
    ],
    "total_liquidity_usd": 226000,
    "primary_pool": "9WzD...aB3k",
    "primary_dex": "PumpSwap",
    "top_pool_share_pct": 81.5
  }
}
GET/tokens/{mint}/depthPRO

Token Depth / Price Impact

Per-pool price-impact and slippage for a token mint — "how much SOL does it take to move the price N%", and what each buy size actually costs. For every pool: spot_price_sol, quotes[] per requested SOL size (tokens_out, avg_price_sol, price_impact_pct) and to_move_price (SOL required to move price 1% / 5% / 10%). Exact for constant-product AMMs (PumpSwap, Raydium v4/CPMM, Meteora DAMM — computed from our streamed reserves, zero RPC) and correct for pump.fun / bonk bonding curves via one live read of the curve's virtual reserves (source: "live_rpc"). Honesty markers: impact is per-pool, not router-optimal; concentrated-liquidity pools (Raydium CLMM, Orca, Meteora DLMM) and unclassified pools are listed under unsupported_pools with a reason instead of returning a wrong number. A sharper liquidity-quality read than raw liquidity_usd — the data a bot needs to size entries. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
mintstring (path)requiredToken mint address (base58)
sizesstring0.5,1,5,10Comma-separated SOL buy sizes to quote (max 8, each ≤ 10000)

Example Response

{
  "mint": "EPjF...Dt1v",
  "found": true,
  "sol_usd": 178.42,
  "sizes_sol": [
    0.5,
    1,
    5
  ],
  "primary_pool": "9WzD...aB3k",
  "pools": [
    {
      "pool_address": "9WzD...aB3k",
      "dex": "pumpswap",
      "quote_mint": "So11...1112",
      "pool_model": "constant_product",
      "liquidity_usd": 184200,
      "is_active": true,
      "depth_available": true,
      "model": "constant_product",
      "fee_pct": 0.25,
      "source": "stream",
      "reserves_age_ms": 1840,
      "spot_price_sol": 4.2e-7,
      "quotes": [
        {
          "size_sol": 0.5,
          "tokens_out": 1180212.4,
          "avg_price_sol": 4.24e-7,
          "price_impact_pct": 0.19
        },
        {
          "size_sol": 1,
          "tokens_out": 2352114.8,
          "avg_price_sol": 4.25e-7,
          "price_impact_pct": 0.39
        },
        {
          "size_sol": 5,
          "tokens_out": 11548020.1,
          "avg_price_sol": 4.33e-7,
          "price_impact_pct": 1.97
        }
      ],
      "to_move_price": {
        "1pct": 2.55,
        "5pct": 12.61,
        "10pct": 24.87
      }
    }
  ],
  "unsupported_pools": [
    {
      "pool_address": "5rTe...2wQx",
      "dex": "raydium_clmm",
      "quote_mint": "So11...1112",
      "pool_model": "concentrated",
      "liquidity_usd": 22100,
      "is_active": true,
      "reason": "concentrated_liquidity_depth_not_supported"
    }
  ],
  "note": "Impact is per-pool (not router-optimal). Constant-product served from stream reserves; pump.fun/bonk from live virtual reserves."
}
POST/tokens/batch/riskPRO

Batch Token Risk Score

The same transparent 0–100 rug-risk / safety score as GET /tokens/{mint}/risk — risk_score, band, auditable factors[], inputs, score_version — for up to 50 mints in one call. Same loader as the single route (score v2, assessment, dev block, coverage); only the live dev-holdings RPC is skipped (dev.holdings_* null, transfer_status unknown). Untracked mints come back as { mint, error: "not_tracked" } instead of a fabricated score; a mint whose score-critical inputs could not be read comes back as { mint, error: "unavailable", retryable: true } — never a partial score (error: "error" if that one mint's computation failed). Counts as one request. PRO+.

Parameters

NameTypeDefaultDescription
mintsstring[]required1-50 base58 mint addresses (array or comma-separated string)

Example Response

{
  "tokens": [
    {
      "mint": "9aK2rFy1...pump",
      "risk_score": 41,
      "band": "caution",
      "factors": [
        {
          "key": "mint_authority",
          "label": "Mint authority",
          "status": "ok",
          "points": 0,
          "detail": "Mint authority revoked — supply can't be inflated."
        },
        {
          "key": "freeze_authority",
          "label": "Freeze authority",
          "status": "danger",
          "points": 18,
          "detail": "Freeze authority NOT revoked — holders' tokens can be frozen."
        },
        {
          "key": "liquidity",
          "label": "Liquidity",
          "status": "danger",
          "points": 15,
          "detail": "Very thin liquidity ($1,240)."
        },
        {
          "key": "lp_burn",
          "label": "LP burn/lock",
          "status": "warn",
          "points": 8,
          "detail": "LP burn/lock status unknown — LP-token custody is not observed for this pool; liquidity may be removable. (A token-supply burn is not LP evidence.)"
        }
      ],
      "inputs": {
        "mint_authority_revoked": true,
        "freeze_authority_revoked": false,
        "liquidity_usd": 1240,
        "liquidity_to_mc_ratio": null,
        "transfer_fee_bps": 0,
        "is_token_2022": false,
        "token_supply_burn_detected": false,
        "burn_detected": false,
        "lp_burn_status": "unknown",
        "launch_cohort_sol": null,
        "launch_cohort_size": null,
        "sniper_footprint": null,
        "deployer_bonding_rate": null,
        "deployer_total_deployed": null,
        "deployer_history_status": null,
        "deployer_reputation_scored": false,
        "kol_signal": "neutral",
        "is_blacklisted": false,
        "supply_inflation_pct": null
      },
      "assessment": {
        "status": "complete",
        "unknown_inputs": [],
        "not_assessed": [
          "lp_custody",
          "deployer_reputation"
        ]
      },
      "dev_status": "not_found",
      "dev": null,
      "score_version": "v2",
      "as_of": "2026-09-12T10:00:00Z"
    },
    {
      "mint": "5xQq...9zZ",
      "error": "not_tracked"
    }
  ],
  "count": 2
}
POST/tokens/batch/buyer-qualityFREE

Token Buyer Quality (Batch)

Bulk scoring for up to 50 mints. Shares the same 5-minute LRU cache as the single-mint endpoint — already-warm mints return at near-zero cost. Response includes a `cache_hits` counter so you can see how many were served from cache.

Parameters

NameTypeDefaultDescription
bodyJSONrequired{ "mints": ["...", "..."] } — 1 to 50 base58 Solana token mints

Example Response

{
  "tokens": [
    {
      "mint": "EPjF...Dt1v",
      "score": 74,
      "confidence": "medium",
      "signal": "positive",
      "breakdown": {
        "alpha_wallet_count": 6,
        "kol_count": 2,
        "bundle_buyer_count": 1,
        "bot_dominated": false,
        "wallets_with_history": 9,
        "qualified_win_rate_wallets": 7,
        "dump_cluster_count": 0,
        "recycled_early_buyer_count": 4
      }
    },
    {
      "mint": "So11...1112",
      "score": 50,
      "confidence": "insufficient_data",
      "signal": "neutral",
      "breakdown": {
        "alpha_wallet_count": 0,
        "kol_count": 0,
        "bundle_buyer_count": 0,
        "bot_dominated": false,
        "wallets_with_history": 0,
        "qualified_win_rate_wallets": 0,
        "dump_cluster_count": 0,
        "recycled_early_buyer_count": 0
      }
    }
  ],
  "count": 2,
  "cache_hits": 1
}
GET/signalsFREE

Signal Scorecard Catalog

The list of enrichment signals that carry a live, out-of-sample Signal Scorecard — name, methodology and the /signals/{name}/performance URL for each (dump_cluster_count, runner_rate, recycled_early_buyer_count, coordination_count, scout_first_touch). Any key.

Example Response

{
  "name": "MadeOnSol Signal Scorecard",
  "signals": [
    {
      "name": "dump_cluster_count",
      "methodology": "Tokens whose early buyers overlap ≥N dump cohorts vs the base rate of a ≥2× runner…",
      "performance_url": "/api/v1/signals/dump_cluster_count/performance"
    },
    {
      "name": "runner_rate",
      "performance_url": "/api/v1/signals/runner_rate/performance"
    }
  ]
}
GET/signals/{name}/performanceFREE

Signal Scorecard (efficacy)

Live, out-of-sample backtest for an enrichment signal so bots can weight it programmatically instead of guessing. Returns per-bucket hit rate, base rate, and lift over base. `?history=true` adds the per-day series for drift. Open to any authenticated tier — aggregate, non-sensitive efficacy data.

Parameters

NameTypeDefaultDescription
namestringrequiredSignal name (path): dump_cluster_count, runner_rate, or recycled_early_buyer_count
historybooleanfalseInclude the per-day snapshot series (up to 90 days) for drift tracking

Example Response

{
  "signal": "dump_cluster_count",
  "metric_type": "count",
  "outcome": "dumped",
  "window_days": 14,
  "base_rate": 0.75,
  "test_from": "2026-05-28",
  "test_to": "2026-06-11",
  "as_of": "2026-06-11T03:50:00Z",
  "methodology": "Out-of-sample: rolling train/test split, >=15 early-buyer filter, peak-timing labels (<15min=dump / >=60min=runner), no lookahead.",
  "buckets": [
    {
      "bucket": "0",
      "hit_rate": 0.71,
      "base_rate": 0.75,
      "lift": 0.95,
      "sample_n": 4210
    },
    {
      "bucket": ">=8",
      "hit_rate": 0.98,
      "base_rate": 0.75,
      "lift": 1.31,
      "sample_n": 190
    }
  ]
}

Tools

Solana directory data.

1,200+ tools indexed across the Solana ecosystem.

GET/tools/searchFREE

Tools Directory Search

Search across 1,200+ Solana & Robinhood Chain tools by name, tagline, or category. Returns ratings, health scores, pricing, and direct links.

Parameters

NameTypeDefaultDescription
qstring—Search query (2-200 characters)
categorystring—Filter by category slug (e.g. trading-bots, dex, analytics)
limitinteger20Max results (1-50)

Example Response

{
  "tools": [
    {
      "name": "Jupiter",
      "slug": "jupiter",
      "tagline": "The best swap aggregator on Solana",
      "average_rating": 4.8,
      "review_count": 12,
      "pricing_model": "free",
      "health_score": 100,
      "categories": [
        "dex"
      ],
      "url": "https://madeonsol.com/tools/jupiter"
    }
  ],
  "count": 1
}
GET/token/{mint}FREE

Token Intelligence

Comprehensive token data in one call: real-time VWAP price from our DEX trade stream, market cap, 24h volume, **velocity deltas** (`mc_change_pct`, `volume_usd`, `mev_volume_pct` across 5m/15m/1h/2h/4h windows), deployer reputation, KOL smart money flow (including top buyers by SOL volume), `first_seen_at` + `age_seconds` (from our indexer), and `is_blacklisted` + `blacklist_category` (stablecoin / wrapped_sol / lst / rug-flagged). The `mev_volume_pct` field — unique to MadeOnSol — surfaces the % of each window's volume tagged as sandwich/Jito-bundle MEV, so traders can flag wash-pump patterns where headline volume is bot-driven rather than organic demand. All data self-hosted — no external API dependencies. ULTRA adds individual KOL wallet addresses in the top-buyer list. For bulk lookups use POST /token/batch. Freshness + honesty (2026-09-21): `price_source` + `price_observed_at` anchor `price_age_seconds`/`price_is_stale` to the pipeline that actually produced the price (`price_is_stale` is null — unknown — when that source carries no timestamp; `last_trade_at` is the newest trade of either source). `kol_activity` is the complete 7-day aggregate (not a newest-N sample). `deployer` is resolved for unbonded launches too; `deployer_identity` says why it is null (unknown vs lookup_failed) and `history_status` whether its bonding rate is a real track record. `data_status` names any block whose lookup failed — its fields are null (unknown), never a default like 0 KOLs or not-blacklisted. `burn_detected` is a token-SUPPLY burn, not LP evidence. `as_of` is response time, not an observation time.

Parameters

NameTypeDefaultDescription
mintpathrequiredToken mint address (base58)

Example Response

{
  "token": {
    "mint": "CYTUg8qLd45EGbx7MXxSwR5PSMNoUck5SetxxSDHpump",
    "price_usd": 0.001024,
    "price_sol": 0.0000136,
    "market_cap": 1024000,
    "volume_24h_usd": 4858,
    "volume_24h_sol": 46.17,
    "trades_24h": 71,
    "last_trade_at": "2026-04-06T14:50:00Z",
    "price_source": "mc_tracker",
    "price_observed_at": "2026-04-06T14:50:00Z",
    "price_age_seconds": 42,
    "price_is_stale": false,
    "is_token_2022": false,
    "transfer_fee_bps": 0,
    "burn_detected": false,
    "first_seen_at": "2026-04-03T08:12:44Z",
    "age_seconds": 276136,
    "is_blacklisted": false,
    "blacklist_category": null,
    "mc_change_pct": {
      "5m": 8.2,
      "15m": 31.4,
      "1h": 62.1,
      "2h": 75,
      "4h": 87
    },
    "volume_usd": {
      "5m": 42000,
      "15m": 118000,
      "1h": 340000,
      "2h": 500000,
      "4h": 920000
    },
    "mev_volume_pct": {
      "5m": 18.4,
      "15m": 22.1,
      "1h": 27.3,
      "2h": 31.8,
      "4h": 34.2
    },
    "history_age_seconds": 14400,
    "deployer": {
      "wallet": "6vxo...5UhE",
      "address": "6vxo...5UhE",
      "tier": "rising",
      "bonding_rate": 0.5,
      "total_deployed": 2,
      "total_bonded": 1,
      "identity_status": "resolved",
      "identity_source": "pending_deploys",
      "history_status": "limited_history",
      "observed_launch_count": 2,
      "resolved_outcome_count": 1
    },
    "deployer_identity": {
      "identity_status": "resolved",
      "history_status": "limited_history",
      "address": "6vxo...5UhE",
      "source": "pending_deploys"
    },
    "kol_activity": {
      "status": "ok",
      "buying_kols": 14,
      "selling_kols": 18,
      "net_flow_sol": -228.52,
      "signal": "distributing",
      "top_buyers": [
        {
          "name": "Scharo",
          "sol_amount": 65.69
        }
      ],
      "window_hours": 168,
      "unique_kols": 27,
      "buys": 61,
      "sells": 88,
      "buy_sol": 402.1,
      "sell_sol": 630.62,
      "counts_basis": "complete_window"
    },
    "data_status": {
      "market": "ok",
      "deployer": "ok",
      "kol_activity": "ok",
      "first_seen": "ok",
      "blacklist": "ok",
      "metadata": "ok",
      "launch_cohort": "ok",
      "sniper_footprint": "ok",
      "volume_candles": "ok",
      "twitter_reuse": "ok"
    },
    "liquidity_to_mc_ratio": 0.0278,
    "launch_cohort_sol": 12.45,
    "launch_cohort_size": 18
  },
  "as_of": "2026-04-06T14:50:42Z"
}
POST/token/batchFREE

Token Intelligence (Batch)

Bulk lookup of up to 50 mints in a single request. Returns the same per-mint shape as `GET /token/{mint}` — including the full velocity / volume / MEV-share deltas across 5m/15m/1h/2h/4h windows. DB queries batched with `IN (...)`; dex-stream + RPC supply fan-outs run in parallel — ~10-20× cheaper than N sequential single-mint calls. Ideal for sniper pipelines and dashboards scoring many tokens at once. KOL activity is a complete per-mint aggregate (one busy mint can no longer starve another's sample); a failed lookup block is listed once in top-level `degraded_fields` and its per-token fields are null (unknown), never an empty-state default.

Parameters

NameTypeDefaultDescription
bodyJSONrequired{ "mints": ["...", "..."] } — 1 to 50 base58 Solana token mints

Example Response

{
  "tokens": [
    {
      "mint": "CYTUg8qLd45EGbx7MXxSwR5PSMNoUck5SetxxSDHpump",
      "price_usd": 0.001024,
      "market_cap": 1024000,
      "age_seconds": 276136,
      "is_blacklisted": false,
      "mc_change_pct": {
        "5m": 8.2,
        "1h": 62.1,
        "4h": 87
      },
      "volume_usd": {
        "5m": 42000,
        "1h": 340000,
        "4h": 920000
      },
      "mev_volume_pct": {
        "5m": 18.4,
        "1h": 27.3,
        "4h": 34.2
      },
      "price_source": "mc_tracker",
      "price_observed_at": "2026-04-06T14:50:00Z",
      "price_is_stale": false,
      "deployer": {
        "tier": "rising",
        "bonding_rate": 0.5,
        "identity_status": "resolved",
        "history_status": "limited_history"
      },
      "deployer_identity": {
        "identity_status": "resolved",
        "history_status": "limited_history",
        "address": "6vxo...5UhE",
        "source": "pending_deploys"
      },
      "kol_activity": {
        "buying_kols": 14,
        "signal": "distributing",
        "buys": 61,
        "sells": 88,
        "window_hours": 168,
        "complete": true
      },
      "liquidity_to_mc_ratio": 0.0278,
      "launch_cohort_sol": 12.45,
      "launch_cohort_size": 18
    }
  ],
  "count": 1,
  "as_of": "2026-04-06T14:50:42Z"
}
GET/statusFREE

API Status

Public system health endpoint. Seven core services are monitored: kol_tracker, deployer_listener, nextjs_app, supabase_db, websocket, rhc_node_sync and rhc_trades_freshness (the last two cover Robinhood Chain). Returns per-service status, uptime percentages and stream lag. `slo_target_pct` is our published availability TARGET, not a measurement of the current period — compare it against the `uptime` block, which is the measured figure. No authentication required. Checks run every 5 minutes.

Example Response

{
  "status": "operational",
  "services": {
    "kol_tracker": {
      "status": "healthy",
      "last_trade_age_s": 5
    },
    "deployer_listener": {
      "status": "healthy"
    },
    "nextjs_app": {
      "status": "healthy",
      "response_ms": 41
    },
    "supabase_db": {
      "status": "healthy",
      "response_ms": 3
    },
    "websocket": {
      "status": "healthy"
    },
    "rhc_node_sync": {
      "status": "healthy",
      "block_lag": 2
    },
    "rhc_trades_freshness": {
      "status": "healthy",
      "last_trade_age_s": 11
    }
  },
  "uptime": {
    "last_24h": 99.5,
    "last_7d": 99.8
  },
  "slo_target_pct": 99.5,
  "slo_note": "slo_target_pct is a target, not a measurement — the measured figures are in `uptime`.",
  "checked_at": "2026-04-06T15:00:00Z"
}
GET/meFREE

Account & Quota (v1.7)

Inspect your tier, daily/burst quota state, subscription expiry, and per-feature usage. `features` carries all 12 keys: webhooks, ws_connections, dex_connections, copytrade_wallets, copytrade_wallets_per_rule, copytrade_rules, coordination_rules, first_touch_subscriptions, price_alerts, rhc_copytrade_rules, wallet_tracker_watchlist, rhc_wallet_tracker_watchlist. `copytrade_wallets` counts distinct wallets across all your rules; `copytrade_wallets_per_rule` is the limit the create/PATCH routes enforce on ONE rule (`used` = your largest rule). Robinhood Chain quotas are PER CHAIN — the rhc_* keys are separate budgets that never eat into their Solana counterparts. Reads from the same in-memory counters that drive rate-limit enforcement, so `quota.daily.remaining` is authoritative — no header parsing. Available to every authenticated tier; useful for self-throttling and quota-aware retry logic.

Example Response

{
  "subscriber": "9189666b-0b8f-4606-b39d-a6a52918c587",
  "tier": "PRO",
  "tier_label": "Pro",
  "subscription": {
    "status": "active",
    "billing_cycle": "monthly",
    "current_period_end": "2026-06-12T10:00:00Z",
    "started_at": "2026-04-12T10:00:00Z"
  },
  "quota": {
    "daily": {
      "limit": 10000,
      "used": 3427,
      "remaining": 6573,
      "resets_at": "2026-05-13T00:00:00Z"
    },
    "burst": {
      "limit": 300,
      "used": 14,
      "remaining": 286,
      "window_seconds": 60
    }
  },
  "features": {
    "webhooks": {
      "limit": 3,
      "used": 1
    },
    "ws_connections": {
      "limit": 2
    },
    "dex_connections": {
      "limit": 0
    },
    "copytrade_wallets": {
      "limit": 5,
      "used": 2
    },
    "copytrade_wallets_per_rule": {
      "limit": 5,
      "used": 2
    },
    "copytrade_rules": {
      "limit": 3,
      "used": 1
    },
    "coordination_rules": {
      "limit": 5,
      "used": 1
    },
    "first_touch_subscriptions": {
      "limit": 0,
      "used": 0
    },
    "price_alerts": {
      "limit": 5,
      "used": 2
    },
    "rhc_copytrade_rules": {
      "limit": 3,
      "used": 0
    },
    "wallet_tracker_watchlist": {
      "used": 12
    },
    "rhc_wallet_tracker_watchlist": {
      "used": 4
    }
  }
}
GET/manifestsFREE

Dataset Manifests

One row per dataset per night: rows written in the previous 24h, min/max event timestamp, a catalogue row estimate, a schema_hash (columns + types) and a fingerprint. Cite the fingerprint in a report or evidence export and it names the exact dataset state the numbers came from — two manifests with a different schema_hash mean the shape of the data changed between them. Also carries `methodology_version` (see /methodology). Default returns the latest manifest per dataset; pass `dataset` to walk one dataset's history. Metadata, not data — available on any valid key. Cached 60s.

Parameters

NameTypeDefaultDescription
datasetstring—Walk one dataset's history instead of the latest-per-dataset default (lowercase, digits, underscore)
limitinteger30History rows when `dataset` is set (1-365)

Example Response

{
  "manifests": [
    {
      "dataset": "deployer_tokens",
      "data_as_of": "2026-09-06T04:20:02.160582+00:00",
      "produced_at": "2026-09-06T04:22:17.9941+00:00",
      "ts_column": "deployed_at",
      "rows_24h": 635,
      "min_ts": "2024-01-25T19:35:33.993+00:00",
      "max_ts": "2026-09-06T04:15:35.976+00:00",
      "row_count_estimate": 73607,
      "schema_hash": "c71901159ac11f94dd12aa42d17db70a",
      "fingerprint": "52ec41a1f79f3c231ef8f66fe73f3f72"
    }
  ],
  "count": 1,
  "dataset": null,
  "methodology_version": "2026.08.28-2",
  "note": "rows_24h/min_ts/max_ts are measured on the streaming replica at data_as_of; row_count_estimate is the planner estimate. Produced nightly ~06:10 Europe/Berlin."
}
GET/tokensPRO

Token Directory (v1.7, PRO+)

Filtered, sortable token directory. Complements `/token/{mint}` (single lookup) and the KOL-scoped `/kol/tokens/{hot,trending}`. Server-side filters: `min_mc`, `max_mc`, `min_liq` (**default 2000** — set 0 to disable phantom-MC dust floor), `active_h`, `primary_dex` (pumpfun/pumpswap/raydium/meteora/orca/raydium_clmm), `authority_revoked`, `exclude_token2022`, `lp_burned` (verified LP evidence only — matches nothing until an LP-custody writer exists), `supply_burn` (token-supply burn). `deployer_tier` / `launchpad` are served by a bounded scan: `pagination.scan_truncated` + `next_offset` say where to continue, and `has_more` is false only when the candidates ran out. Offset pages walk a live order (`order_is_live`). Computed post-filters: `min_volume_1h_usd`, `max_mev_share_pct`, `mc_change_1h_min_pct`, `mc_change_1h_max_pct`. **Trending / momentum sorts** (PRO/ULTRA): `mc_change_5m_desc`, `mc_change_1h_desc`, `volume_1h_desc`, and `trending` (recent volume × momentum) turn the directory into a reputation-aware momentum board — combine with `deployer_tier` and `max_mev_share_pct` for clean-volume movers from trusted deployers. Full sort set: `mc_desc` | `mc_asc` | `last_trade_desc` | `liquidity_desc` | `cumulative_volume_desc` | `mc_change_5m_desc` | `mc_change_1h_desc` | `volume_1h_desc` | `trending`. Pagination includes `post_filtered: true` so clients can detect when computed filters trim a page below `limit`.

Parameters

NameTypeDefaultDescription
min_mcquery—Minimum market_cap_usd
max_mcquery—Maximum market_cap_usd
min_liqquery2000Minimum liquidity_usd. Set 0 to disable the default dust floor.
active_hquery—Only tokens traded within the last N hours (0.1–168)
primary_dexquery—pumpfun | pumpswap | raydium | meteora | orca | raydium_clmm
authority_revokedquery—true = both mint + freeze revoked; false = at least one not revoked
exclude_token2022queryfalseDrop Token-2022 mints (common transfer-fee scam vector)
lp_burnedquery—DEPRECATED. VERIFIED LP evidence only: true = lp_burnt_pct ≥ 99, false = measured below it; unknown LP custody matches neither, so both match no token today. Never a token-supply burn (use supply_burn). Sending it adds a deprecations entry to the response
supply_burnquery—Token-SUPPLY burn flag (the mint's supply decreased) — what lp_burned used to filter on; not LP evidence
min_volume_1h_usdquery—Computed organic-volume floor (post-filter)
max_mev_share_pctquery—Computed MEV/bot volume ceiling % (post-filter)
mc_change_1h_min_pctquery—Computed minimum 1h MC change % (post-filter; momentum scans)
mc_change_1h_max_pctquery—Computed maximum 1h MC change % (post-filter; dip scans)
min_liq_mc_ratioquery—Minimum liquidity-to-MC ratio (liquidity_usd / market_cap_usd)
max_liq_mc_ratioquery—Maximum liquidity-to-MC ratio (liquidity_usd / market_cap_usd)
deployer_tierquery—Filter by deployer tier: elite | good | moderate | rising | cold | unranked
sortquerymc_descmc_desc | mc_asc | last_trade_desc | liquidity_desc | cumulative_volume_desc | mc_change_5m_desc | mc_change_1h_desc | volume_1h_desc | trending (last four are momentum sorts, PRO/ULTRA)
limitquery501–100
offsetquery00–10000

Example Response

{
  "tokens": [
    {
      "mint": "CYTUg8qLd45EGbx7MXxSwR5PSMNoUck5SetxxSDHpump",
      "symbol": "ALPHA",
      "name": "Alpha Coin",
      "price_usd": 0.001024,
      "market_cap_usd": 1024000,
      "fdv_usd": 1024000,
      "liquidity_usd": 28430,
      "primary_dex": "raydium",
      "authorities_revoked": true,
      "lp_burned": null,
      "lp_burn_status": "unknown",
      "lp_burnt_pct": null,
      "token_supply_burn_detected": false,
      "is_token_2022": false,
      "last_trade_time": "2026-05-12T17:15:05Z",
      "mc_change_5m_pct": 4.2,
      "mc_change_1h_pct": 31.8,
      "organic_volume_1h_usd": 12480,
      "mev_share_pct": 18.4,
      "liquidity_to_mc_ratio": 0.0278,
      "deployer_tier": "elite"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "returned": 50,
    "has_more": true,
    "order_is_live": true,
    "next_offset": 50
  },
  "filters": {
    "min_liq": 2000,
    "min_liq_default_applied": true,
    "sort": "mc_desc",
    "lp_burned": null,
    "lp_burned_source": "lp_burnt_pct >= 99 (verified LP evidence only)",
    "supply_burn": null
  }
}
GET/tokens/almost-bondedPRO

Almost-Bonded Tokens (PRO+)

Pre-bond pump.fun tokens approaching graduation — catch them *before* they bond. Each token carries its live bonding-curve `progress_pct` (from on-chain `real_token_reserves` depletion) and, uniquely, its **velocity** (`velocity_pct_per_min` = Δprogress/min) plus a linear `eta_minutes` projection — so "95% and accelerating" ranks above "92% stalled". Enriched with deployer reputation (`deployer_tier`) from our deployer-hunter graph, so you can filter to elite/good deployers only. Defaults to the 80–99.99% band, already-bonded tokens excluded. Self-hosted from our firehose — no external API.

Parameters

NameTypeDefaultDescription
min_progressquery80Minimum bonding-curve progress % (0–100)
max_progressquery99.99Maximum bonding-curve progress % (< 100; bonded tokens always excluded)
min_velocity_pct_per_minquery—Minimum Δprogress/min — drops tokens without a 5m snapshot when set
max_age_minutesquery—Only tokens deployed within the last N minutes (≥1)
deployer_tierquery—elite | good | moderate | rising | cold | unranked
authority_revokedquery—true = both mint + freeze revoked
min_liqquery—Minimum liquidity_usd
sortqueryvelocity_descvelocity_desc | progress_desc | eta_asc
limitquery501–100

Example Response

{
  "tokens": [
    {
      "mint": "8xKv9aK2rFy1mPQ...pump",
      "symbol": "MOON",
      "name": "Moon Soon",
      "progress_pct": 96.4,
      "velocity_pct_per_min": 1.82,
      "eta_minutes": 2,
      "stalled": false,
      "real_sol_reserves": 78.3,
      "market_cap_usd": 61200,
      "liquidity_usd": 24100,
      "authorities_revoked": true,
      "deployer_tier": "elite",
      "age_minutes": 14
    }
  ],
  "filters": {
    "min_progress": 80,
    "max_progress": 99.99,
    "deployer_tier": null,
    "sort": "velocity_desc"
  },
  "returned": 1,
  "note": "Pre-bond pump.fun tokens. velocity = Δprogress/min (null until a 5m snapshot exists). eta_minutes is a linear projection from current velocity."
}

Wallet Tracker

Watchlist any Solana wallet.

PRO/ULTRA only — 50 / 100 / 500 wallets (Pro / Ultra / Business). Events stored 120 days. ULTRA gets the WS push channel. Robinhood Chain has its own watchlist at /rhc/wallet-tracker/* with a separate per-chain quota.

Webhooks are subscriber-scoped — you only receive events for wallets you added.
GET/wallet-tracker/watchlistPRO

List Watchlist

List all tracked wallets with labels, added_at timestamps, and remaining capacity. PRO: 50 wallets. ULTRA: 100. BUSINESS: 500. PRO/ULTRA only — BASIC keys receive 403 on every /wallet-tracker/* route.

Example Response

{
  "wallets": [
    {
      "wallet_address": "7xKX...3bPq",
      "label": "whale #1",
      "added_at": "2026-04-15T10:00:00Z"
    }
  ],
  "count": 1,
  "limit": 50,
  "remaining": 49
}
POST/wallet-tracker/watchlistPRO

Add Wallet

Add a Solana wallet to your watchlist. Returns HTTP 409 if the wallet is already tracked or the tier limit is reached. PRO: 50, ULTRA: 100, BUSINESS: 500. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
wallet_addressstringrequiredSolana wallet address (base58)
labelstringnullOptional human-readable label

Example Response

{
  "wallet_address": "7xKX...3bPq",
  "label": "whale #1",
  "added_at": "2026-04-15T10:00:00Z",
  "remaining": 9
}
DELETE/wallet-tracker/watchlist/{address}PRO

Remove Wallet

Remove a wallet from your watchlist. Returns 404 if not found. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
addresspathrequiredSolana wallet address (base58)

Example Response

{
  "success": true
}
PATCH/wallet-tracker/watchlist/{address}PRO

Update Wallet Label

Update the label for a tracked wallet. Pass null to clear the label. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
addresspathrequiredSolana wallet address (base58)
labelstring | nullrequiredNew label or null to clear

Example Response

{
  "wallet_address": "7xKX...3bPq",
  "label": "renamed whale",
  "added_at": "2026-04-15T10:00:00Z"
}
GET/wallet-tracker/tradesPRO

Wallet Trade History

Historical swap and transfer events across all your watched wallets. Swaps = token trades (action buy or sell; no counterparty key). Transfers = SOL moved without a token change (action null; counterparty = the wallet on the other side when it could be matched, key omitted otherwise). block_time is our ingest clock, not chain time: order by slot for chain order (the default when no before cursor is sent). replayed = true when the row was recovered by a gap replay rather than delivered live. Retention: 120 days. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
walletstring—Filter to a specific wallet address
actionstring—Filter swaps by action: buy or sell (transfers have action null)
event_typestring—Filter by event type: swap or transfer
limitinteger50Max results (1–200)
orderstringslotslot (on-chain order) or block_time (ingest order). Defaults to slot, or to block_time when a before cursor is sent; an explicit value always wins
before_slotinteger—Cursor for order=slot: pass next_cursor_slot from the previous page
beforeinteger—Legacy cursor for order=block_time: pass next_cursor from the previous page

Example Response

{
  "events": [
    {
      "wallet_address": "7xKX...3bPq",
      "label": "whale #1",
      "event_type": "swap",
      "action": "buy",
      "token_mint": "EPjF...fEgN",
      "token_symbol": "EXAMPLE",
      "token_name": "Example Token",
      "sol_amount": 2.5,
      "token_amount": 1000000,
      "tx_signature": "5Hyj...kMnP",
      "block_time": 1744720800,
      "slot": 449476673,
      "replayed": false,
      "ingested_at": "2026-04-15T10:00:00.000Z",
      "timestamp": "2026-04-15T10:00:00.000Z"
    },
    {
      "wallet_address": "7xKX...3bPq",
      "label": "whale #1",
      "event_type": "transfer",
      "action": null,
      "token_mint": null,
      "token_symbol": null,
      "token_name": null,
      "sol_amount": 12,
      "token_amount": null,
      "counterparty": "9WzD...AWWM",
      "tx_signature": "3kPq...Zx7d",
      "block_time": 1744720740,
      "slot": 449476520,
      "replayed": false,
      "ingested_at": "2026-04-15T09:59:00.000Z",
      "timestamp": "2026-04-15T09:59:00.000Z"
    }
  ],
  "count": 2,
  "ordered_by": "slot",
  "next_cursor": null,
  "next_cursor_slot": null
}
GET/wallet-tracker/summaryPRO

Wallet Stats Summary

Per-wallet stats over a time window: swap counts, buys, sells, SOL bought/sold, last activity time. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
periodstring7dTime window: 24h, 7d, or 30d
walletstring—Filter to a specific wallet address

Example Response

{
  "wallets": [
    {
      "wallet_address": "7xKX...3bPq",
      "label": "whale #1",
      "swap_count": 24,
      "buys": 18,
      "sells": 6,
      "sol_bought": 45.2,
      "sol_sold": 38.7,
      "last_event_at": "2026-04-15T09:45:00Z"
    }
  ],
  "period": "7d"
}

Wallet

Universal wallet profile.

Stats, FIFO PnL with daily curve, open positions with live unrealized, and paginated raw trades — for any Solana wallet, not just curated KOLs.

Cost basis is observable over the last ~90 days. PRO+ on every endpoint; cache hits don't count against your quota.
GET/wallet/{address}PRO

Wallet Stats + Enrichments

Aggregate counters for any Solana wallet over the last 90 days (trade count, buys/sells split, SOL in/out, unique tokens) plus cross-product flags from kol_wallets, mv_alpha_wallets, and deployers. The flags block carries reputation classification: is_sniper (≥5 tokens early-bought with ≥80% flipped <5min, behavior-updated hourly), is_bundler (bought >1 token in the same block, lifetime flag), is_dumper (≥5 dump cohorts + 0 runners in a rolling 42d window) with the raw dump_cluster cohort counts, and bot_confidence (string enum: none/low/medium/high). Reputation flags are pump.fun-pipeline scoped — false means not observed, not verified clean. v1.8.1 adds four enrichment fields: top traded tokens with realized PnL + peak MC, trading-style signals (sniper rate, round-trip rate, median hold), deployer-tier distribution, and a recent-trades timeline. Sub-100ms even on heavy wallets. PRO+.

Parameters

NameTypeDefaultDescription
addresspathrequiredBase58 wallet address

Example Response

{
  "address": "ASVz...ybJk",
  "stats": {
    "first_seen": "2026-04-12T14:18:33Z",
    "last_seen": "2026-05-20T18:27:34Z",
    "total_trades": 1123,
    "buys": 564,
    "sells": 559,
    "bought_sol": 1494.39,
    "sold_sol": 1562.55,
    "unique_tokens": 324,
    "window_days": 90
  },
  "flags": {
    "is_kol": true,
    "kol_name": "Reljoo",
    "is_alpha_tracked": true,
    "bot_confidence": "low",
    "alpha_win_rate": 0.43,
    "alpha_net_pnl_sol": 68.2,
    "alpha_tokens_traded": 324,
    "is_deployer": false,
    "deployer_tokens_deployed": null,
    "deployer_bonding_rate": null,
    "is_sniper": false,
    "is_bundler": false,
    "is_dumper": false,
    "dump_cluster": {
      "dump_cohorts": 2,
      "runner_cohorts": 3,
      "total_cohorts": 5,
      "as_of": "2026-07-10T04:00:00Z"
    }
  },
  "top_tokens": [
    {
      "token_mint": "C7Py...pump",
      "token_symbol": "ALVEUS",
      "buys": 12,
      "sells": 9,
      "sol_in": 18.47,
      "sol_out": 22.13,
      "realized_pnl_sol": 3.66,
      "current_mc_usd": 124000,
      "peak_mc_usd": 380000,
      "last_traded_at": "2026-05-19T08:42:11Z"
    }
  ],
  "trading_style": {
    "total_trades": 1123,
    "avg_trade_size_sol": 2.72,
    "sniper_rate": 0.18,
    "early_entries": 202,
    "round_trip_rate": 0.84,
    "tokens_with_round_trips": 272,
    "median_hold_minutes": 47,
    "dominant_action": "balanced"
  },
  "deployer_breakdown": {
    "total_tokens": 89,
    "tracked_deployers": 4,
    "by_tier": [
      {
        "tier": "elite",
        "count": 38
      },
      {
        "tier": "good",
        "count": 27
      },
      {
        "tier": "rising",
        "count": 14
      },
      {
        "tier": "cold",
        "count": 10
      }
    ]
  },
  "recent_trades": [
    {
      "token_mint": "ASVz...pump",
      "token_symbol": "PEPE2",
      "action": "buy",
      "sol_amount": 1.42,
      "block_time": 1747900800,
      "traded_at": "2026-05-22T12:00:00Z",
      "tx_signature": "5Tx...abc"
    }
  ]
}
GET/wallet/{address}/flagsPRO

Point-In-Time Wallet Flags

What did we know about this wallet on a given date — as a first-class answer, not a reconstruction. For every flag source (deployer, alpha, dump_cluster, kol, sniper, bundler), returns the latest write-on-change snapshot with snapshot_at ≤ as_of, i.e. the state that was actually current at that moment. A source with `carried: true` was recorded before as_of and hadn't changed by then; a source that is `null` means no snapshot existed yet — we knew nothing about this wallet on that source at that time. Without `as_of`, returns the latest state (same values as the flags block on GET /wallet/{address}). Snapshots exist from 2026-08-28 (daily 01:20 UTC); deployer tier trajectory before that lives in /deployer-hunter/{wallet}/history. `history=true` adds the full change series for that wallet (newest first, ≤200 rows) for audit trails. PRO+.

Parameters

NameTypeDefaultDescription
addresspathrequiredBase58 wallet address
as_ofISO datetimenowMust include a UTC offset, e.g. 2026-07-15T00:00:00Z. Returns the state as of this moment.
historybooleanfalseInclude the full change series (≤200 rows, newest first)

Example Response

{
  "wallet": "CyaE1VxvBrahnPWkqm5VsdCvyS2QmNht2UFrKJHga54o",
  "as_of": "2026-09-06T07:15:18.203Z",
  "flagged": [
    "deployer",
    "dump_cluster",
    "kol",
    "sniper",
    "bundler"
  ],
  "sources": {
    "deployer": {
      "tier": "cold",
      "bonding_rate": 0.0989,
      "total_bonded": 65,
      "labeled_tokens": 59,
      "total_tokens_deployed": 657,
      "snapshot_at": "2026-08-28T18:48:36.884407+00:00",
      "active": true,
      "carried": true
    },
    "alpha": null,
    "dump_cluster": {
      "member": true,
      "dump_cohorts": 234,
      "total_cohorts": 263,
      "runner_cohorts": 29,
      "snapshot_at": "2026-09-06T01:20:00.008966+00:00",
      "active": true,
      "carried": true
    },
    "kol": {
      "name": "Cented",
      "member": true,
      "is_active": true,
      "strategy_tag": "scalper",
      "snapshot_at": "2026-08-28T18:48:36.884407+00:00",
      "active": true,
      "carried": true
    },
    "sniper": {
      "member": true,
      "snapshot_at": "2026-08-28T18:48:36.884407+00:00",
      "active": true,
      "carried": true
    },
    "bundler": {
      "member": true,
      "snapshot_at": "2026-08-28T18:48:36.884407+00:00",
      "active": true,
      "carried": true
    }
  },
  "note": "Write-on-change snapshots since 2026-08-28 (daily 01:20 UTC). carried=true means the state was recorded before as_of and had not changed by then. null = no snapshot at or before as_of for that source."
}
POST/wallet/batch/tradesPRO

Batch Wallet Trades

The recent trade tape for up to 50 wallets in ONE call — the poll-loop replacement for anyone tracking a wallet set over REST. Per wallet: newest trades since a unix-second cursor (default and floor: 90 days back), each with tx_signature, token_mint, action, sol/token amounts, price fields and traded_at. next_since in the response is the newest block_time seen — pass it back as since on the next poll to get only new trades. Counts as one request. PRO+.

Parameters

NameTypeDefaultDescription
walletsstring[]required1-50 base58 wallet addresses (array or comma-separated string)
sinceintegernow − 90dUnix seconds — only trades after this (floored at 90 days back)
limit_per_walletinteger20Trades per wallet (1-100)
actionstring—"buy" or "sell"

Example Response

{
  "wallets": [
    {
      "wallet": "7xKX...3bPq",
      "count": 2,
      "trades": [
        {
          "tx_signature": "5K7j...",
          "token_mint": "9aK2rFy1...pump",
          "action": "buy",
          "sol_amount": 1.5,
          "token_amount": 4200000,
          "price_sol": 3.57e-7,
          "block_time": 1755507662,
          "traded_at": "2026-08-18T09:41:02Z"
        }
      ]
    }
  ],
  "since": 1747731662,
  "next_since": 1755507662,
  "limit_per_wallet": 20,
  "coverage": {
    "history_start_days": 90,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)"
  }
}
POST/wallet/batch/classifyPRO

Batch Wallet Classify

Bulk reputation flags for up to 100 wallet addresses in one call — the batch counterpart to the flags block on GET /wallet/{address} (values are identical). Per wallet: is_sniper, is_bundler, is_dumper, is_kol + kol_name, bot_confidence (string enum: none/low/medium/high), and the raw dump_cluster cohort counts (null unless the wallet has recent cohort appearances). Flags are pump.fun-pipeline scoped — false means not observed, not verified clean. Pure index lookups: ~10ms per 100-address batch. Counts as 1 request against quota. PRO+.

Parameters

NameTypeDefaultDescription
walletsstring[] | stringrequired1-100 base58 wallet addresses — JSON array or comma-separated string

Example Response

{
  "wallets": [
    {
      "address": "7xKv...9mPQ",
      "is_sniper": true,
      "is_bundler": false,
      "is_dumper": false,
      "is_kol": true,
      "kol_name": "Cented",
      "bot_confidence": "low",
      "dump_cluster": {
        "dump_cohorts": 2,
        "runner_cohorts": 3,
        "total_cohorts": 5,
        "as_of": "2026-07-10T04:00:00Z"
      }
    },
    {
      "address": "3nQd...42aa",
      "is_sniper": false,
      "is_bundler": true,
      "is_dumper": true,
      "is_kol": false,
      "kol_name": null,
      "bot_confidence": "high",
      "dump_cluster": {
        "dump_cohorts": 6,
        "runner_cohorts": 0,
        "total_cohorts": 6,
        "as_of": "2026-07-10T04:00:00Z"
      }
    }
  ],
  "count": 2,
  "as_of": "2026-07-10T12:00:00Z"
}
GET/wallet/{address}/pnlPRO

Wallet PnL (FIFO)

Full per-wallet PnL: realized + unrealized SOL, profit factor, max drawdown, avg + median hold minutes, daily UTC PnL curve, closed positions sorted by pnl desc (with ROI %, hold minutes, win/loss), and open positions hydrated with current prices from market-cap tracker. Cached in wallet_analyses with dynamic TTL (5min / 1h / 24h based on activity). Cache hits don't count against your daily quota. Check `coverage.in_scope` before trusting a flat PnL: `false` means we hold no persisted trades for this wallet, so the numbers mean "not captured", NOT "no activity". Every cache hit is validated against the wallet's trade head — a wallet that traded after the cached analysis is recomputed (`cache_invalidated: new_activity`); `cache_age_seconds` + `cache_validation` report the source age. PRO+.

Parameters

NameTypeDefaultDescription
addresspathrequiredBase58 wallet address

Example Response

{
  "address": "ASVz...ybJk",
  "window_days": 90,
  "coverage": {
    "history_start": 1775984757,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)",
    "in_scope": true
  },
  "summary": {
    "realized_sol": 211.68,
    "unrealized_sol": -197.22,
    "total_pnl_sol": 14.46,
    "wins": 12,
    "losses": 8,
    "win_rate": 0.6,
    "profit_factor": 2.35,
    "avg_hold_minutes": 47,
    "median_hold_minutes": 22,
    "max_drawdown_sol": 4.81,
    "open_positions_count": 27,
    "closed_positions_count": 268,
    "total_tokens_traded": 324
  },
  "pnl_curve": [
    {
      "date": "2026-04-12",
      "day_pnl": 1.5,
      "cumulative_pnl": 1.5,
      "trades": 3
    },
    {
      "date": "2026-04-13",
      "day_pnl": -0.3,
      "cumulative_pnl": 1.2,
      "trades": 2
    }
  ],
  "closed_positions": [
    {
      "token_mint": "81QY...pump",
      "buy_count": 3,
      "sell_count": 2,
      "bought_sol": 2.5,
      "sold_sol": 7.7,
      "pnl_sol": 5.2,
      "roi_pct": 208,
      "hold_minutes": 47,
      "result": "win"
    }
  ],
  "open_positions": [
    {
      "token_mint": "5KSo...bonk",
      "token_amount": 1000,
      "cost_basis_sol": 1.5,
      "avg_entry_price_sol": 0.0015,
      "current_price_sol": 0.002,
      "current_value_sol": 2,
      "unrealized_sol": 0.5,
      "unrealized_pct": 33.3
    }
  ],
  "notes": {
    "cost_basis_observable_from": "2026-04-12T00:00:00Z"
  },
  "cache_hit": false,
  "ttl_seconds": 300
}
GET/wallet/{address}/positionsPRO

Open Positions

Open lots only — same data as /pnl's open_positions[] but without summary or curve. Shares the wallet_analyses cache: if you recently called /pnl for this wallet, this is an immediate cache hit. Mints without a current price in market-cap tracker return unrealized_sol: null rather than fabricated zero. An empty positions[] with `coverage.in_scope: false` means we hold no persisted trades for the wallet — "not captured", NOT "no activity". Cache hits are validated against the trade head (`cache_validation`, `cache_age_seconds`). PRO+.

Parameters

NameTypeDefaultDescription
addresspathrequiredBase58 wallet address

Example Response

{
  "address": "ASVz...ybJk",
  "coverage": {
    "history_start": 1775984757,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)",
    "in_scope": true
  },
  "positions": [
    {
      "token_mint": "5KSo...bonk",
      "token_amount": 1000,
      "cost_basis_sol": 1.5,
      "avg_entry_price_sol": 0.0015,
      "current_price_sol": 0.002,
      "current_value_sol": 2,
      "unrealized_sol": 0.5,
      "unrealized_pct": 33.3,
      "first_buy_at": "2026-05-01T10:00:00Z",
      "buys_in_position": 2
    }
  ],
  "cache_hit": true,
  "computed_at": "2026-05-20T18:25:42Z"
}
GET/wallet/{address}/holdingsULTRA

Verified Holdings

Current on-chain token balances, read live from the wallet's SPL + Token-2022 accounts (getTokenAccountsByOwner) plus native SOL — not trade-derived like /positions, so transfers, airdrops and CEX withdrawals are all reflected. Each holding is enriched from our data with price/market-cap, name/symbol, and transfer_delta: the on-chain amount minus the 90-day trade-derived net, which surfaces tokens that arrived or left WITHOUT a swap (airdrops, insider funding, wallet-hopping). Sorted by USD value (unpriced last). 90s cache; 6 uncached lookups/min (cache hits don't count). ULTRA.

Parameters

NameTypeDefaultDescription
addresspathrequiredBase58 wallet address
limitinteger2001-500 holdings returned
min_value_usdnumber0Hide holdings below this USD value

Example Response

{
  "address": "ASVz...ybJk",
  "sol_balance": 12.45,
  "holdings": [
    {
      "mint": "5KSo...bonk",
      "symbol": "BONK",
      "name": "Bonk",
      "amount": 1500000,
      "amount_raw": "1500000000000",
      "decimals": 5,
      "token_program": "spl",
      "price_usd": 0.0000132,
      "value_usd": 19.8,
      "market_cap_usd": 890000000,
      "is_bonded": true,
      "trade_derived_amount": 1200000,
      "transfer_delta": 300000
    }
  ],
  "summary": {
    "token_accounts": 42,
    "non_zero": 14,
    "returned": 14,
    "priced": 13,
    "total_value_usd": 1082.89,
    "truncated": false
  },
  "verified_at": "2026-07-05T18:25:42Z",
  "trade_window_days": 90,
  "cache_hit": false,
  "ttl_seconds": 90
}
GET/wallet/{address}/tradesPRO

Paginated Trades

Cursor-paginated raw trades from token_trades. Cursor encodes (block_time, id) for stable DESC ordering across pages. Filters: action (buy/sell), token_mint, since/until Unix timestamps (default 90-day window), limit 1-500 (default 100). The `coverage` block disambiguates an empty page: `in_scope: false` means the wallet is outside our launchpad write-gate, so no rows means "not covered by our capture", NOT "no activity". PRO+.

Parameters

NameTypeDefaultDescription
addresspathrequiredBase58 wallet address
limitinteger1001-500
cursorstring—From next_cursor of previous page
actionstring—buy or sell
token_mintstring—Filter to one token
sinceintegernow-90dUnix epoch seconds
untilintegernowUnix epoch seconds

Example Response

{
  "address": "ASVz...ybJk",
  "trades": [
    {
      "tx_signature": "5Hyj...kMnP",
      "token_mint": "81QY...pump",
      "action": "buy",
      "sol_amount": 1.002,
      "token_amount": 278537,
      "block_time": 1747746000,
      "traded_at": "2026-05-20T12:20:00Z"
    }
  ],
  "next_cursor": "MTc0Nzc0NjAwMDoxMjM0NQ==",
  "has_more": true,
  "filters": {
    "action": null,
    "token_mint": null,
    "since": 1739970000,
    "until": 1747746000
  },
  "coverage": {
    "history_start": 1775984757,
    "scope": "pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)",
    "in_scope": true
  }
}

Copy-Trade

Per-rule signals on tracked KOL wallets.

PRO: 3 rules × 5 wallets. ULTRA: 20 × 50. Signals fire to webhook / WS in ~1–1.5 s. Robinhood Chain has its own rules at /rhc/copytrade/* with a separate per-chain quota.

HMAC-SHA256 signed delivery per rule. You handle the trade execution. Rules fire only for wallets in the KOL tracker; for any other Solana wallet, use the Wallet Tracker. The RHC equivalent is ETH-denominated (min_trade_eth / sizing_amount) and has no market-cap band.
POST/copytrade/subscriptionsPRO

Create Copy-Trade Rule

Register a copy-trade rule targeting one or more tracked KOL wallets (rules fire only for wallets in the KOL tracker; for any other Solana wallet, use the Wallet Tracker). When a matching trade hits our gRPC pipeline, a signal fires to your webhook and/or WebSocket in ~1–1.5s. Returns the HMAC secret once — save it for signature verification. PRO: 3 rules × 5 source wallets each. ULTRA: 20 rules × 50 wallets each. BUSINESS: 100 rules × 250 wallets each. Your own per-rule limit is `features.copytrade_wallets_per_rule.limit` on GET /me.

Parameters

NameTypeDefaultDescription
source_walletsstring[]requiredSolana wallets to copy (1 to your tier's per-rule limit: PRO 5, ULTRA 50, BUSINESS 250 base58 addresses)
sizing_amountnumberrequiredSize of the suggested copy trade (fixed SOL or multiplier, depending on sizing_mode)
delivery_modestringwebhook"webhook", "websocket", or "both"
webhook_urlstring—HTTPS URL — required when delivery_mode includes webhook
namestring—Human-readable label (≤64 chars)
min_trade_solnumber0Only fire on source trades ≥ this SOL size
only_actionstringbuy"buy", "sell", or "both"
sizing_modestringfixed"fixed" (SOL amount), "proportional" (multiplier × source size), or "percent_source"
min_mc_usdnumber | null—Only fire when the source trade's market cap ≥ this (USD, 0–1e12). Trades with unknown MC are dropped when set.
max_mc_usdnumber | null—Only fire when the source trade's market cap ≤ this (USD, 0–1e12); must be ≥ min_mc_usd

Example Response

{
  "subscription": {
    "id": 12,
    "name": "Cented buys only",
    "source_wallets": [
      "CyaE1Vxv...ga54o"
    ],
    "min_trade_sol": 0.5,
    "only_action": "buy",
    "sizing_mode": "fixed",
    "sizing_amount": 0.25,
    "delivery_mode": "both",
    "webhook_url": "https://your-app.com/copytrade/hook",
    "is_active": true,
    "created_at": "2026-04-18T14:00:00Z"
  },
  "webhook_secret": "a1b2c3...save-me",
  "note": "Save the webhook_secret — it will not be shown again. Use it to verify HMAC-SHA256 signatures on incoming webhook payloads."
}
GET/copytrade/subscriptionsPRO

List Copy-Trade Rules

List all your active and inactive copy-trade rules. Webhook secret is never returned here — only at creation time.

Example Response

{
  "subscriptions": [
    {
      "id": 12,
      "name": "Cented buys only",
      "source_wallets": [
        "CyaE1Vxv...ga54o"
      ],
      "min_trade_sol": 0.5,
      "only_action": "buy",
      "sizing_mode": "fixed",
      "sizing_amount": 0.25,
      "delivery_mode": "both",
      "webhook_url": "https://your-app.com/copytrade/hook",
      "is_active": true,
      "created_at": "2026-04-18T14:00:00Z"
    }
  ]
}
GET/copytrade/subscriptions/{id}PRO

Get Copy-Trade Rule

Fetch a single rule by ID. Returns 404 if the rule doesn't belong to your account.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredSubscription ID

Example Response

{
  "subscription": {
    "id": 12,
    "name": "Cented buys only",
    "source_wallets": [
      "CyaE1Vxv...ga54o"
    ],
    "only_action": "buy",
    "sizing_mode": "fixed",
    "sizing_amount": 0.25,
    "delivery_mode": "both",
    "webhook_url": "https://your-app.com/copytrade/hook",
    "is_active": true
  }
}
PATCH/copytrade/subscriptions/{id}PRO

Update Copy-Trade Rule

Update any rule field. Pass only the fields you want to change. Tier limits on source_wallets still apply.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredSubscription ID
source_walletsstring[]—Replace tracked wallets
min_trade_solnumber—New SOL threshold
only_actionstring—buy / sell / both
sizing_modestring—fixed / proportional / percent_source
sizing_amountnumber—New size or multiplier
delivery_modestring—webhook / websocket / both
webhook_urlstring | null—New HTTPS URL or null to clear
is_activeboolean—Pause (false) or resume (true)

Example Response

{
  "subscription": {
    "id": 12,
    "min_trade_sol": 1,
    "is_active": true,
    "updated_at": "2026-04-18T15:00:00Z"
  }
}
DELETE/copytrade/subscriptions/{id}PRO

Delete Copy-Trade Rule

Permanently delete a rule and its signal history. Returns 404 if not found.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredSubscription ID

Example Response

{
  "deleted": true
}
GET/copytrade/signalsPRO

Signal History

Last 7 days of signals fired by your rules. Each signal carries the source token's MC at trade time AND the current velocity context (`mc_change_pct`, `volume_usd`, `mev_volume_pct`) so you can see at a glance whether the signal token is still pumping or already faded — the difference between 'good entry' and 'chasing the top'. Useful for backfilling missed webhook deliveries or for audit. Always scoped to your account.

Parameters

NameTypeDefaultDescription
subscription_idinteger—Filter to a single rule
sinceISO 8601—Return signals fired at or after this time
limitinteger50Max signals (1–500)

Example Response

{
  "signals": [
    {
      "id": 4521,
      "subscription_id": 12,
      "fired_at": "2026-04-18T14:12:03.142Z",
      "source_wallet": "CyaE1Vxv...ga54o",
      "action": "buy",
      "token_mint": "tca3tbFf...pump",
      "token_symbol": "Hands Off",
      "source_sol_amount": 5.27,
      "suggested_sol_amount": 0.25,
      "tx_signature": "4fu8vvsF...v1sb",
      "market_cap_usd_at_trade": 28430,
      "market_cap_usd": 423000,
      "mc_change_pct": {
        "5m": 8.2,
        "15m": 31.4,
        "1h": 62.1,
        "2h": 75,
        "4h": 87
      },
      "volume_usd": {
        "5m": 42000,
        "15m": 118000,
        "1h": 340000,
        "2h": 500000,
        "4h": 920000
      },
      "mev_volume_pct": {
        "5m": 18.4,
        "1h": 27.3,
        "4h": 34.2
      },
      "delivered": true,
      "delivered_at": "2026-04-18T14:12:04.019Z"
    }
  ]
}

Price Alerts

MC dip/recovery alerts.

Evaluated on every 250 ms tick of the in-memory mc-tracker price feed. PRO: 5 alerts. ULTRA: 25. Robinhood Chain has its own alerts at /rhc/price-alerts/* with a separate per-chain quota.

Set a drop_pct threshold and get notified the instant a token's MC dips from its recent high. Optional recovery_pct fires a follow-up when it bounces. The RHC equivalent is event-driven off the chain trade feed and lands within a few seconds, not sub-second, so don't assume parity.
GET/price-alertsPRO

List Price Alerts

List all your token MC dip/recovery alert rules — active and inactive. PRO: 5 alerts max. ULTRA: 25 alerts max. Evaluated on every 250 ms tick of the in-memory mc-tracker price feed.

Example Response

{
  "alerts": [
    {
      "id": 4127,
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "name": "PEPE2 dip watch",
      "drop_pct": 20,
      "recovery_pct": 15,
      "delivery_mode": "webhook",
      "webhook_url": "https://my.bot/hooks/dip",
      "is_active": true,
      "created_at": "2026-05-25T08:00:00Z",
      "last_fired_at": "2026-05-25T12:42:11Z"
    }
  ],
  "count": 1
}
POST/price-alertsPRO

Create Price Alert

Create a token MC dip/recovery alert. When the token's market cap drops by `drop_pct` from its recent high, the alert fires via your chosen delivery mode. Optional `recovery_pct` triggers a follow-up when MC recovers from the dip low. Returns `webhook_secret` once if webhook delivery is configured. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
token_mintstringrequiredSolana token mint address (base58)
drop_pctnumberrequiredMC drop threshold (0.01-99.99). E.g. 20 = fire when MC drops 20% from recent high
recovery_pctnumber—Optional recovery threshold — fires when MC recovers this % from the dip low
namestring—Optional human-readable label (max 64 chars)
delivery_modestringwebsocket"websocket", "webhook", or "both"
webhook_urlstring—HTTPS URL — required when delivery_mode includes webhook

Example Response

{
  "alert": {
    "id": 4127,
    "token_mint": "9aK2rFy1...pump",
    "name": "PEPE2 dip watch",
    "drop_pct": 20,
    "recovery_pct": 15,
    "delivery_mode": "webhook",
    "webhook_url": "https://my.bot/hooks/dip",
    "is_active": true,
    "created_at": "2026-05-25T08:00:00Z"
  },
  "webhook_secret": "<32-byte hex -- shown once>",
  "note": "Save the webhook_secret -- it will not be shown again."
}
GET/price-alerts/{id}PRO

Get Price Alert

Fetch a single price alert rule by ID. Returns 404 if not found or not owned by the caller. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredAlert rule ID (integer)

Example Response

{
  "alert": {
    "id": 4127,
    "token_mint": "9aK2rFy1...pump",
    "token_symbol": "PEPE2",
    "name": "PEPE2 dip watch",
    "drop_pct": 20,
    "recovery_pct": 15,
    "delivery_mode": "webhook",
    "is_active": true,
    "created_at": "2026-05-25T08:00:00Z",
    "last_fired_at": null
  }
}
PATCH/price-alerts/{id}PRO

Update Price Alert

Update fields on a price alert rule. Patchable: name, delivery_mode, webhook_url, is_active. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredAlert rule ID (integer)
namestring—New label
delivery_modestring—websocket / webhook / both
webhook_urlstring | null—New HTTPS URL or null to clear
is_activeboolean—Pause (false) or resume (true)

Example Response

{
  "alert": {
    "id": 4127,
    "name": "Updated dip alert",
    "is_active": true,
    "updated_at": "2026-05-25T15:00:00Z"
  }
}
DELETE/price-alerts/{id}PRO

Delete Price Alert

Permanently delete a price alert and its event history. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredAlert rule ID (integer)

Example Response

{
  "deleted": true
}
GET/price-alerts/eventsPRO

Price Alert Event History

Historical dip/recovery events fired by your price alerts. Each event carries the token's MC at fire time, the drop/recovery percentage, and delivery status. Useful for backtesting alert quality and auditing missed deliveries. PRO/ULTRA only.

Parameters

NameTypeDefaultDescription
alert_idinteger—Filter to events from a specific alert rule
event_typestring—"dip" or "recovery"
sinceISO datetime—Only events after this timestamp
limitinteger50Max results (1-500)

Example Response

{
  "events": [
    {
      "id": "e7c12f88-...",
      "alert_id": 4127,
      "event_type": "dip",
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "mc_at_fire_usd": 340000,
      "recent_high_mc_usd": 750000,
      "drop_pct_actual": 54.7,
      "fired_at": "2026-05-25T12:42:11Z",
      "delivered": true
    },
    {
      "id": "f8d23a99-...",
      "alert_id": 4127,
      "event_type": "recovery",
      "token_mint": "9aK2rFy1...pump",
      "token_symbol": "PEPE2",
      "mc_at_fire_usd": 480000,
      "dip_low_mc_usd": 340000,
      "recovery_pct_actual": 41.2,
      "fired_at": "2026-05-25T14:18:33Z",
      "delivered": true
    }
  ],
  "count": 2
}

Bulk exports

Whole months, one download.

The archived history as Parquet files, for backtests and model training — no paging through the API. Business and Enterprise.

GET/exportsBUSINESS

Bulk Parquet Exports

Every fully archived closed month of token_trades, rhc_trades, token_ohlc_1m and rhc_ohlc_1m as zstd Parquet — the same immutable dual-provider archive behind /data-integrity. Call with no params to list what is archived (rows, bytes, files per month); add dataset + month for presigned S3 download links valid about 1 hour. The open month is never listed — it is live in Postgres behind the paginated endpoints. BUSINESS+ (Enterprise passes). Errors: 400 invalid_params, 404 month_not_archived, 502 archive_unavailable.

Parameters

NameTypeDefaultDescription
datasetstring—token_trades · rhc_trades · token_ohlc_1m · rhc_ohlc_1m — required together with month; omit both to list
monthstring—Closed month YYYY-MM (UTC) — required together with dataset

Example Response

{
  "dataset": "token_trades",
  "month": "2026-07",
  "rows": 412884920,
  "bytes": 41206118400,
  "files": [
    {
      "name": "token_trades/2026-07/part-0001.parquet",
      "bytes": 2147483648,
      "url": "https://…/token_trades/2026-07/part-0001.parquet?X-Amz-Signature=…",
      "expires_at": "2026-09-12T15:04:05Z"
    }
  ],
  "license_note": "Business embed license — display inside your product; redistribution requires Enterprise."
}

Sniper Alerts (Pro + Ultra)

Pre-confirm pump.fun deploys.

New token launches surface a median ~290ms before they confirm on-chain. Webhook + WS delivery. PRO covers elite + good deployers; ULTRA adds every tier, custom watchlists, and the by-deployer feed.

The read API is for backtesting and post-hoc auditing — live alerts flow via the sniper:deploy webhook event, or the sniper:deploys WebSocket channel. Payloads carry no execution metadata (no MC, balances, logs) because detection is pre-execution; ~1-3% of detected deploys may abandon before chain settlement (confidence: 'deshred').
GET/sniper/recentPRO

Recent pre-confirm deploys (Pro + Ultra)

Newest-first list of pump.fun deploys detected before chain settlement. Median ~290ms head start in production vs CONFIRMED-stream alerts (24 h to 2026-09-20, n = 37,957 reconciled deploys, p10 160ms / p90 401ms; the confirmed stream is first on ~3.4% of launches, which is why the head start is published as a median, not a floor). Payload carries mint + deployer + signature + slot + a snapshot of the deployer's reputation (tier, lifetime bond rate, last-10 outcome bitmap). Each deploy also carries a `footprint` block — the slot-window snipe rollup (slots deploy−1 to deploy+3): buys, buyers, sol, supply_pct, sniper_wallet_buys, data_available, as_of; null for deploys younger than the rollup's 10-minute settle window. attribution_status says whether the deshred read of the deployer was cross-checked against the confirmed create tx (every 15 min): unverified until checked, confirmed when it matched, corrected when the deployer/mint was fixed from the confirmed tx (attribution_checked_at = when that ran). For live alerts use the `sniper:deploy` webhook event or the `sniper:deploys` WebSocket channel; this endpoint is for backtesting / catch-up after a gap. PRO is curated to elite/good-tier deployers; ULTRA sees every tier, and ULTRA can pass watchlist=true to narrow the feed to its custom deployer watchlist (an empty watchlist answers deploys: [] with watchlist_empty: true). Every 200 carries the launch-pipeline `coverage` block.

Parameters

NameTypeDefaultDescription
sinceISO datetime—Only deploys detected after this timestamp
deployer_tierstring—elite / good / moderate / rising / cold / unranked
min_bond_ratenumber—Minimum lifetime bond rate (0-1, e.g. 0.5 = 50%)
watchlistbooleanfalseULTRA only — true narrows to the deployers on your sniper watchlist (any tier, overrides the tier scope); 403 on PRO
limitinteger50Max results (1-200)

Example Response

{
  "deploys": [
    {
      "mint": "9kQu...3xY7pump",
      "name": "Waffle Inu",
      "symbol": "WAFFLE",
      "deployer_wallet": "7dEx...4pQ8",
      "signature": "5xT...8jK",
      "slot": 305418729,
      "detected_at": "2026-05-28T19:32:29.068Z",
      "detection_region": "Frankfurt",
      "detection_confirmed": false,
      "attribution_status": "confirmed",
      "attribution_checked_at": "2026-05-28T19:45:01Z",
      "deployer_tier": "elite",
      "deployer_bond_rate": 0.734,
      "deployer_total_bonded": 11,
      "deployer_recent": "BBBBBFBBB",
      "confirmed_on_chain": null,
      "confirmed_at": null,
      "footprint": {
        "buys": 14,
        "buyers": 9,
        "sol": 12.4,
        "supply_pct": 3.8,
        "sniper_wallet_buys": 4,
        "data_available": true,
        "as_of": "2026-05-28T19:42:30Z"
      }
    }
  ],
  "count": 1,
  "data_age_seconds": 4
}
GET/sniper/by-deployer/{wallet}ULTRA

Sniper feed for a specific deployer (Ultra)

Recent pre-confirm deploys filtered to a single deployer wallet. Useful for auditing a deployer's recent track record before adding them to a custom watchlist.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredDeployer wallet address (base58, 32-44 chars)
limitinteger50Max results (1-200)

Example Response

{
  "deployer": "7dEx...4pQ8",
  "deploys": [
    {
      "mint": "9kQu...3xY7pump",
      "symbol": "WAFFLE",
      "signature": "5xT...8jK",
      "slot": 305418729,
      "detected_at": "2026-05-28T19:32:29.068Z",
      "detection_region": "Frankfurt",
      "deployer_tier": "elite",
      "deployer_bond_rate": 0.734,
      "deployer_total_bonded": 11,
      "confirmed_on_chain": null
    }
  ],
  "count": 1
}
GET/sniper/watchlistULTRA

List custom deployer watchlist (Ultra)

Your custom sniper watchlist — specific deployer wallets you want alerts for regardless of tier. Enable it as a scope on any channel: `?watchlist=true` here, `sniper_scope: "watchlist"` in a webhook/WS subscription. Ultra only, up to 50 deployers.

Example Response

{
  "deployers": [
    {
      "deployer_wallet": "7dEx...4pQ8",
      "label": "alpha dev",
      "created_at": "2026-05-29T18:00:00Z"
    }
  ],
  "count": 1,
  "limit": 50,
  "remaining": 49
}
POST/sniper/watchlistULTRA

Add to watchlist (Ultra)

Add one deployer (`wallet`) or many (`wallets[]`, the paste-50-addresses case), with an optional `label`. Idempotent — already-watchlisted deployers are skipped. DELETE /sniper/watchlist/{wallet} removes one.

Parameters

NameTypeDefaultDescription
walletstring—Single deployer wallet (base58)
walletsstring[]—Bulk add (max 50)
labelstring—Optional note for the added deployer(s)

Example Response

{
  "added": 2,
  "deployers": [
    "7dEx...4pQ8",
    "9aBc...2zZ1"
  ]
}
DELETE/sniper/watchlist/{wallet}ULTRA

Remove from watchlist (Ultra)

Remove one deployer wallet from your custom sniper watchlist. 404 if it isn't on your list. Ultra only.

Parameters

NameTypeDefaultDescription
walletstring (path)requiredDeployer wallet (base58)

Example Response

{
  "removed": "7dEx...4pQ8"
}

Robinhood Chain

Second chain, same key.

Every plan covers Robinhood Chain (chain id 4663) at no extra cost — one key, one shared quota pool, EVM-native field names.

Robinhood Chain (chain id 4663)

KOL, wallets, tokens, trades & deployers on RHC.

Same KOL wallets (bridge-traced to their EVM addresses), plus any-wallet PnL and positions, chain-wide token discovery, the DEX trade tape, candles and deployer reputation — from our self-hosted node. Copy-trade rules, price alerts, coordination alerts and first-touch subscriptions all have RHC equivalents here, each on its own PER-CHAIN quota that never touches your Solana budget. 14 WebSocket channels ride the standard stream: rhc:kol_trades, rhc:dex_trades, rhc:dex_trades_unattributed, rhc:new_tokens, rhc:copytrade:signals, rhc:price_alert:events, rhc:kol:coordination, rhc:kol:first_touches, rhc:token_locks, rhc:token_prices, rhc:lp_events, rhc:token_candles, rhc:token_risk and rhc:wallet_scores.

Responses echo chain: 'robinhood' and use EVM-native fields (eth_amount, token_address, tx_hash). The full interactive schema for every /rhc/* endpoint lives in the dedicated reference at /robinhood/api.
GET/rhc/kol/feedFREE

RHC KOL Trade Feed

Live buys and sells on Robinhood Chain from the same verified KOL wallets we track on Solana — EVM addresses traced through their bridge deposits. Free tier.

Parameters

NameTypeDefaultDescription
limitinteger50Number of trades (1-100)
actionstring—Filter: "buy" or "sell"
walletstring—Filter by KOL 0x address
min_kol_winratenumber—Minimum 7d winrate of the KOL, 0–1 (a FRACTION, not the 0–100 percent the Solana /kol/feed takes). Resolved from the RHC KOL score matview, which scores CLOSED positions only — a KOL who never sells has a null winrate and is DROPPED, not treated as zero. So ?min_kol_winrate=0 is not a no-op: it means "scored, and non-negative".
strategystring—Hold-time bucket from the RHC score matview: "scalper", "day_trader", "swing", "inactive" or "unscored". These values DIFFER from the Solana /kol/feed strategy set (swing_trader / hodler / mixed) — it is a separate classifier, not a port. Like min_kol_winrate, KOLs absent from the matview are dropped.

Example Response

{
  "chain": "robinhood",
  "trades": [
    {
      "kol_name": "danny",
      "evm_address": "0x4a9f…c21e",
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "action": "buy",
      "eth_amount": 0.215,
      "market_cap_usd_at_trade": 3300000,
      "dex": "uniswap-v4",
      "tx_hash": "0x7d1a…8e3f",
      "traded_at": "2026-07-15T17:04:12+00:00"
    }
  ],
  "count": 1
}
GET/rhc/kol/leaderboardFREE

RHC KOL Leaderboard

Net-flow leaderboard of KOLs on Robinhood Chain over 24h/7d/30d windows. Free tier.

Parameters

NameTypeDefaultDescription
periodstring24h"24h", "7d" or "30d"

Example Response

{
  "chain": "robinhood",
  "leaderboard": [
    {
      "kol_name": "danny",
      "trades": 42,
      "buy_eth": 12.4,
      "sell_eth": 3.1
    }
  ]
}
GET/rhc/kol/hot-tokensFREE

RHC KOL Hot Tokens

Consensus signal — tokens bought by 2+ distinct tracked KOLs on Robinhood Chain inside the window, ranked by KOL-buyer count then volume, enriched with launchpad, deployer tier, graduation and current MC. Free tier.

Parameters

NameTypeDefaultDescription
windowstring1hRolling consensus window: "5m", "15m", "1h", "6h" or "24h"

Example Response

{
  "chain": "robinhood",
  "window": "1h",
  "tokens": [
    {
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "kol_buyer_count": 4,
      "buy_volume_eth": 6.2,
      "market_cap_usd": 3300000,
      "deployer_tier": "good"
    }
  ],
  "count": 1
}
GET/rhc/kol/coordinationFREE

RHC KOL Coordination Detector

Tokens on Robinhood Chain that ≥ min_kols distinct tracked KOLs bought inside the window — the read/poll twin of the /rhc/kol/coordination/alerts rule engine. Each cluster carries buy/sell/net ETH, accumulating vs distributing signal, exited vs holding KOL counts, time-to-consensus and MC at first buy / now / peak. RHC has no KOL winrate / strategy / coordination-score MVs, so those Solana fields are intentionally absent. Optional MC band on entry MC. Free tier.

Parameters

NameTypeDefaultDescription
periodstring24h"1h", "6h", "24h" or "7d" ("window" accepted as an alias)
min_kolsinteger2Minimum distinct KOL buyers (2-50)
limitinteger20Max results (1-50)
min_mc_usdnumber—Entry-MC floor in USD
max_mc_usdnumber—Entry-MC ceiling in USD

Example Response

{
  "chain": "robinhood",
  "period": "24h",
  "min_kols": 2,
  "coordination": [
    {
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "token_name": "Cash Cat",
      "launchpad": "clanker",
      "is_graduated": true,
      "deployer_tier": "good",
      "token_age_minutes": 92,
      "kol_count": 4,
      "total_buys": 7,
      "buy_eth": 6.2,
      "sell_eth": 0.4,
      "net_eth": 5.8,
      "signal": "accumulating",
      "exited_count": 1,
      "holders_count": 3,
      "first_buy_at": "2026-08-18T08:02:11Z",
      "last_buy_at": "2026-08-18T08:41:50Z",
      "time_to_consensus_sec": 2379,
      "market_cap_usd_at_first_buy": 412000,
      "current_mc_usd": 1180000,
      "peak_mc_usd": 1420000,
      "liquidity_usd": 96000,
      "kols": [
        {
          "kol_name": "danny",
          "evm_address": "0x4a9f…c21e"
        }
      ]
    }
  ],
  "count": 1
}
GET/rhc/kol/first-touchesFREE

RHC KOL First Touches

The earliest tracked-KOL buy per Robinhood Chain token — one row per token, ever (a second KOL buying the same token is not a first touch). Enriched with launchpad, graduation flag, token age and MC at first buy / now / peak. Free tier (limit clamped to 20 on BASIC); ULTRA adds the KOL's evm_address on each row.

Parameters

NameTypeDefaultDescription
limitinteger50Max events (1-100)
since / beforeISO datetime—Cursor window on first_buy_at (pass next_before from the previous page)
min_ethnumber—Minimum first-buy size in ETH
token_age_max_mininteger—Only tokens younger than N minutes at first touch (1-43200)
launchpadstring—Launchpad slug filter
min_mc_usd / max_mc_usdnumber—MC band at first touch (USD)

Example Response

{
  "chain": "robinhood",
  "events": [
    {
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "token_name": "Cash Cat",
      "launchpad": "clanker",
      "is_graduated": true,
      "first_buy_at": "2026-07-15T17:04:12Z",
      "eth_amount": 0.215,
      "token_amount": 1240000,
      "tx_hash": "0x7d1a…8e3f",
      "token_age_minutes": 4,
      "market_cap_usd_at_first_buy": 412000,
      "price_usd_at_first_buy": 0.00041,
      "current_mc_usd": 101000000,
      "peak_mc_usd": 206000000,
      "first_kol": {
        "name": "danny",
        "twitter_url": "https://x.com/danny"
      }
    }
  ],
  "count": 1,
  "next_before": "2026-07-15T17:04:12Z",
  "data_age_seconds": 41
}
GET/rhc/kol/{wallet}FREE

RHC KOL Profile

A single KOL's Robinhood Chain profile — identity (name, Twitter), aggregate stats, and their 50 most recent RHC trades with MC-at-trade and tx hash. Free tier.

Parameters

NameTypeDefaultDescription
walletstring—KOL EVM wallet address (0x, 40 hex) — path param

Example Response

{
  "chain": "robinhood",
  "evm_address": "0x4a9f…c21e",
  "kol_name": "danny",
  "kol_twitter": "danny",
  "stats": {
    "trades": 128,
    "buy_eth": 42.1,
    "sell_eth": 18.7
  },
  "trades": [
    {
      "token_symbol": "CASHCAT",
      "action": "buy",
      "eth_amount": 0.215,
      "tx_hash": "0x7d1a…8e3f"
    }
  ]
}
GET/rhc/tradesPRO

RHC DEX Trade Tape

Every v2/v3/v4 + launchpad-curve swap on the chain with real trader EOA, gas, MC-at-trade and pool liquidity. PRO+.

Parameters

NameTypeDefaultDescription
tokenstring—Filter by token 0x address
dexstring—"uniswap-v2", "uniswap-v3" or "uniswap-v4"
actionstring—"buy" or "sell"
limitinteger50Number of trades (1-200)
beforestring—Keyset cursor — pass `next_before` from the previous page

Example Response

{
  "chain": "robinhood",
  "trades": [
    {
      "token_address": "0x8c3b…9f04",
      "action": "sell",
      "eth_amount": 1.2,
      "trader_eoa": "0x4a9f…c21e",
      "dex": "uniswap-v3",
      "block_number": 11133411
    }
  ]
}
GET/rhc/tokens/{address}/tradesFREE

RHC Token Trade Tape

Alias of /rhc/trades?token={address} — one token's swaps, newest first, keyset-paginated; same params (dex, action, limit 1-200, before). Inherits the /rhc/trades gate. PRO+.

Parameters

NameTypeDefaultDescription
addressstring (path)requiredRHC token 0x address
limitinteger50Number of trades (1-200)
beforestring—Keyset cursor (next_before)

Example Response

{
  "chain": "robinhood",
  "trades": [
    {
      "token_address": "0x8c3b…9f04",
      "action": "buy",
      "eth_amount": 0.4,
      "trader_eoa": "0x4a9f…c21e",
      "dex": "uniswap-v4",
      "tx_hash": "0x7d1a…8e3f",
      "block_time": "2026-07-15T17:04:12Z"
    }
  ],
  "has_more": true,
  "next_before": "eyJi…"
}
GET/rhc/tokensPRO

RHC Token Discovery

Screener over every token on the chain: sort by last trade, market cap, liquidity, peak MC or newest; launchpad, asset-class and liquidity/MC floors. /rhc/tokens/new and /rhc/tokens/recent are aliases pinned to sort=newest. PRO+.

Parameters

NameTypeDefaultDescription
sortstringlast_trade"last_trade", "market_cap", "liquidity", "peak_mc", "newest"
limitinteger50Number of tokens (1-100)
sinceISO datetime—Only tokens first seen after this time (with sort=newest)
asset_classstring—"equity" (tokenized stocks/ETFs) or "other"
launchpadstring—Launchpad slug filter
min_mc_usdnumber—Minimum market cap in USD
min_liquidity_usdnumber—Minimum pool liquidity in USD

Example Response

{
  "chain": "robinhood",
  "tokens": [
    {
      "address": "0x8c3b…9f04",
      "symbol": "CASHCAT",
      "market_cap_usd": 101000000,
      "liquidity_usd": 3360000,
      "deployer_tier": "good"
    }
  ]
}
GET/rhc/tokens/newFREE

RHC Newest Tokens

Alias of /rhc/tokens?sort=newest — the newest tokens on the chain, first-seen order; every other /rhc/tokens param (since, limit, asset_class, launchpad, min_mc_usd, min_liquidity_usd) passes through. /rhc/tokens/recent is the same alias. Inherits the /rhc/tokens gate. PRO+.

Parameters

NameTypeDefaultDescription
sinceISO datetime—Only tokens first seen after this time
limitinteger50Number of tokens (1-100)

Example Response

{
  "chain": "robinhood",
  "tokens": [
    {
      "address": "0x1f2e…aa10",
      "symbol": "NEWCAT",
      "launchpad": "clanker",
      "first_seen_at": "2026-08-18T09:40:11Z",
      "market_cap_usd": 18400,
      "liquidity_usd": 6100
    }
  ]
}
GET/rhc/tokens/recentFREE

RHC Recent Tokens (alias)

Alias of /rhc/tokens?sort=newest — identical to /rhc/tokens/new. Inherits the /rhc/tokens gate. PRO+.

Parameters

NameTypeDefaultDescription
limitinteger50Number of tokens (1-100)

Example Response

{
  "chain": "robinhood",
  "tokens": [
    {
      "address": "0x1f2e…aa10",
      "symbol": "NEWCAT",
      "first_seen_at": "2026-08-18T09:40:11Z"
    }
  ]
}
GET/rhc/equitiesFREE

RHC Tokenized Equities (stocks & ETFs)

Every Robinhood-issued tokenized stock / ETF on the chain with live price, MC, liquidity and 24h trades / ETH volume / buyers / sellers. Identity is the issuer BEACON (EIP-1967 beacon proxy on Robinhood's issuer beacon 0xe10b…151b00, read from our own node) — never the name, so the fake "GameStop • Robinhood Token" contracts never appear and verified is true by construction. The response states the identity method and beacon. Free tier; per-token drill-downs (/trades, /holders, /candles) keep their own gates.

Parameters

NameTypeDefaultDescription
sortstringvolume"volume" (24h ETH), "trades" (24h), "market_cap", "last_trade", "symbol"
limitinteger100Number of equities (1-300)
symbolstring—Exact ticker, e.g. NVDA
qstring—Substring of symbol or name (1-40 chars)

Example Response

{
  "chain": "robinhood",
  "equities": [
    {
      "address": "0x33a1…c9d2",
      "symbol": "NVDA",
      "name": "Nvidia • Robinhood Token",
      "underlying_name": "Nvidia",
      "verified": true,
      "last_price_usd": 181.42,
      "market_cap_usd": 44200000,
      "liquidity_usd": 1900000,
      "trades_24h": 12034,
      "volume_eth_24h": 2229.4,
      "buyers_24h": 3120,
      "sellers_24h": 2870,
      "primary_dex": "uniswap-v4",
      "last_trade_time": "2026-08-18T09:41:50Z"
    }
  ],
  "count": 1,
  "total_equities": 206,
  "sort": "volume",
  "identity": {
    "method": "beacon",
    "issuer_beacon": "0xe10b6f6b275de231345c20d14ab812db62151b00"
  }
}
GET/rhc/tokens/{address}FREE

RHC Token Detail

Full token bundle: price, MC, peak + drawdown, pools with reserves, deployer reputation block and KOL activity. Free tier.

Example Response

{
  "chain": "robinhood",
  "token": {
    "address": "0x8c3b…9f04",
    "symbol": "CASHCAT",
    "market_cap_usd": 101000000,
    "peak_mc_usd": 206000000,
    "deployer": {
      "address": "0x91ab…77c2",
      "tier": "good",
      "graduation_rate": 0.31,
      "runner_rate": 0.28
    }
  }
}
POST/rhc/token/batchFREE

RHC Token Batch

The /rhc/tokens/{address} bundle for up to 50 tokens in one request (body: { addresses: [...] }; "mints" is accepted as an alias key). Unknown addresses come back with found: false. GET /rhc/token/{address} is a compat alias of /rhc/tokens/{address}. Free tier.

Parameters

NameTypeDefaultDescription
addressesstring[]required1-50 RHC token 0x addresses

Example Response

{
  "chain": "robinhood",
  "tokens": [
    {
      "address": "0x8c3b…9f04",
      "found": true,
      "symbol": "CASHCAT",
      "market_cap_usd": 101000000,
      "liquidity_usd": 3360000,
      "deployer_tier": "good"
    },
    {
      "address": "0x0000…dead",
      "found": false
    }
  ],
  "requested": 2,
  "found": 1
}
GET/rhc/tokens/{address}/candlesPRO

RHC 1-Minute OHLC Candles

Per-minute OHLC + volume + close liquidity for any RHC token, built from the raw trade stream. PRO+.

Parameters

NameTypeDefaultDescription
limitinteger240Number of candles (1-1500)

Example Response

{
  "chain": "robinhood",
  "candles": [
    {
      "t": "2026-07-15T17:04:00Z",
      "o": 0.0021,
      "h": 0.0024,
      "l": 0.002,
      "c": 0.0023,
      "v_usd": 18240
    }
  ]
}
GET/rhc/tokens/{address}/kol-consensusPRO

RHC KOL Consensus

How the tracked-KOL cohort is positioned on an RHC token: distinct buyers vs sellers, exit rate, net ETH flow, and median entry market cap. PRO+ (ULTRA adds the buyer/exited wallet lists).

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "consensus": {
    "total_kol_buyers": 83,
    "total_kol_sellers": 72,
    "kol_exit_rate": 0.735,
    "net_flow_eth": -407.5,
    "median_entry_mc_usd": 63279213,
    "entry_mc_samples": 256
  }
}
GET/rhc/tokens/{address}/buyer-qualityFREE

RHC Buyer Quality

A 0-100 quality score on an RHC token's earliest buyer cohort — full parity with the Solana scorer: win-rate + KOL + bot + bundle-buyer + dump-cluster legs. `coverage` reports both bundle_detection and dump_cluster_signal available (dump-cluster is informational and out-of-sample validated). Free tier.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "cohort_selection": "distinct_first_buy",
  "quality": {
    "score": 28,
    "confidence": "high",
    "signal": "negative",
    "breakdown": {
      "early_buyers_analyzed": 20,
      "wallets_with_history": 14,
      "qualified_win_rate_wallets": 12,
      "alpha_wallet_count": 8,
      "kol_count": 0,
      "bundle_buyer_count": 6,
      "dump_cluster_count": 6,
      "recycled_early_buyer_count": 15,
      "avg_historical_win_rate": 48.41,
      "bot_dominated": true
    }
  },
  "coverage": {
    "bundle_detection": "available",
    "dump_cluster_signal": "available"
  }
}
POST/rhc/tokens/batch/buyer-qualityFREE

RHC Batch Buyer Quality

Buyer-quality scores for up to 20 RHC tokens in one call — same scorer and coverage block as the single-token endpoint. Body: { addresses: [...] }. Free tier.

Parameters

NameTypeDefaultDescription
addressesstring[]required1-20 RHC token 0x addresses

Example Response

{
  "chain": "robinhood",
  "tokens": [
    {
      "token_address": "0x8c3b…9f04",
      "score": 64,
      "signal": "positive",
      "breakdown": {
        "kol_buyers": 3,
        "bot_buyers": 1,
        "dump_cluster_count": 0
      }
    }
  ],
  "requested": 1,
  "max_addresses": 20,
  "coverage": {
    "bundle_detection": true,
    "dump_cluster_signal": true
  }
}
GET/rhc/tokens/{address}/bundleFREE

RHC Launch-Bundle Detection

Detects a coordinated launch bundle in an RHC token's earliest buyers: ranks the first 20 by on-chain order, flags a bundle when 3+ buy in the same block, then reports how much of what they bought they still hold — or if they fully exited (bought the launch, then dumped). BASIC gets the scalar signal; PRO the top-10 wallets; ULTRA the full cohort with alpha-wallet identity.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "bundle": {
    "wallet_count": 9,
    "bundle_kind": "same_block",
    "held_ratio": 0,
    "held_pct_of_supply": 0,
    "fully_exited": true,
    "buy_volume": 261900000,
    "tokens_held": 0
  },
  "wallets": []
}
GET/rhc/tokens/{address}/top-tradersPRO

RHC Top Traders

Who actually made money on a token. Lifetime per-trader performance ranked by realized ETH, enriched with win-rate, bot heuristic, KOL identity, dump-cluster membership and early-buyer rank. net_eth is REALIZED flow (sell − buy), not PnL — it doesn't value a trader's remaining bag, so a wallet that bought and still holds ranks last. PRO returns 50 rows; ULTRA/BUSINESS 200.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address
limitnumber501–200 (capped at 50 on PRO)
offsetnumber0Page offset

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "traders": [
    {
      "trader_eoa": "0x3387…9694",
      "buy_eth": 412.3,
      "sell_eth": 759.5,
      "net_eth": 347.18,
      "trades": 992,
      "win_rate": 0.61,
      "likely_bot": true,
      "is_known_kol": false,
      "kol_name": null,
      "dump_cohorts": 0,
      "early_buyer_rank": null
    }
  ],
  "count": 1,
  "limit": 50,
  "offset": 0,
  "has_more": true,
  "metric": "net_eth = realized ETH flow (sell - buy); excludes unrealized bag value"
}
GET/rhc/tokens/{address}/flowPRO

RHC Cohort Flow

Who is accumulating and who is distributing. Splits a token's flow into mutually-exclusive trader cohorts — KOL, bot, dump-cluster, early-buyer, unprofiled, smart-money, retail. Sign convention: net_eth = sell − buy, so a positive value means that cohort DISTRIBUTED. smart_money is derived (win-rate ≥ 0.5 and net positive); unprofiled is a real answer, not missing data.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address
windowstring24h"1h", "6h", "24h", "7d"

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "window": "24h",
  "cohorts": [
    {
      "cohort": "bot",
      "traders": 1142,
      "trades": 10404,
      "buy_eth": 485.64,
      "sell_eth": 827.37,
      "net_eth": 341.73
    },
    {
      "cohort": "smart_money",
      "traders": 385,
      "trades": 1144,
      "buy_eth": 86.62,
      "sell_eth": 176.09,
      "net_eth": 89.46
    },
    {
      "cohort": "retail",
      "traders": 1365,
      "trades": 4054,
      "buy_eth": 465.83,
      "sell_eth": 325.97,
      "net_eth": -139.86
    }
  ],
  "sign_convention": "net_eth = sell - buy; positive = cohort distributed, negative = accumulated"
}
GET/rhc/tokens/{address}/peak-historyPRO

RHC Peak History

Peak market cap, drawdown from peak, and a running high-water curve. Returns TWO peaks because they disagree: peak_mc_usd_recorded is the stored high-water mark other surfaces key off (sampled from write batches, so it can undercount an intra-batch spike), while peak_mc_usd_observed is the max of 1-minute candle highs — trade-level truth, always ≥ recorded. Candle history starts 2026-07-15.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address
windowstring7d"24h", "7d", "30d", "all"
curvestringtrue"false" for the summary only

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "symbol": "NVDA",
  "current": {
    "market_cap_usd": 1412003,
    "liquidity_usd": 88120
  },
  "peak": {
    "peak_mc_usd_recorded": 1814857,
    "peak_mc_usd_observed": 2694095,
    "observed_covers_full_history": false,
    "pct_of_peak": 0.524,
    "drawdown_from_peak": 0.476
  },
  "curve": {
    "window": "7d",
    "bucket": "5m",
    "count": 1338
  }
}
GET/rhc/tokens/{address}/riskPRO

RHC Token Risk (EVM-native, live)

Risk computed LIVE against our own Robinhood Chain node. Not the Solana model — EVM has no mint or freeze authority, and only 2.3% of RHC tokens even expose an owner function, so an absent flag is the norm rather than a safety signal. What discriminates here: proxy upgradeability, LP custody, and above all sellability — a sell is simulated at the chain head to catch a token you can buy but not sell. Never cached.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "checked_at": "2026-07-29T20:12:46.369Z",
  "code_size": 4830,
  "is_contract": true,
  "proxy": {
    "kind": "eip1967_beacon",
    "implementation": "0xb354…5ae2",
    "upgradeable": true
  },
  "owner": {
    "model": "none",
    "address": null
  },
  "capabilities": {
    "can_mint": true,
    "can_pause": true,
    "has_access_control": true,
    "selectors_found": [
      "mint(address,uint256)",
      "pause()",
      "hasRole(bytes32,address)"
    ]
  },
  "liquidity": {
    "dex": "uniswap-v3",
    "lp_custody": "burned",
    "lp_burned_pct": 99.27
  },
  "sellability": {
    "sellable": "yes",
    "reason": null
  },
  "flags": [
    "mintable",
    "pausable",
    "upgradeable"
  ],
  "score": 55
}
GET/rhc/tokens/{address}/early-buyersPRO

RHC Early Buyers

The first buyers of an RHC token, in order, joined to what happened next — realized ETH, trade count, average entry market cap, and whether they still hold. Read position alongside realized_eth: it is sell minus buy, so a buyer who is still holding shows a NEGATIVE figure because they have spent and not yet sold. still_holding comes from the same Transfer-log fold as /holders, so treat it as exact only when holdings_verified is true. Ranks are as of computed_at (a daily sweep), so a token that started trading since then returns an empty list with a stated reason — never an assertion that it had no early buyers.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address
limitnumber201–20 (ranking depth is 20 by construction)

Example Response

{
  "chain": "robinhood",
  "token_address": "0x85f2…34f9",
  "computed_at": "2026-07-30T19:13:40Z",
  "holdings_verified": true,
  "early_buyers": [
    {
      "rank": 3,
      "wallet": "0x902c9d30…",
      "first_buy_at": "2026-07-29T11:02:14Z",
      "first_buy_block": 34118207,
      "still_holding": false,
      "balance": "0",
      "position": "closed",
      "bought_eth": 0.362932,
      "sold_eth": 0.483379,
      "realized_eth": 0.120447,
      "trades": 13,
      "avg_entry_mc_usd": 41288.55
    }
  ],
  "count": 20,
  "summary": {
    "ranked": 20,
    "with_holding_data": 20,
    "still_holding": 1,
    "exited": 19,
    "closed_positions": 19,
    "realized_eth_closed_only": 0.229843
  }
}
GET/rhc/tokens/{address}/holdersPRO

RHC Holders & Concentration

Exact holder set and concentration — folded from ERC-20 Transfer logs, not derived from trades, and reconciled against on-chain totalSupply(). Check verified first: false means the reconstruction is incomplete for that token and the response says why. Concentration excludes liquidity pools and burn addresses from the circulating denominator (the top holder is otherwise the token's own pool) and reports them separately. Balances are raw uint256 strings. holder_growth gives entered / exited / net holders over 1h, 24h and 7d — possible because the Transfer-log fold keeps first-seen and last-moved blocks per address.

Parameters

NameTypeDefaultDescription
addressstring—RHC token 0x address
limitnumber501–200 (capped at 50 on PRO)
offsetnumber0Page offset

Example Response

{
  "chain": "robinhood",
  "token_address": "0x8c3b…9f04",
  "verified": true,
  "unverified_reason": null,
  "holders": [
    {
      "holder": "0xb98b…ded7",
      "balance": "72595847095530512318459056",
      "share": 0.080699,
      "is_pool": true,
      "is_burn": false,
      "is_deployer": false
    }
  ],
  "concentration": {
    "holder_count": 214314,
    "top1_share": 0.04663,
    "top10_share": 0.245752,
    "top50_share": 0.62173,
    "hhi": 0.011576,
    "pool_held_pct": 0.072596,
    "burned_pct": 0.069595
  },
  "holder_growth": {
    "1h": {
      "cutoff_block": 38939885,
      "entered": 370,
      "entered_still_holding": 357,
      "exited": 12,
      "net": 345
    },
    "24h": {
      "cutoff_block": 38114592,
      "entered": 593,
      "entered_still_holding": 560,
      "exited": 0,
      "net": 560
    }
  },
  "source": {
    "method": "erc20_transfer_log_replay",
    "backfill_complete": true
  }
}
GET/rhc/lp-eventsPRO

RHC Liquidity Removals (rug signal)

Liquidity REMOVAL events across the chain from our own node's log subscription — Uniswap v2/v3 Burn logs and v4 ModifyLiquidity with a negative delta — newest first, keyset-paginated. By default removals only: a request without action returns exactly the historical feed, event is always "remove" and coverage.events says so. Since 2026-09-23 action=add|pool_created|all opts into liquidity adds (v2/v3 Mint, v4 positive ModifyLiquidity; kept 7 days) and live pool creations; earlier windows hold removals only, so an empty add page there means not recorded, not no adds. Every row also carries the depth fields tick_lower / tick_upper, liquidity_delta, in_range, active_liquidity_delta, active_share (v3/v4: a share of liquidity at the current price, not of TVL), share_of_reserves (v2) and material (a removal of at least 25 %), null where the pool state was unknown and on older rows. amount0/amount1/liquidity are raw uint256 strings; token_amount_raw / quote_amount_raw pre-resolve the token's side; v4 rows carry only liquidity (the pool manager emits no token amounts). provider is usually the router or position manager on v3/v4, not the beneficial owner. Live push: WS channel rhc:lp_events (ULTRA+). Per-token alias: GET /rhc/tokens/{address}/lp-events. PRO+.

Parameters

NameTypeDefaultDescription
tokenstring—Filter by token 0x address
poolstring—Pool address (v2/v3, 40 hex) or v4 poolId (64 hex)
dexstring—"uniswap-v2", "uniswap-v3" or "uniswap-v4"
providerstring—Liquidity provider 0x address
actionstringremove"remove" (default, unchanged), "add" (kept 7 days), "pool_created" or "all" (2026-09-23)
limitinteger50Number of events (1-200)
beforestring—Keyset cursor (next_before)

Example Response

{
  "chain": "robinhood",
  "events": [
    {
      "id": "8812734",
      "event": "remove",
      "pool": "0x5a1c…e0f9",
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "dex": "uniswap-v3",
      "provider": "0x91ab…77c2",
      "liquidity": "184223391004312",
      "amount0": "12000000000000000000",
      "amount1": "3922000000000000000000000",
      "token_amount_raw": "3922000000000000000000000",
      "quote_amount_raw": "12000000000000000000",
      "block_number": 11402211,
      "tx_hash": "0x9c…41",
      "log_index": 12,
      "block_time": "2026-08-18T08:12:40Z",
      "tick_lower": -887220,
      "tick_upper": 887220,
      "liquidity_delta": "-184223391004312",
      "in_range": true,
      "active_liquidity_delta": "-184223391004312",
      "active_share": 0.41,
      "share_of_reserves": null,
      "material": true
    }
  ],
  "count": 1,
  "has_more": true,
  "next_before": "eyJi…",
  "coverage": {
    "events": [
      "remove"
    ],
    "adds_persisted": true,
    "adds_retention_days": 7
  }
}
GET/rhc/tokens/{address}/lp-eventsFREE

RHC Token Liquidity Removals

Alias of /rhc/lp-events?token={address} — one token's liquidity removals, newest first; same params and the same removals-only coverage note. Inherits the /rhc/lp-events gate. PRO+.

Parameters

NameTypeDefaultDescription
addressstring (path)requiredRHC token 0x address
actionstringremoveSame as /rhc/lp-events: remove (default) | add | pool_created | all
limitinteger50Number of events (1-200)

Example Response

{
  "chain": "robinhood",
  "events": [
    {
      "event": "remove",
      "pool": "0x5a1c…e0f9",
      "dex": "uniswap-v3",
      "provider": "0x91ab…77c2",
      "block_time": "2026-08-18T08:12:40Z"
    }
  ],
  "count": 1,
  "has_more": false,
  "next_before": null,
  "coverage": {
    "events": [
      "remove"
    ],
    "adds_persisted": true,
    "adds_retention_days": 7
  }
}
GET/rhc/tokens/locksPRO

RHC Token Locks & Vesting Feed

Newest token lock / vesting contracts CREATED on Robinhood Chain, newest first — who just locked tokens, of what, how much, until when. Decoded from the locker contracts' own events on our node (PinkLock-compatible, HoodLock + vesting, Team Finance-compatible, Titan Locker, UNCX-compatible LP lockers, Sablier Lockup v4); a new deployment of a known locker shape is caught on its first event. Each row carries the on-chain schedule (start / cliff / end, cliff amount, tranches) and a live derived view: locked_* (still locked right now), unlocked_*, next_unlock (cliff | final | tranche), status. sender = depositor / creator (compare with the token's deployer for a dev lock), recipient = beneficiary; cancelable_by_sender from Sablier's flag. Raw base units as strings; ui / usd / pct null when decimals or price are unknown. Create-only tape: withdrawals are NOT tracked (withdrawn is null, coverage.withdrawals_tracked false). LP locks are excluded unless subject=lp|all and never claim usd / pct. Pushed live on WS channel rhc:token_locks. PRO+.

Parameters

NameTypeDefaultDescription
sincestring—ISO cursor — only locks created after it (pagination.next_since)
beforestring—ISO cursor — page back (pagination.next_before)
tokenstring—Filter by token 0x address
senderstring—Depositor / creator 0x address
recipientstring—Beneficiary 0x address
lockerstring—Locker contract 0x address
familystring—"pinklock", "hoodlock", "hoodlock-vesting", "teamfinance", "teamfinance-nft", "titan", "titan-position", "titan-vesting", "sablier", "uncx-v2-lp", "uncx-v3-lp", …
kindstring—"lock" or "vesting"
subjectstringtoken"token" (excludes LP locks), "lp" or "all"
statusstring—"active" or "completed"
min_usdnumber—Post-filter on the deposited amount in USD
min_pct_of_supplynumber—Post-filter on the deposited amount as % of supply
limitinteger50Number of locks (1-100)

Example Response

{
  "chain": "robinhood",
  "locks": [
    {
      "lock_id": "0x5fad…bc33:12",
      "locker": "0xd0f7…c32f",
      "locker_name": "HoodLock",
      "family": "hoodlock",
      "kind": "lock",
      "subject": "token",
      "status": "active",
      "token_address": "0x2331…589b",
      "sender": "0x79c1…cea2",
      "amount_raw": "528871244309257833409813",
      "amount": 528871.24,
      "amount_usd": 4120.5,
      "amount_pct_of_supply": 52.89,
      "locked_raw": "528871244309257833409813",
      "end_at": "2026-10-14T01:41:48Z",
      "next_unlock": {
        "at": "2026-10-14T01:41:48Z",
        "kind": "final",
        "amount": 528871.24
      },
      "cancelable_by_sender": null,
      "withdrawn_raw": null,
      "created_at": "2026-09-13T21:52:08Z",
      "tx_hash": "0x5fad…bc33",
      "token": {
        "symbol": "PONS",
        "decimals": 18,
        "price_usd": 0.00779
      }
    }
  ],
  "pagination": {
    "limit": 50,
    "count": 1,
    "has_more": true,
    "next_since": "2026-09-13T21:52:08Z",
    "next_before": "2026-09-13T21:52:08Z"
  },
  "stream": {
    "channel": "rhc:token_locks"
  },
  "coverage": {
    "withdrawals_tracked": false,
    "cancels_tracked": false
  }
}
GET/rhc/tokens/{address}/locksPRO

RHC Token Locks (per token)

Every lock / vesting contract on one Robinhood Chain token with a live summary — did the team lock, how much, until when, and can they cancel. summary covers the token-subject rows: locked / deposited (raw + ui + usd + % of supply), unlocking_7d_* / unlocking_30d_* (forward schedule), nearest next_unlock, active_cancelable_by_sender (funds are locked against the recipient, not the locker, when the sender can cancel), counts by family / kind, distinct depositing wallets; LP locks on the token's pools are counted apart (lp_lock_count) because their amounts are pair units. Rows active-first, largest locked first. token.facts_resolved false means decimals are unknown and every ui / usd / pct is null. Same create-only caveat as the feed. PRO+.

Parameters

NameTypeDefaultDescription
addressstring (path)requiredRHC token 0x address
statusstring—"active" or "completed"
familystring—Locker family (see /rhc/tokens/locks)
subjectstringall"token", "lp" or "all"
limitinteger200Rows returned (1-500); the summary always covers every row

Example Response

{
  "chain": "robinhood",
  "token_address": "0x2331…589b",
  "token": {
    "symbol": "PONS",
    "decimals": 18,
    "price_usd": 0.00779,
    "supply": 1000000,
    "market_cap_usd": 7790,
    "facts_resolved": true
  },
  "summary": {
    "lock_count": 3,
    "active_count": 2,
    "token_lock_count": 2,
    "lp_lock_count": 1,
    "by_family": {
      "hoodlock": 2,
      "pinklock": 1
    },
    "distinct_lockers": 1,
    "locked_raw": "528871244309257833409813",
    "locked": 528871.24,
    "locked_pct_of_supply": 52.89,
    "unlocking_7d": 0,
    "unlocking_30d": 528871.24,
    "next_unlock": {
      "at": "2026-10-14T01:41:48Z",
      "kind": "final",
      "lock_id": "0x5fad…bc33:12"
    },
    "active_cancelable_by_sender": 0
  },
  "locks": [
    {
      "lock_id": "0x5fad…bc33:12",
      "family": "hoodlock",
      "status": "active",
      "locked": 528871.24,
      "end_at": "2026-10-14T01:41:48Z"
    }
  ],
  "coverage": {
    "withdrawals_tracked": false
  }
}
GET/rhc/tokens/unlocksPRO

RHC Upcoming Unlocks

Upcoming unlock EVENTS across all active Robinhood Chain lock / vesting contracts — which tokens have supply hitting the market inside the window, how much, from whose lock. One entry per active contract = its NEXT cliff / tranche / final unlock inside within=1h..90d, with amount_* (the event, raw / ui / usd / % of supply) and window_amount_* (that contract's total release over the whole window). Linear per-second streams (Sablier linear, HoodLock / Titan vesting) contribute cliff / final events only. Token subject only. Prices implying a market cap above $100B are treated as phantom (usd null). PRO+.

Parameters

NameTypeDefaultDescription
withinstring7d"1h", "6h", "24h", "3d", "7d", "14d", "30d" or "90d"
tokenstring—Filter by token 0x address
familystring—Locker family
kindstring—"lock" or "vesting"
min_usdnumber—On the next-event amount
min_pct_of_supplynumber—On the next-event amount
sortstringsoonest"soonest", "largest_usd" or "largest_pct"
limitinteger50Number of entries (1-200)

Example Response

{
  "chain": "robinhood",
  "window": {
    "within": "7d",
    "from": "2026-09-15T16:00:00Z",
    "to": "2026-09-22T16:00:00Z"
  },
  "unlocks": [
    {
      "unlock_at": "2026-09-18T09:30:00Z",
      "in_seconds": 235800,
      "event": "tranche",
      "amount_raw": "402532625000000000000000",
      "amount": 402532.63,
      "amount_usd": 3135.7,
      "amount_pct_of_supply": 4.17,
      "window_amount": 402532.63,
      "token_address": "0x2531…3ba3",
      "token": {
        "symbol": "ROBIN",
        "decimals": 18
      },
      "lock": {
        "lock_id": "0xb47f…3165:7",
        "family": "sablier",
        "kind": "vesting",
        "name": "tranchedMonthly",
        "sender": "0xd7bd…e446",
        "recipient": "0x7844…ac18",
        "locked": 9258250.4,
        "cancelable_by_sender": false
      }
    }
  ],
  "pagination": {
    "limit": 50,
    "count": 1,
    "total_in_window": 1,
    "has_more": false
  }
}
GET/rhc/deployer-hunter/leaderboardFREE

RHC Deployer Leaderboard

370K+ Robinhood Chain deployers ranked by graduation rate, runner rate, tokens deployed or best peak MC — spam factories tiered out. Reputation tiers are scored on runner rate ($100K+ peak MC), not the $40K graduation bar. Free tier.

Parameters

NameTypeDefaultDescription
sortstringgraduation_rate"graduation_rate", "runner_rate", "tokens_deployed", "best_peak_mc_usd", "last_deploy_at"
tierstring—"elite", "good", "neutral" or "spammer"
min_tokensinteger3Minimum tokens deployed

Example Response

{
  "chain": "robinhood",
  "deployers": [
    {
      "deployer_address": "0x91ab…77c2",
      "tokens_deployed": 28,
      "graduated": 9,
      "graduation_rate": 0.321,
      "runners": 8,
      "runner_rate": 0.286,
      "tier": "good"
    }
  ],
  "total": 99237
}
GET/rhc/deployer-hunter/statsFREE

RHC Deployer Hunter Stats

Chain-wide deployer reputation summary for Robinhood Chain: total deployers and tokens, reputable (elite + good) count, population per tier, spam-token share — and the active tier thresholds (elite/good are earned on the $100K runner_rate, spammer on graduation_rate) so a consumer can see what "elite" currently means. Free tier.

Example Response

{
  "chain": "robinhood",
  "total_deployers": 163942,
  "total_tokens": 744708,
  "reputable_deployers": 180,
  "by_tier": {
    "elite": 56,
    "good": 124,
    "neutral": 160825,
    "spammer": 2937
  },
  "spam_token_share": 0.395,
  "tier_rules": {
    "elite": "tokens_deployed >= 5 AND runner_rate >= 0.50",
    "good": "tokens_deployed >= 5 AND runner_rate >= 0.25",
    "spammer": "tokens_deployed >= 20 AND graduation_rate < 0.05"
  }
}
GET/rhc/deployer-hunter/alertsFREE

RHC Deployer Alerts

Real-time launch + graduation alerts from ranked Robinhood Chain deployers, enriched with tier, priority, launchpad and current MC. Untradeable launches (no pool yet) are hidden unless include_untradeable=true. Cursor (before/since) or offset pagination. Free tier — limit is capped at 50 per page below ULTRA (ULTRA up to 500).

Parameters

NameTypeDefaultDescription
deployer_tierstring—"elite", "good", "neutral" or "spammer"
prioritystring—"high" or "medium"
alert_typestring—"new_deploy" or "graduated"
launchpadstring—Launchpad slug filter
min_mcnumber—Minimum current market cap (USD)
include_untradeablebooleanfalseAlso return launches with no pool yet
limitinteger501-50 (ULTRA: 1-500)
since / beforeISO datetime—Cursor window on detected_at
offsetinteger0Offset pagination (0-10000)

Example Response

{
  "chain": "robinhood",
  "alerts": [
    {
      "id": 918273,
      "alert_type": "new_deploy",
      "priority": "high",
      "title": "Elite deployer launched NEWCAT",
      "message": "0x91ab…77c2 (elite, 5/9 runners) deployed NEWCAT on clanker",
      "deployer_address": "0x91ab…77c2",
      "tier": "elite",
      "tier_at_alert": "elite",
      "tier_is_stale": false,
      "token_address": "0x1f2e…aa10",
      "token_symbol": "NEWCAT",
      "token_name": "New Cat",
      "launchpad": "clanker",
      "mc_at_alert": 18400,
      "current_mc_usd": 22100,
      "liquidity_usd": 6100,
      "risk": {
        "sellable": "yes",
        "upgradeable": false,
        "score": 18,
        "checked_at": "2026-08-18T09:40:25Z"
      },
      "created_at": "2026-08-18T09:40:20Z",
      "event_at": "2026-08-18T09:40:18Z"
    }
  ],
  "count": 1,
  "next_before": "2026-08-18T09:40:20Z"
}
GET/rhc/deployer-hunter/recent-bondsFREE

RHC Recent Graduations

Recently graduated tokens from ranked deployers — graduation on RHC = the $40K peak-market-cap milestone (most RHC launchpads are direct-to-DEX, not bonding-curve), stated in the response as graduation_mc. Free tier.

Parameters

NameTypeDefaultDescription
deployer_tierstring—"elite", "good", "neutral" or "spammer"
min_peaknumber—Minimum peak market cap (USD)
limitinteger50Number of tokens (1-200)

Example Response

{
  "chain": "robinhood",
  "graduation_mc": 40000,
  "tokens": [
    {
      "address": "0x8c3b…9f04",
      "symbol": "CASHCAT",
      "deployer_address": "0x91ab…77c2",
      "deployer_tier": "good",
      "peak_mc_usd": 206000000,
      "peak_mc_at": "2026-07-16T02:10:00Z"
    }
  ],
  "count": 1
}
GET/rhc/deployer-hunter/best-tokensFREE

RHC Best Tokens from Reputable Deployers

Top launches from elite/good RHC deployers in a period, ranked by peak market cap — a curated "what did the good deployers ship" list. Free tier.

Parameters

NameTypeDefaultDescription
periodstring7d"24h", "7d", "30d" or "all"
limitinteger10Number of tokens (1-50)

Example Response

{
  "chain": "robinhood",
  "period": "7d",
  "tokens": [
    {
      "address": "0x8c3b…9f04",
      "symbol": "CASHCAT",
      "deployer_address": "0x91ab…77c2",
      "deployer_tier": "good",
      "peak_mc_usd": 206000000,
      "market_cap_usd": 101000000
    }
  ],
  "reputable_deployers": 180
}
GET/rhc/deployer-hunter/{address}FREE

RHC Deployer Detail

One deployer's full reputation row plus their recent tokens with current + peak market caps. Free tier.

Example Response

{
  "chain": "robinhood",
  "deployer": {
    "deployer_address": "0x91ab…77c2",
    "tier": "good",
    "graduation_rate": 0.321,
    "runner_rate": 0.286
  },
  "recent_tokens": [
    {
      "address": "0x8c3b…9f04",
      "symbol": "CASHCAT",
      "is_graduated": true,
      "peak_mc_usd": 206000000
    }
  ]
}
GET/rhc/deployer-hunter/{address}/tokensFREE

RHC Deployer Tokens

Full paginated list of every token one RHC deployer launched — current + peak MC, graduation flag, first_seen_at — sortable by first_seen_at or peak_mc_usd. Non-deployers return is_deployer: false with an empty list rather than a 404. Free tier.

Parameters

NameTypeDefaultDescription
sortstringfirst_seen_at"first_seen_at" or "peak_mc_usd"
limitinteger50Number of tokens (1-100)
offsetinteger0Offset pagination (0-10000)

Example Response

{
  "chain": "robinhood",
  "is_deployer": true,
  "address": "0x91ab…77c2",
  "tokens": [
    {
      "address": "0x8c3b…9f04",
      "symbol": "CASHCAT",
      "is_graduated": true,
      "peak_mc_usd": 206000000,
      "market_cap_usd": 101000000,
      "first_seen_at": "2026-07-14T20:01:00Z"
    }
  ],
  "total": 14
}
GET/rhc/deployer-hunter/{address}/historyPRO

RHC Deployer Token History

One RHC deployer's launch history in chronological order — every token with its outcome (graduated / peak MC), deep-paginated up to 1,000 rows per page for backtests. PRO+.

Parameters

NameTypeDefaultDescription
limitinteger100Rows per page (1-1000)
offsetinteger0Offset (0-100000)

Example Response

{
  "chain": "robinhood",
  "is_deployer": true,
  "address": "0x91ab…77c2",
  "tokens": [
    {
      "address": "0x8c3b…9f04",
      "symbol": "CASHCAT",
      "first_seen_at": "2026-07-14T20:01:00Z",
      "is_graduated": true,
      "peak_mc_usd": 206000000
    }
  ],
  "total": 14
}
GET/rhc/deployer-hunter/{address}/trajectoryFREE

RHC Deployer Trajectory

Is this RHC deployer improving or decaying? Rolling 10-launch graduation-rate windows, streaks, recent-vs-lifetime rate and trend, with success_metric stated as "graduated ($40K+ peak market cap)" — Solana-parity shape. Free tier.

Example Response

{
  "chain": "robinhood",
  "is_deployer": true,
  "address": "0x91ab…77c2",
  "success_metric": "graduated ($40K+ peak market cap)",
  "trajectory": {
    "total_launches": 14,
    "lifetime_rate": 0.321,
    "recent_rate": 0.4,
    "trend": "improving",
    "current_streak": {
      "kind": "graduated",
      "length": 2
    },
    "rolling": [
      {
        "window_end": 10,
        "bond_rate": 0.3
      },
      {
        "window_end": 14,
        "bond_rate": 0.4
      }
    ]
  }
}
GET/rhc/alpha-walletsPRO

RHC Alpha Wallets

Smart-money ranking on Robinhood Chain — the highest-performing non-bot wallets, filterable by net ETH, win-rate, memecoin share, size and identity (known-KOL vs net-new smart money). Also reachable at /rhc/alpha/leaderboard (identical response — an alias for parity with Solana's /alpha/leaderboard). PRO+.

Parameters

NameTypeDefaultDescription
classificationstringall"human", "smart_money" or "all"
identitystringall"known_kol", "unknown" or "all"
sortstringnet_ethSort key (net_eth, win_rate, …)
limitinteger25Rows returned (offset paging)

Example Response

{
  "chain": "robinhood",
  "wallets": [
    {
      "address": "0x4a9f…c21e",
      "net_eth": 18.4,
      "win_rate": 0.63,
      "trades": 84,
      "likely_bot": false
    }
  ],
  "total": 320,
  "has_more": true
}
GET/rhc/wallet/{address}PRO

RHC Wallet Profile

Any Robinhood Chain wallet's 90-day profile: FIFO cost-basis PnL in ETH, per-token breakdown, recent trades, and reputation flags (tracked KOL, known deployer + tier, alpha-ranked, dump-cluster, early-buyer count). Keyed on trader_eoa — the effective trading account, never the router or an ERC-4337 bundler. PRO+.

Example Response

{
  "chain": "robinhood",
  "address": "0xada5…f7cb",
  "stats": {
    "total_trades": 1420,
    "analyzed_trades": 1180,
    "unattributed_trades": 240,
    "realized_pnl_eth": 1.46,
    "unrealized_pnl_eth": -0.32,
    "total_pnl_eth": 1.14,
    "unique_tokens": 96
  },
  "flags": {
    "is_kol": false,
    "is_deployer": true,
    "deployer_tier": "neutral",
    "likely_bot": false,
    "is_dumper": false
  }
}
GET/rhc/wallet/{address}/pnlPRO

RHC Wallet PnL

Full FIFO cost-basis PnL: realized/unrealized split, daily realized curve, every closed position with ROI and token-weighted hold time, open positions marked to live price. Same FIFO engine as the Solana /wallet/{address}/pnl, ETH-denominated. Shares one loader with the profile endpoint, so the two cannot disagree. PRO+.

Example Response

{
  "chain": "robinhood",
  "summary": {
    "realized_eth": 1.46,
    "unrealized_eth": -0.32,
    "win_rate": 0.36,
    "profit_factor": 1.8,
    "max_drawdown_eth": 1.44,
    "open_positions_count": 12,
    "closed_positions_count": 84
  },
  "pnl_curve": [
    {
      "date": "2026-07-24",
      "day_pnl": 0.42,
      "cumulative_pnl": 1.46,
      "trades": 9
    }
  ]
}
GET/rhc/wallet/{address}/positionsPRO

RHC Wallet Positions

Only what the wallet still holds, marked to the current price. "Open" means FIFO-unmatched buys — a trading position, not an on-chain balance, so tokens acquired by transfer or bridge don't appear. PRO+.

Example Response

{
  "chain": "robinhood",
  "summary": {
    "open_positions": 12,
    "total_cost_basis_eth": 3.9,
    "total_current_value_eth": 3.1,
    "total_unrealized_eth": -0.8,
    "unpriced_positions": 0
  },
  "positions": [
    {
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "cost_basis_eth": 0.42,
      "current_value_eth": 1.31,
      "unrealized_pct": 211.9
    }
  ]
}
GET/rhc/wallet/{address}/tradesPRO

RHC Wallet Trades

One wallet's swaps, newest first, cursor-paginated on block_time. Distinct from /rhc/trades?token= — that filters by token, this by wallet. token_amount is reconstructed from raw uint256 leg amounts and is null when it can't be, never a guess. PRO+.

Parameters

NameTypeDefaultDescription
limitinteger50Rows returned (max 200)
beforestring—Cursor: trades older than this block_time
actionstring—"buy" or "sell"
tokenstring—Restrict to one token address

Example Response

{
  "chain": "robinhood",
  "trades": [
    {
      "token_symbol": "GME",
      "action": "buy",
      "eth_amount": 0.0026,
      "token_amount": 46070.24,
      "dex": "uniswap-v3",
      "block_time": "2026-07-25T18:23:32Z"
    }
  ],
  "count": 1,
  "next_before": "2026-07-25T18:23:32Z"
}
GET/rhc/wallet-tracker/summaryPRO

RHC Wallet Tracker

Watchlist CRUD (/rhc/wallet-tracker/watchlist) plus a per-wallet activity rollup and a merged trade feed across everything you track. Quotas are PER CHAIN — 50/100/500 RHC wallets — so this never eats into your Solana watchlist. Read straight from the chain rather than a capture log, so a wallet added today reports its full history. PRO+.

Parameters

NameTypeDefaultDescription
periodstring7d"24h", "7d" or "30d"
walletstring—Restrict to one watched wallet

Example Response

{
  "chain": "robinhood",
  "period": "7d",
  "wallets": [
    {
      "wallet_address": "0xada5…f7cb",
      "label": "whale-1",
      "stats": {
        "trades": 447,
        "buys": 222,
        "sells": 147,
        "net_eth": -14.1,
        "tokens_traded": 56
      }
    }
  ]
}
GET/rhc/wallet-tracker/watchlistPRO

List RHC Watchlist

Your tracked Robinhood Chain wallets with labels and remaining per-chain capacity (PRO 50 / ULTRA 100 / BUSINESS 500 — separate from the Solana quota). PRO+.

Example Response

{
  "chain": "robinhood",
  "wallets": [
    {
      "wallet_address": "0xada5…f7cb",
      "label": "whale-1",
      "added_at": "2026-07-20T10:00:00Z"
    }
  ],
  "count": 1,
  "limit": 50,
  "remaining": 49
}
POST/rhc/wallet-tracker/watchlistPRO

Add RHC Wallet

Track a Robinhood Chain wallet (0x address, optional label). 409 if already tracked or the per-chain limit is reached. PRO+.

Parameters

NameTypeDefaultDescription
wallet_addressstringrequiredEVM address (0x + 40 hex)
labelstring—Optional label (≤64 chars)

Example Response

{
  "chain": "robinhood",
  "wallet": {
    "wallet_address": "0xada5…f7cb",
    "label": "whale-1",
    "added_at": "2026-07-20T10:00:00Z"
  }
}
PATCH/rhc/wallet-tracker/watchlist/{address}PRO

Update RHC Wallet Label

Update the label of a tracked RHC wallet; null clears it. PRO+.

Parameters

NameTypeDefaultDescription
addressstring (path)requiredEVM address
labelstring | nullrequiredNew label or null

Example Response

{
  "chain": "robinhood",
  "wallet": {
    "wallet_address": "0xada5…f7cb",
    "label": "whale-1 (rotated)"
  }
}
DELETE/rhc/wallet-tracker/watchlist/{address}PRO

Remove RHC Wallet

Stop tracking an RHC wallet. 404 if it isn't on your list. PRO+.

Parameters

NameTypeDefaultDescription
addressstring (path)requiredEVM address

Example Response

{
  "chain": "robinhood",
  "removed": "0xada5…f7cb"
}
GET/rhc/wallet-tracker/tradesPRO

RHC Watchlist Trade Feed

Merged, newest-first trade tape across every RHC wallet you track (labels attached), keyset-paginated on (block_time, id) — pass next_before back as before; a bare ISO timestamp is accepted for compatibility. PRO+.

Parameters

NameTypeDefaultDescription
walletstring—Restrict to one tracked wallet
tokenstring—Filter by token 0x address
actionstring—"buy" or "sell"
limitinteger50Number of trades (1-200)
beforestring—Keyset cursor (next_before)

Example Response

{
  "chain": "robinhood",
  "trades": [
    {
      "wallet_address": "0xada5…f7cb",
      "label": "whale-1",
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "action": "sell",
      "eth_amount": 2.1,
      "tx_hash": "0x7d1a…8e3f",
      "block_time": "2026-08-18T09:30:00Z"
    }
  ],
  "count": 1,
  "has_more": true,
  "next_before": "eyJi…"
}
GET/rhc/copytrade/subscriptionsPRO

List RHC Copy-Trade Rules

Every copy-trade rule you have on Robinhood Chain, active or not, newest first. The webhook secret is never returned here — only once, at creation. Each rule also reports source_wallets_tracked / source_wallets_untracked: only wallets in the tracked KOL set (kol_evm_wallets — the set behind /rhc/kol/wallets) can ever fire, and a rule with untracked wallets carries warnings[{ code: "untracked_source_wallets" }]. Quotas are PER CHAIN: PRO 3 rules × 5 source wallets, ULTRA 20 × 50, BUSINESS 100 × 250 — none of it consumes your Solana copy-trade budget. PRO+.

Example Response

{
  "chain": "robinhood",
  "subscriptions": [
    {
      "id": 7,
      "name": "danny buys",
      "source_wallets": [
        "0x4a9f…c21e",
        "0x59a1…0b3d"
      ],
      "min_trade_eth": 0.05,
      "only_action": "buy",
      "sizing_mode": "fixed",
      "sizing_amount": 0.01,
      "delivery_mode": "both",
      "webhook_url": "https://your-app.com/rhc/hook",
      "is_active": true,
      "created_at": "2026-07-28T09:00:00Z",
      "updated_at": "2026-07-28T09:00:00Z",
      "source_wallets_tracked": [
        "0x4a9f…c21e"
      ],
      "source_wallets_untracked": [
        "0x59a1…0b3d"
      ],
      "warnings": [
        {
          "code": "untracked_source_wallets",
          "message": "1 of 2 source wallet(s) are not tracked Robinhood Chain KOL wallets … this rule will never fire for: 0x59a1…0b3d"
        }
      ]
    }
  ]
}
POST/rhc/copytrade/subscriptionsPRO

Create RHC Copy-Trade Rule

Register a rule against one or more TRACKED Robinhood Chain KOL wallets (the set behind /rhc/kol/wallets). Any 0x address is accepted, but the engine only evaluates trades of tracked wallets — the response's source_wallets_untracked + warnings tell you which wallets can never fire (use /rhc/wallet-tracker for arbitrary addresses). Sizing is ETH-denominated (min_trade_eth / sizing_amount), not SOL. There is NO market-cap band on RHC copy-trade — the producer's event carries no MC, so min_mc_usd / max_mc_usd simply do not exist here; filter on MC after the fact via /rhc/tokens/{address}. Source addresses are lowercased on write, so a checksummed address still matches. Returns webhook_secret once. PRO+ (rules 3/20/100, wallets 5/50/250 per rule — per-chain quota).

Parameters

NameTypeDefaultDescription
source_walletsstring[]required1–250 EVM addresses (0x + 40 hex) to copy; tier-capped at 5 / 50 / 250
sizing_amountnumberrequiredSuggested copy size in ETH (or the multiplier, depending on sizing_mode). Must be > 0
namestring—Human-readable label (1–64 chars)
min_trade_ethnumber0Only fire on source trades ≥ this ETH size
only_actionstringbuy"buy", "sell" or "both"
sizing_modestringfixed"fixed" (ETH amount), "proportional" (multiplier × source size) or "percent_source"
delivery_modestringwebhook"webhook", "websocket" or "both" — websocket delivers on the rhc:copytrade:signals channel
webhook_urlstring—HTTPS URL — required unless delivery_mode is "websocket"

Example Response

{
  "chain": "robinhood",
  "subscription": {
    "id": 7,
    "name": "danny buys",
    "source_wallets": [
      "0x4a9f…c21e"
    ],
    "min_trade_eth": 0.05,
    "only_action": "buy",
    "sizing_mode": "fixed",
    "sizing_amount": 0.01,
    "delivery_mode": "both",
    "webhook_url": "https://your-app.com/rhc/hook",
    "is_active": true,
    "created_at": "2026-07-28T09:00:00Z",
    "updated_at": "2026-07-28T09:00:00Z",
    "source_wallets_tracked": [
      "0x4a9f…c21e"
    ],
    "source_wallets_untracked": []
  },
  "webhook_secret": "<32-byte hex — shown once>",
  "note": "Save the webhook_secret — it will not be shown again. Payloads are signed HMAC-SHA256 over `<timestamp>.<body>` in the X-MadeOnSol-Signature header."
}
GET/rhc/copytrade/subscriptions/{id}PRO

Get RHC Copy-Trade Rule

Fetch one rule by integer id. Scoped to your account — a rule you don't own returns 404, never someone else's row. PRO+.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredRule ID

Example Response

{
  "chain": "robinhood",
  "subscription": {
    "id": 7,
    "name": "danny buys",
    "source_wallets": [
      "0x4a9f…c21e"
    ],
    "min_trade_eth": 0.05,
    "only_action": "buy",
    "sizing_mode": "fixed",
    "sizing_amount": 0.01,
    "delivery_mode": "both",
    "webhook_url": "https://your-app.com/rhc/hook",
    "is_active": true,
    "source_wallets_tracked": [
      "0x4a9f…c21e"
    ],
    "source_wallets_untracked": []
  }
}
PATCH/rhc/copytrade/subscriptions/{id}PRO

Update RHC Copy-Trade Rule

Partial update — send only the fields you want changed; an empty body is a 400. The per-chain source_wallets cap is re-checked on update. No new webhook_secret is issued: to rotate one, delete and recreate the rule. PRO+.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredRule ID
source_walletsstring[]—Replace the tracked EVM wallets (tier cap re-applied)
min_trade_ethnumber—New ETH threshold
only_actionstring—buy / sell / both
sizing_modestring—fixed / proportional / percent_source
sizing_amountnumber—New ETH size or multiplier
delivery_modestring—webhook / websocket / both
webhook_urlstring | null—New HTTPS URL, or null to clear
namestring | null—New label, or null to clear
is_activeboolean—Pause (false) or resume (true)

Example Response

{
  "chain": "robinhood",
  "subscription": {
    "id": 7,
    "min_trade_eth": 0.1,
    "is_active": true,
    "updated_at": "2026-07-28T11:00:00Z",
    "source_wallets_tracked": [
      "0x4a9f…c21e"
    ],
    "source_wallets_untracked": []
  }
}
DELETE/rhc/copytrade/subscriptions/{id}PRO

Delete RHC Copy-Trade Rule

Permanently delete a rule. Returns 404 if it isn't yours. PRO+.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredRule ID

Example Response

{
  "chain": "robinhood",
  "deleted": true
}
GET/rhc/copytrade/signalsPRO

RHC Signal History

The catch-up path for signals your RHC rules fired — use it to backfill a missed webhook or a dropped WebSocket. Retained 7 days. Always scoped to your own rules. PRO+.

Parameters

NameTypeDefaultDescription
subscription_idinteger—Filter to one rule (404 if not yours)
sinceISO 8601—Signals fired at or after this timestamp
limitinteger50Max signals (1–500)

Example Response

{
  "chain": "robinhood",
  "signals": [
    {
      "id": 8812,
      "subscription_id": 7,
      "fired_at": "2026-07-28T09:14:02.318Z",
      "source_wallet": "0x4a9f…c21e",
      "action": "buy",
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "token_name": "Cash Cat",
      "source_eth_amount": 0.215,
      "suggested_eth_amount": 0.01,
      "price_usd": 0.0021,
      "dex": "uniswap-v4",
      "tx_hash": "0x7d1a…8e3f",
      "delivered": true,
      "delivered_at": "2026-07-28T09:14:02.904Z"
    }
  ],
  "count": 1
}
GET/rhc/price-alertsPRO

List RHC Price Alerts

Your Robinhood Chain MC dip/recovery alerts, active and inactive. Per-chain quota: PRO 5, ULTRA 25, BUSINESS 125 active alerts — independent of your Solana price-alert budget. PRO+.

Example Response

{
  "chain": "robinhood",
  "alerts": [
    {
      "id": 31,
      "name": "CASHCAT dip watch",
      "token_address": "0x8c3b…9f04",
      "token_symbol": "CASHCAT",
      "baseline_mc_usd": 3300000,
      "drop_pct": 20,
      "recovery_pct": 15,
      "status": "armed",
      "dip_low_mc_usd": null,
      "dip_fired_at": null,
      "delivery_mode": "webhook",
      "webhook_url": "https://your-app.com/rhc/dip",
      "is_active": true,
      "expires_at": null,
      "created_at": "2026-07-28T09:00:00Z",
      "updated_at": "2026-07-28T09:00:00Z"
    }
  ]
}
POST/rhc/price-alertsPRO

Create RHC Price Alert

Create an MC dip alert on an RHC token. The token's current market cap is captured at create time as baseline_mc_usd — an untracked token, or one with no MC to baseline against, is a 400 rather than a silently dead alert. IMPORTANT: RHC alerts are event-driven off the chain trade feed (rhc:dex_trade), with price-table polls (5 s / 60 s) and a trade-tape replay as safety nets. Latency is a few seconds (the chain trade flush is about 2 s), not the sub-second in-memory loop the Solana alerts use. Do not assume Solana parity. Returns webhook_secret once. PRO+ (5 / 25 / 125 active alerts, per-chain quota).

Parameters

NameTypeDefaultDescription
token_addressstringrequiredRHC token 0x address (lowercased on write)
drop_pctnumberrequiredMC drop threshold from baseline, 0.01–99.99
recovery_pctnumber—Optional follow-up threshold when MC recovers from the dip low, 0.01–1000
namestring—Optional label (1–64 chars)
delivery_modestringwebhook"webhook", "websocket" or "both" — websocket delivers on rhc:price_alert:events
webhook_urlstring—HTTPS URL — required unless delivery_mode is "websocket"

Example Response

{
  "chain": "robinhood",
  "alert": {
    "id": 31,
    "name": "CASHCAT dip watch",
    "token_address": "0x8c3b…9f04",
    "token_symbol": "CASHCAT",
    "baseline_mc_usd": 3300000,
    "drop_pct": 20,
    "recovery_pct": 15,
    "status": "armed",
    "delivery_mode": "webhook",
    "webhook_url": "https://your-app.com/rhc/dip",
    "is_active": true,
    "created_at": "2026-07-28T09:00:00Z"
  },
  "webhook_secret": "<32-byte hex — shown once>",
  "evaluation": {
    "mode": "event_driven",
    "trigger": "rhc:dex_trade",
    "interval_seconds": 5,
    "fallback_poll_seconds": {
      "fast": 5,
      "slow": 60
    },
    "note": "RHC alerts are evaluated as trades land on the rhc:dex_trade feed, with table polls and a tape replay as safety nets. Latency is a few seconds, not sub-second like the Solana alerts."
  },
  "note": "Save the webhook_secret — it will not be shown again."
}
GET/rhc/price-alerts/{id}PRO

Get RHC Price Alert

Fetch one alert by integer id, including its live dip state (status, dip_low_mc_usd, dip_fired_at). 404 if it isn't yours. PRO+.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredAlert ID

Example Response

{
  "chain": "robinhood",
  "alert": {
    "id": 31,
    "token_address": "0x8c3b…9f04",
    "token_symbol": "CASHCAT",
    "baseline_mc_usd": 3300000,
    "drop_pct": 20,
    "recovery_pct": 15,
    "status": "dipped",
    "dip_low_mc_usd": 2410000,
    "dip_fired_at": "2026-07-28T12:42:11Z",
    "is_active": true
  }
}
PATCH/rhc/price-alerts/{id}PRO

Update RHC Price Alert

Only four fields are mutable: name, delivery_mode, webhook_url, is_active. token_address, drop_pct and recovery_pct are IMMUTABLE by design — moving a threshold on an already-dipped alert would make its recorded events uninterpretable, so delete and recreate instead. Sending an immutable field is a 400. PRO+.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredAlert ID
namestring | null—New label, or null to clear
delivery_modestring—webhook / websocket / both
webhook_urlstring | null—New HTTPS URL, or null to clear
is_activeboolean—Pause (false) or resume (true)

Example Response

{
  "chain": "robinhood",
  "alert": {
    "id": 31,
    "name": "CASHCAT dip watch v2",
    "is_active": false,
    "updated_at": "2026-07-28T15:00:00Z"
  }
}
DELETE/rhc/price-alerts/{id}PRO

Delete RHC Price Alert

Permanently delete an alert and its event history. 404 if it isn't yours. PRO+.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredAlert ID

Example Response

{
  "chain": "robinhood",
  "deleted": true
}
GET/rhc/price-alerts/eventsPRO

RHC Price Alert Events

Dip and recovery events fired by your RHC alerts, newest first — the audit / catch-up path for a missed delivery. Retained 30 days. PRO+.

Parameters

NameTypeDefaultDescription
alert_idinteger—Filter to one alert (404 if not yours)
event_typestring—"dip" or "recovery"
sinceISO 8601—Events fired at or after this timestamp
limitinteger50Max events (1–500)

Example Response

{
  "chain": "robinhood",
  "events": [
    {
      "id": 902,
      "alert_id": 31,
      "event_type": "dip",
      "fired_at": "2026-07-28T12:42:11Z",
      "token_address": "0x8c3b…9f04",
      "baseline_mc_usd": 3300000,
      "current_mc_usd": 2410000,
      "drop_pct_actual": 26.97,
      "dip_low_mc_usd": 2410000,
      "recovery_pct_actual": null,
      "delivered": true,
      "delivered_at": "2026-07-28T12:42:11.812Z"
    }
  ],
  "count": 1
}
GET/rhc/kol/coordination/alertsPRO

List RHC Coordination Rules

Your Robinhood Chain KOL-convergence rules — fire when N+ tracked KOLs buy the same token inside a rolling window. Per-chain quota: PRO 5, ULTRA 20, BUSINESS 100 rules, separate from the Solana coordination budget. PRO+.

Example Response

{
  "chain": "robinhood",
  "rules": [
    {
      "id": "b41c…",
      "name": "3 KOLs in 15m",
      "min_kols": 3,
      "window_minutes": 15,
      "min_score": 0,
      "cooldown_min": 30,
      "score_jump_break": 20,
      "min_mc_usd": null,
      "max_mc_usd": null,
      "delivery_mode": "websocket",
      "webhook_url": null,
      "is_active": true,
      "created_at": "2026-07-28T09:00:00Z",
      "updated_at": "2026-07-28T09:00:00Z"
    }
  ]
}
POST/rhc/kol/coordination/alertsPRO

Create RHC Coordination Rule

Fire when min_kols distinct tracked KOLs converge on one RHC token inside window_minutes. Unlike copy-trade, coordination rules DO take an MC band (min_mc_usd / max_mc_usd). Scoring is v1: the quality leg is real (7d winrate from the RHC KOL score matview) while earliness is defaulted on RHC — treat min_score accordingly. Returns webhook_secret once. PRO+ (5 / 20 / 100 rules, per-chain quota).

Parameters

NameTypeDefaultDescription
min_kolsinteger3Distinct KOL buyers needed to fire (2–50)
window_minutesinteger15Rolling convergence window (1–60)
min_scoreinteger0Minimum coordination score, 0–100
cooldown_mininteger30Per-token cooldown between firings (1–1440)
score_jump_breakinteger20Re-fire inside cooldown if the score jumps by this much (0–100)
min_mc_usdnumber | null—Lower market-cap bound (0–1e12)
max_mc_usdnumber | null—Upper market-cap bound (0–1e12); must be ≥ min_mc_usd
namestring—Optional label (1–64 chars)
delivery_modestringwebsocket"websocket", "webhook" or "both" — websocket delivers on rhc:kol:coordination
webhook_urlstring—HTTPS URL — required unless delivery_mode is "websocket"

Example Response

{
  "chain": "robinhood",
  "rule": {
    "id": "b41c…",
    "name": "3 KOLs in 15m",
    "min_kols": 3,
    "window_minutes": 15,
    "min_score": 0,
    "cooldown_min": 30,
    "score_jump_break": 20,
    "min_mc_usd": null,
    "max_mc_usd": null,
    "delivery_mode": "websocket",
    "webhook_url": null,
    "is_active": true,
    "created_at": "2026-07-28T09:00:00Z"
  },
  "webhook_secret": null,
  "scoring": {
    "score_version": "v1",
    "quality": "7d winrate from the RHC KOL score matview",
    "earliness": "defaulted on RHC — no scout-score equivalent yet"
  }
}
GET/rhc/kol/coordination/alerts/{id}PRO

Get RHC Coordination Rule

Fetch one rule by UUID. Scoped to your account — 404 for anything you don't own. PRO+.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredRule ID

Example Response

{
  "chain": "robinhood",
  "rule": {
    "id": "b41c…",
    "name": "3 KOLs in 15m",
    "min_kols": 3,
    "window_minutes": 15,
    "min_score": 0,
    "cooldown_min": 30,
    "delivery_mode": "websocket",
    "is_active": true
  }
}
PATCH/rhc/kol/coordination/alerts/{id}PRO

Update RHC Coordination Rule

Partial update of any rule field; an empty body is a 400. The min_mc_usd ≤ max_mc_usd check only runs when you send BOTH bounds in the same request — the DB constraint is the backstop for the one-sided case. No webhook_secret is re-issued. PRO+.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredRule ID
min_kolsinteger—2–50
window_minutesinteger—1–60
min_scoreinteger—0–100
cooldown_mininteger—1–1440
score_jump_breakinteger—0–100
min_mc_usdnumber | null—Lower MC bound, or null to clear
max_mc_usdnumber | null—Upper MC bound, or null to clear
namestring | null—New label, or null to clear
delivery_modestring—websocket / webhook / both
webhook_urlstring | null—New HTTPS URL, or null to clear
is_activeboolean—Pause (false) or resume (true)

Example Response

{
  "chain": "robinhood",
  "rule": {
    "id": "b41c…",
    "min_kols": 4,
    "is_active": true,
    "updated_at": "2026-07-28T15:00:00Z"
  }
}
DELETE/rhc/kol/coordination/alerts/{id}PRO

Delete RHC Coordination Rule

Permanently delete a coordination rule. 404 if it isn't yours. PRO+.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredRule ID

Example Response

{
  "chain": "robinhood",
  "deleted": true
}
GET/rhc/kol/first-touches/subscriptionsULTRA

List RHC First-Touch Subscriptions

Your subscriptions to the moment a tracked KOL touches an RHC token for the FIRST time — the earliest signal we can emit for a KOL/token pair. ULTRA+ only (PRO is 0): ULTRA 10, BUSINESS 50 subscriptions, a per-chain quota separate from the Solana first-touch budget.

Example Response

{
  "chain": "robinhood",
  "subscriptions": [
    {
      "id": "9d02…",
      "name": "winners only",
      "filters": {
        "min_kol_winrate": 0.55,
        "strategy": "scalper",
        "min_first_buy_eth": 0.1
      },
      "delivery_mode": "websocket",
      "webhook_url": null,
      "is_active": true,
      "created_at": "2026-07-28T09:00:00Z",
      "updated_at": "2026-07-28T09:00:00Z"
    }
  ]
}
POST/rhc/kol/first-touches/subscriptionsULTRA

Create RHC First-Touch Subscription

Subscribe to first-touch events with an optional filters object. RHC deliberately omits the Solana min_scout_tier / min_n_touches filters (there is no scout-score matview on RHC) — min_kol_winrate and strategy are the quality gates instead, and both DROP unscored KOLs rather than treating them as zero. Unknown filter keys are rejected, not ignored. Returns webhook_secret once. ULTRA+ (10 / 50, per-chain quota).

Parameters

NameTypeDefaultDescription
filters.kolstring—Restrict to one KOL EVM address (lowercased on write)
filters.min_first_buy_ethnumber—Minimum size of the first buy, 0–100000 ETH
filters.min_kol_winratenumber—Minimum 7d winrate as a FRACTION, 0–1 (not 0–100). Unscored KOLs are dropped.
filters.strategystring—"scalper", "day_trader", "swing", "inactive" or "unscored" — the RHC hold-time buckets, which differ from the Solana strategy values
filters.min_mc_usdnumber—Lower market-cap bound (0–1e12)
filters.max_mc_usdnumber—Upper market-cap bound (0–1e12); must be ≥ min_mc_usd
namestring—Optional label (1–64 chars)
delivery_modestringwebsocket"websocket", "webhook" or "both" — websocket delivers on rhc:kol:first_touches
webhook_urlstring—HTTPS URL — required unless delivery_mode is "websocket"

Example Response

{
  "chain": "robinhood",
  "subscription": {
    "id": "9d02…",
    "name": "winners only",
    "filters": {
      "min_kol_winrate": 0.55,
      "strategy": "scalper",
      "min_first_buy_eth": 0.1
    },
    "delivery_mode": "websocket",
    "webhook_url": null,
    "is_active": true,
    "created_at": "2026-07-28T09:00:00Z"
  },
  "webhook_secret": null,
  "note": "delivery_mode is websocket — subscribe to the rhc:kol:first_touches channel."
}
GET/rhc/kol/first-touches/subscriptions/{id}ULTRA

Get RHC First-Touch Subscription

Fetch one subscription by UUID. 404 for anything you don't own. ULTRA+.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredSubscription ID

Example Response

{
  "chain": "robinhood",
  "subscription": {
    "id": "9d02…",
    "name": "winners only",
    "filters": {
      "min_kol_winrate": 0.55,
      "strategy": "scalper"
    },
    "delivery_mode": "websocket",
    "is_active": true
  }
}
PATCH/rhc/kol/first-touches/subscriptions/{id}ULTRA

Update RHC First-Touch Subscription

Partial update; an empty body is a 400. NOTE: `filters` is a whole-object REPLACE, not a merge — send the complete filter set you want, because merging would make removing a filter inexpressible. Send `filters: {}` to clear them all. ULTRA+.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredSubscription ID
filtersobject—Replaces the whole filter object (same six keys and bounds as POST)
namestring | null—New label, or null to clear
delivery_modestring—websocket / webhook / both
webhook_urlstring | null—New HTTPS URL, or null to clear
is_activeboolean—Pause (false) or resume (true)

Example Response

{
  "chain": "robinhood",
  "subscription": {
    "id": "9d02…",
    "filters": {
      "min_kol_winrate": 0.6
    },
    "is_active": true,
    "updated_at": "2026-07-28T15:00:00Z"
  }
}
DELETE/rhc/kol/first-touches/subscriptions/{id}ULTRA

Delete RHC First-Touch Subscription

Permanently delete a first-touch subscription. 404 if it isn't yours. ULTRA+.

Parameters

NameTypeDefaultDescription
iduuid (path)requiredSubscription ID

Example Response

{
  "chain": "robinhood",
  "deleted": true
}

Real-time

Push, don't poll.

Events pushed as they happen via webhooks and direct WebSocket, no polling. Measured detection latency is on /benchmarks. The all-DEX firehose is its own stream on Ultra and Business.

Webhooks

Signed HTTPS deliveries.

PRO 3 webhooks · ULTRA 10 · BUSINESS 30. Per-rule secret, automatic retry, auto-disable on repeated failure. Nine registerable events, including rhc:kol_trade for Robinhood Chain (PRO+) and token:surge / token:revival momentum fires — note min_sol and kol_name are Solana-only filters.

Relaying deliveries into a chat? See how a bot backend turns a signed delivery into a Telegram message.
POST/webhooksPRO

Create Webhook

Register a webhook URL to receive real-time push notifications for KOL trades and deployer alerts. HTTPS URLs only. Server generates an HMAC-SHA256 secret for payload verification. Pro+: Pro 3 webhooks max, Ultra 10, Business 30. Custom `filters.conditions` need Ultra+.

Parameters

NameTypeDefaultDescription
urlstringrequiredHTTPS webhook URL to receive events
eventsstring[]requiredThe complete registerable set (9): "kol:trade", "kol:coordination", "deployer:alert", "deployer:bond", "wallet_tracker:event", "sniper:deploy" (Pro+; Pro curated to elite/good deployers), "rhc:kol_trade" (Pro+, Robinhood Chain), "token:surge", "token:revival" (Pro+, token momentum fires). Anything else is rejected with 400. Price-alert, copy-trade, coordination and first-touch delivery is configured on the rule itself via its own `webhook_url` + per-rule HMAC secret, not through the /webhooks registry.
filtersobject{}Optional filters: min_sol, action (buy/sell), kol_name, deployer_tier[], min_kols, and for token:surge / token:revival kinds[], tiers[], launchpads[], exclude_flags[], min_mc_usd/max_mc_usd. min_sol and kol_name are Solana-only — see the payload-format section before setting them on "rhc:kol_trade". ULTRA+: `conditions` — up to 10 { field, op, value } triples ANDed against the event payload (ops eq/neq/gt/gte/lt/lte/in/contains; `field` must be a documented payload field of a subscribed event type, else 400; on PRO a 403 tier_required).

Example Response

{
  "webhook": {
    "id": 1,
    "url": "https://your-app.com/webhooks/madeonsol",
    "secret": "a1b2c3d4...your-hmac-secret",
    "events": [
      "kol:trade",
      "deployer:alert"
    ],
    "filters": {
      "min_sol": 1
    },
    "is_active": true,
    "created_at": "2026-04-03T12:00:00Z"
  },
  "note": "Save the secret — it will not be shown again."
}
GET/webhooksPRO

List Webhooks

List all your registered webhooks with delivery status and failure counts.

Example Response

{
  "webhooks": [
    {
      "id": 1,
      "url": "https://your-app.com/webhooks/madeonsol",
      "events": [
        "kol:trade",
        "deployer:alert"
      ],
      "filters": {
        "min_sol": 1
      },
      "is_active": true,
      "last_delivered_at": "2026-04-03T14:30:00Z",
      "consecutive_failures": 0
    }
  ]
}
GET/webhooks/{id}PRO

Webhook Detail + Delivery Log

Get webhook details and the last 20 delivery attempts with status codes, response times, and errors.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredWebhook ID

Example Response

{
  "webhook": {
    "id": 1,
    "url": "https://your-app.com/webhooks/madeonsol",
    "is_active": true,
    "consecutive_failures": 0
  },
  "recent_deliveries": [
    {
      "event_type": "kol:trade",
      "status_code": 200,
      "response_time_ms": 142,
      "delivered_at": "2026-04-03T14:30:00Z",
      "error": null
    }
  ]
}
PATCH/webhooks/{id}PRO

Update Webhook

Update webhook URL, events, filters, or re-enable a disabled webhook. Re-enabling resets the failure counter.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredWebhook ID
urlstring—New HTTPS URL
eventsstring[]—Updated event types
filtersobject—Updated filters
is_activeboolean—Re-enable (true) or disable (false)

Example Response

{
  "webhook": {
    "id": 1,
    "url": "https://your-app.com/webhooks/madeonsol",
    "events": [
      "kol:trade"
    ],
    "is_active": true,
    "updated_at": "2026-04-03T15:00:00Z"
  }
}
DELETE/webhooks/{id}PRO

Delete Webhook

Permanently delete a webhook and all its delivery history.

Parameters

NameTypeDefaultDescription
idinteger (path)requiredWebhook ID

Example Response

{
  "deleted": true
}
POST/webhooks/testPRO

Test Webhook

Send a sample event payload to your webhook URL to verify it's reachable and correctly processing events. Returns the HTTP status code and response time.

Parameters

NameTypeDefaultDescription
webhook_idintegerrequiredID of the webhook to test

Example Response

{
  "success": true,
  "status_code": 200,
  "response_time_ms": 89
}

Payload format

Signed deliveries with replay protection.

Every delivery carries a timestamp + HMAC-SHA256 signature over the raw body.

Every delivery carries X-MadeOnSol-Timestamp (unix ms) and X-MadeOnSol-Signature (HMAC-SHA256 of <timestamp>.<body> keyed with your webhook secret exactly as the API returned it). The signature is bare lowercase hex with no prefix. Compute it over the raw request bytes, never re-serialized JSON. The server does not enforce a replay window; the verifiers below reject deliveries older than 5 minutes, which is safe because every retry is signed again with a fresh timestamp.

Headers

X-MadeOnSol-Timestamp: <unix milliseconds>
X-MadeOnSol-Signature: <hmac-sha256-hex of "<ts>.<body>">
X-MadeOnSol-Event: kol:trade
Content-Type: application/json

Verifier (Node.js)

import crypto from "node:crypto";
import express from "express";

// rawBody:   the exact request bytes (never re-serialized JSON)
// secret:    the webhook secret exactly as the API returned it (do not hex-decode)
function verifyMadeOnSol(rawBody, timestamp, signature, secret) {
  // X-MadeOnSol-Timestamp: unix milliseconds, fresh on every retry
  if (typeof timestamp !== "string" || !/^\d{1,16}$/.test(timestamp)) return false;
  // Replay window: your choice, the server does not enforce one
  if (Math.abs(Date.now() - Number(timestamp)) > 5 * 60_000) return false;
  // X-MadeOnSol-Signature: 64 hex characters, bare (no algorithm prefix)
  if (typeof signature !== "string" || !/^[0-9a-f]{64}$/i.test(signature)) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.`)
    .update(rawBody)
    .digest();
  // Both sides are exactly 32 bytes here, so this compares in constant time and cannot throw
  return crypto.timingSafeEqual(expected, Buffer.from(signature, "hex"));
}

const app = express();

// express.raw keeps the body as bytes. Do not mount express.json() in front of it.
app.post("/madeonsol", express.raw({ type: "application/json" }), (req, res) => {
  const ok = verifyMadeOnSol(
    req.body,
    req.get("X-MadeOnSol-Timestamp"),
    req.get("X-MadeOnSol-Signature"),
    process.env.MADEONSOL_WEBHOOK_SECRET,
  );
  if (!ok) return res.sendStatus(401);
  res.sendStatus(200); // answer inside the 10 s delivery timeout, then work
  const { event, data } = JSON.parse(req.body.toString("utf8"));
  // ...
});

Verifier (Python)

import hashlib
import hmac
import re
import time

_HEX64 = re.compile(r"[0-9a-fA-F]{64}")
_DIGITS = re.compile(r"[0-9]{1,16}")

# raw_body:  the exact request bytes (never re-serialized JSON)
# secret:    the webhook secret exactly as the API returned it (do not hex-decode)
def verify_madeonsol(raw_body: bytes, timestamp: str | None, signature: str | None, secret: str) -> bool:
    # X-MadeOnSol-Timestamp: unix milliseconds, fresh on every retry
    if not timestamp or not _DIGITS.fullmatch(timestamp):
        return False
    # Replay window: your choice, the server does not enforce one
    if abs(time.time() * 1000 - int(timestamp)) > 5 * 60 * 1000:
        return False
    # X-MadeOnSol-Signature: 64 hex characters, bare (no algorithm prefix)
    if not signature or not _HEX64.fullmatch(signature):
        return False
    expected = hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
    # Both strings are 64 ASCII hex characters here, so compare_digest cannot raise
    return hmac.compare_digest(expected, signature.lower())
Retry policy: 3 retries with exponential backoff (5 s, 30 s, 2 min). After 10 consecutive failures the webhook auto-disables. Re-enable with PATCH /webhooks/:id and {"is_active": true}.

Event types

kol:tradeKOL wallet buys or sells a token
kol:coordinationYour own coordination alert rule fired: multiple KOLs converged on the same token (delivered only to the rule owner)
deployer:alertTracked deployer launches a new token
deployer:bondTracked deployer's token graduates bonding curve
wallet_tracker:eventSwap or transfer on a wallet in your watchlist (subscriber-scoped)
sniper:deployPre-confirm pump.fun deploy detected (PRO+; PRO is curated to elite/good deployers, ULTRA sees every tier)
rhc:kol_tradeTracked KOL buys or sells on Robinhood Chain (PRO+). EVM-native payload — 0x addresses, eth_amount, tx_hash.
token:surgeA token < 30 min old running vs its launch MC — tier early / strong / breakout, each once per mint (PRO+). Carries the tape, KOL + early-buyer cohort, deployer reputation and risk_flags[].
token:revivalA token with no trade candle for ≥24 h confirmed trading again by real buys + buy volume — never by the price mark alone (PRO+). Same payload shape as token:surge with dormant_hours / prev_mc_usd.
copytrade:signalMatched copy-trade rule — configured via POST /copytrade/subscriptions, NOT /webhooks. Uses a per-rule HMAC secret.

Filter options

min_solnumberMinimum SOL amount (for kol:trade). Solana events only — a silent no-op on rhc:kol_trade, whose payload carries eth_amount, not sol_amount.
actionstring"buy" or "sell" (for kol:trade)
kol_namestringFilter by specific KOL name. Solana events only — RHC payloads do not carry this field, so setting it drops every rhc:kol_trade event.
deployer_tierstring[]Filter by deployer tiers: ["elite", "good"]
min_kolsnumberMinimum KOL count (for kol:coordination)
kindsstring[]["surge"] or ["revival"] — which momentum fires to receive (token:surge / token:revival)
tiersstring[]["strong", "breakout"] — surge tiers to receive (token:surge only)
launchpadsstring[]["pumpfun", "launchlab"] — momentum fires by launchpad / primary DEX
exclude_flagsstring[]["bundled_launch", "thin_liquidity"] — drop momentum fires carrying ANY listed risk flag
min_mc_usd / max_mc_usdnumberMarket-cap band on momentum fires (market_cap_usd at the fire)

WebSocket streams

Push channels, no polling.

30 channels on one socket: 16 Solana — kol:trades, kol:coordination (user-scoped), kol:first_touches, deployer:alerts, wallet_tracker:events (ULTRA), copytrade:signals, price_alert:events, sniper:deploys, token:graduations, token:prices (mint-scoped, PRO+), token:locks, token:fee_claims, token:surges (surge + revival fires with risk flags), token:candles, token:risk (both mint-scoped, PRO+) and wallet:scores (wallet-scoped, PRO+) — plus 14 Robinhood Chain channels — rhc:kol_trades, rhc:copytrade:signals, rhc:price_alert:events, rhc:kol:coordination, rhc:kol:first_touches, rhc:token_locks, rhc:token_prices, rhc:token_candles, rhc:token_risk and rhc:wallet_scores (PRO+ — ULTRA gates only the first-touch subscription endpoint, not the channel; rhc:token_prices, rhc:token_candles and rhc:token_risk are address-scoped, rhc:wallet_scores wallet-scoped, each with its own per-connection cap), plus rhc:dex_trades, rhc:dex_trades_unattributed, rhc:new_tokens and rhc:lp_events (ULTRA+). Event frames carry id + seq (seq gaps are normal, not loss; token:price ticks carry neither). Reconnect with resume:{instance, seq, ts} to recover up to 60 minutes from memory or storage, even across a server restart; replay_end reports per channel what was and was not recovered. The all-DEX firehose runs on its own ULTRA endpoint (2 connections, Business 5).

Need every swap on every venue rather than the tracked-wallet channels? The all-DEX firehose (/ws/v1/dex-stream) is documented below. For the products teams build on it and how it recovers from a short disconnect, see what you can build on the DEX trade firehose. For an interface that charts token:prices and token:candles next to a live tape, see building a trading terminal on these channels.
POST/stream/tokenPRO

Get WebSocket Token

Get your authentication token for the WebSocket streaming server. Since 2026-08-27 the token does NOT expire: every call returns the same value (safe for multi-process clients — nothing to refresh, nothing to schedule). It stops working only if your subscription lapses, or if you send {"rotate":true} to replace it (the old value then keeps working for 60 s). Own rate bucket (10/min) — REST traffic never locks you out of minting. Present it as `Authorization: Bearer <token>` on the handshake, or `?token=` if your client cannot set headers (masked in our access logs either way).

Example Response

{
  "token": "dGhpcyBpcyBhIHNhbXBsZSB0b2tlbg...",
  "expires_at": null,
  "next_refresh_at": null,
  "ws_url": "wss://madeonsol.com/ws/v1/stream",
  "dex_ws_url": "wss://madeonsol.com/ws/v1/dex-stream (Ultra and Business)",
  "usage": "Connect: wscat -c \"wss://madeonsol.com/ws/v1/stream?token=YOUR_TOKEN\" — then send {\"type\":\"subscribe\",\"channels\":[\"kol:trades\"]}. You receive NO events until you subscribe.",
  "subscribe_example": {
    "type": "subscribe",
    "channels": [
      "kol:trades"
    ]
  }
}
WSwss://madeonsol.com/ws/v1/stream

WebSocket Streaming

Real-time event streaming via direct WebSocket connection to madeonsol.com. After connecting, you MUST send a subscribe message — no events are delivered until the server acks it with {type:'subscribed'}. If no channels are active after 10s the server sends a {type:'hint'} frame. The stream token does not expire; if you rotate it, live sockets receive the new value in-band as {type:'token_refresh'}, so store it for your next reconnect. Event frames carry `seq` and a stable `id`; token:price ticks carry neither. seq is one ordinal per server process shared by all channels and all customers, assigned before your filters run, so gaps in the seq you receive are normal and are NOT evidence of loss. The id is the same whether an event is delivered live, re-sent from memory or rebuilt from storage: delivery is at-least-once, dedupe by id. RESUME: keep a cursor {instance, seq, ts} of the last frame your handler finished processing (it returned, or its promise settled) and reconnect with subscribe {..., resume:{instance, seq, ts}}. The {type:'subscribed'} ack echoes resume with accepted:true (accepted:false + a warning code 'replay_in_progress' if a replay is already running on that connection; its channels are still subscribed). Same server instance and cursor inside the in-memory buffer (last 20,000 frames, about 6-8 minutes): frames are re-sent from memory (mode:'ring', with their seq). Otherwise (server restart, or a longer absence) each channel is rebuilt from storage from the cursor's ts (minus 60 s slack, deduped by id), bounded to 60 minutes back, 2,000 rows per channel and 20,000 rows in total (rhc:dex_trades and rhc:dex_trades_unattributed: 10 minutes back and up to 10,000 rows, which can include trades that were never pushed live). Rebuilt frames carry seq:null, mode:'durable', replayed:true, and partial:true + missing:[fields] where a field is not stored. token:graduations and rhc:new_tokens have no stored source: whatever the memory buffer still holds is re-sent, then the channel reports gap 'not_reconstructable'. token:prices gets the current price row per watched mint once (snapshot:true, partial:true). Every resume or legacy replay is bracketed by {type:'replay_start'} and {type:'replay_end'}, even when there is nothing to replay; replay_end carries sent, matched, complete, reason, retryable, retry_after_ms?, resume_ts_hint?, incomplete_channels?, last_seq, last_ts (maxima over frames sent; last_seq never above live_from_seq - 1), live_from_seq, count (legacy, = matched) and channels:{<channel>:{mode, sent, matched, complete, reason?, gap?, time_basis?, max_rows?, retryable?, retry_after_ms?, late_ingest_possible?, partial?, missing?, since_ts?, truncated_at_ts?, gap_before_ts?}}; reasons are backpressure, instance_changed, ring_truncated, window_exceeded, row_cap, source_busy, source_error, late_ingest_possible, not_reconstructable. COMMIT RULE: replayed frames do not move your saved cursor, because a storage replay is sent channel by channel, not in one time order. On replay_end complete:true, commit {instance, seq: last_seq, ts: last_ts} (keep your previous value where one is null) and let live frames advance it again. On complete:false with retryable:true, keep the cursor you resumed from and resume again after retry_after_ms (from ts: resume_ts_hint ONLY when the reply carries one, which the server emits when every incomplete RETRYABLE channel was cut by row_cap (a channel with a FINAL gap, such as not_reconstructable on token:graduations or rhc:new_tokens, does not block the hint, because retrying could not fetch anything behind it); with a mixed retryable set, for example one row_cap and one source_error channel, there is no hint and you resume from your pre-resume cursor, because the hint would step past the failed channel's unread range. Per-channel truncated_at_ts is always there for a client that tracks channels separately); what arrives twice is dropped by id. On complete:false with retryable:false the reported gaps are final (not_reconstructable, window_exceeded, ring_truncated, instance_changed): backfill them from REST, then commit as for complete. SDK behaviour: on a retryable incomplete recovery our SDKs resume again on the same socket after retry_after_ms (up to maxResumeRetries, default 5), using resume_ts_hint only when every incomplete retryable channel is row_cap. The budget is per connection and its counter resets on every (re)connect. When that budget is spent, the gap event says exhausted:true: the client stops asking on that connection, the committed cursor stays where it is, and the next reconnect resumes again. On a FINAL gap they emit a gap event first (channels, reason, permanent, the server's bounds and the RANGE that may be incomplete as skipped.from -> skipped.to) with advancedPastGap:true and source:"auto", then move the cursor past it. A count of missing events is never given because it cannot be known. That advance is the client library's own decision, not your approval: set onUnrecoverableGap:"stop" to keep the cursor instead, which stops the stream and emits fatal with the same gap, and acceptGap() then re-reports it with source:"manual" and continues. WATERMARK AND HOLDBACK: a row's id or timestamp is assigned when it is written, not when it commits, so a row with a lower id can still appear after a read passed it. The server therefore advances the committable watermark only across rows whose writing transaction had already finished when the read took its snapshot (xmin_blocked:true when it stops early), holds it 5 s behind now (holdback_ms) and re-scans the last 60 s (rescan_ms) on the next resume; a stuck long transaction cannot freeze it forever (capped at maxHoldbackMs, reported as holdback_capped_ms). While the cap is in force the channel reports holdback_ms = 300000 (the nominal 5000 stays as nominal_holdback_ms) and its guarantee states the real bound and says CAPPED: about 6 minutes (5 min + the 60 s re-scan), not the usual 65 s.. Frames are still delivered as they are read; the holdback only limits what you may commit, and last_ts is held to the tightest safe_ts (per channel in replay_end.channels.<ch>.watermark {scheme, safe_ts, holdback_ms, nominal_holdback_ms?, holdback_capped_ms?, rescan_ms, xmin_blocked, gate_ms?, guarantee}, overall in replay_end.watermark_safe_ts). RECOVERY IS BOUNDED, NOT A COMPLETENESS GUARANTEE: with the id and ingest-time schemes a write whose transaction commits more than about 65 s after its id or timestamp was taken can be missed (about 6 minutes instead while holdback_capped_ms is set), and for rhc:dex_trades / rhc:dex_trades_unattributed (scheme producer_gate) recovery is bounded by the producer's 600 s freshness rule, so a trade already older than 600 s when it was ingested is not recoverable through this path at all. Each channel states its own bound in watermark.guarantee. LATE WRITES: every storage read pages by an ingest-time column, a storage id or the producer's own freshness window, so a row written late is not skipped; a channel that could not rule that out would report complete:false, reason late_ingest_possible, never complete:true. LOAD: recovery is limited server-wide; a resume waits up to 20 s for a slot, otherwise its storage-backed channels report reason source_busy with retry_after_ms (memory frames are still sent). A second replay request on a socket whose replay is still running gets only a replay_in_progress warning, no second replay_start / replay_end, so do not wait for one. Live frames that arrive during a replay are held (up to 5,000 frames or 4 MB; price ticks coalesced per mint) and delivered right after replay_end, skipping ids already sent. A socket that cannot drain during a replay gets complete:false, reason 'backpressure' and a 4008 close: reconnect and resume. Frames can only be lost across a disconnect or a 4008 close, and a resume tells you what was and was not recovered. LEGACY: replay_since_seq / replay_since_ts still work, from memory only; replay_start now says replay_truncated:true with reason 'instance_changed' or 'ring_truncated' instead of replaying nothing silently. If our own event bus connection drops, the server re-reads the missed events from storage and delivers them with replayed:true, recovered:'bus'. ENTITLEMENTS: every frame is checked against your current plan; after a downgrade, channels above it are dropped with a warning code 'channels_revoked' (also a token:prices mint set above the new cap). Revoking or rotating your API key revokes the stream token: open sockets close with 4001 within about a minute; mint a new token with the new key. NAMED SUBSCRIPTIONS: a subscribe without sub_id is the connection's default subscription (one channel set, one filter object for the socket, e.g. action:'buy' on it also drops deployer alerts); a subscribe with sub_id (1-64 chars of A-Z a-z 0-9 _ . -) opens an independent subscription with its own channels and filters, update {sub_id, filters} replaces its filters, unsubscribe {sub_id} removes it, list answers {type:'subscriptions'}. Frames under a named subscription carry sub_id; an event matching several subscriptions is delivered once per subscription (dedupe by sub_id + id); filters of one never affect another; refusals are warning frames with the sub_id (invalid_sub_id, too_many_subscriptions, unknown_sub_id, invalid_filters, channels_rejected, replay_in_progress). Cap per connection, default included: Pro 5, Ultra 10, Business 20. Resume is per subscription (each subscribe carries the same cursor; replays run one after another and live frames wait for the last replay_end; commit at the smallest last_seq across them). Pro: 2 concurrent connections. Ultra: 3. Business: 10. 15-second heartbeat.

Parameters

NameTypeDefaultDescription
tokenquery paramrequiredAuthentication token from POST /stream/token

Example Response

{
  "_subscribe": {
    "type": "subscribe",
    "channels": [
      "kol:trades",
      "deployer:alerts"
    ],
    "filters": {
      "min_sol": 1
    }
  },
  "_subscribe_with_resume": {
    "type": "subscribe",
    "channels": [
      "kol:trades",
      "deployer:alerts"
    ],
    "resume": {
      "instance": "6f1a2b3c4d5e",
      "seq": 184203,
      "ts": 1712159990000
    }
  },
  "_subscribed_resume": {
    "type": "subscribed",
    "channels": [
      "kol:trades",
      "deployer:alerts"
    ],
    "seq": 190112,
    "instance": "9c8d7e6f5a4b",
    "resume": {
      "instance": "6f1a2b3c4d5e",
      "seq": 184203,
      "ts": 1712159990000,
      "accepted": true
    }
  },
  "_replay_start_durable": {
    "type": "replay_start",
    "mode": "durable",
    "count": null,
    "resume": true,
    "reason": "instance_changed",
    "since_ts": 1712159990000,
    "limits": {
      "max_age_ms": 3600000,
      "max_rows_per_channel": 2000,
      "max_rows_total": 20000,
      "slack_ms": 60000
    }
  },
  "_event_durable": {
    "channel": "kol:trades",
    "event": "kol:trade",
    "id": "kol:trade:5K7j...",
    "seq": null,
    "mode": "durable",
    "replayed": true,
    "partial": true,
    "missing": [
      "slot",
      "fdv_usd_at_trade",
      "liquidity_usd_at_trade",
      "primary_dex",
      "primary_pool_address"
    ],
    "data": {
      "kol_name": "Cented",
      "action": "buy",
      "sol_amount": 5.27,
      "token_symbol": "PEPE"
    },
    "ts": 1712160000000
  },
  "_replay_end": {
    "type": "replay_end",
    "count": 212,
    "sent": 212,
    "matched": 212,
    "complete": true,
    "reason": null,
    "retryable": false,
    "last_seq": null,
    "last_ts": 1712160295000,
    "live_from_seq": 190113,
    "watermark_safe_ts": 1712160295000,
    "mode": "durable",
    "resume_reason": "instance_changed",
    "channels": {
      "kol:trades": {
        "mode": "durable",
        "sent": 180,
        "matched": 180,
        "complete": true,
        "time_basis": "ingest_time",
        "max_rows": 2000,
        "watermark": {
          "scheme": "ingest_time_holdback",
          "safe_ts": 1712160295000,
          "holdback_ms": 5000,
          "rescan_ms": 60000,
          "xmin_blocked": false,
          "guarantee": "bounded recovery, not completeness: a write committing >65s after its stamp may be missed"
        },
        "partial": true,
        "missing": [
          "slot",
          "fdv_usd_at_trade",
          "liquidity_usd_at_trade",
          "primary_dex",
          "primary_pool_address"
        ],
        "since_ts": 1712159930000
      },
      "deployer:alerts": {
        "mode": "durable",
        "sent": 32,
        "matched": 32,
        "complete": true,
        "partial": true,
        "since_ts": 1712159930000
      }
    }
  },
  "_replay_end_retry": {
    "type": "replay_end",
    "count": 2000,
    "sent": 2000,
    "matched": 2000,
    "complete": false,
    "reason": "row_cap",
    "retryable": true,
    "resume_ts_hint": 1712160120000,
    "incomplete_channels": [
      "rhc:dex_trades"
    ],
    "last_seq": null,
    "last_ts": 1712160120000,
    "live_from_seq": 190113,
    "mode": "durable",
    "channels": {
      "rhc:dex_trades": {
        "mode": "durable",
        "sent": 2000,
        "matched": 2000,
        "complete": false,
        "reason": "row_cap",
        "retryable": true,
        "max_rows": 10000,
        "truncated_at_ts": 1712160120000
      }
    }
  },
  "_subscribe_with_replay_legacy": {
    "type": "subscribe",
    "channels": [
      "kol:trades"
    ],
    "replay_since_seq": 184203
  },
  "_subscribe_named": {
    "type": "subscribe",
    "sub_id": "kol-buys",
    "channels": [
      "kol:trades"
    ],
    "filters": {
      "action": "buy",
      "min_sol": 1
    }
  },
  "_subscribed_named": {
    "type": "subscribed",
    "sub_id": "kol-buys",
    "channels": [
      "kol:trades"
    ],
    "filters": {
      "action": "buy",
      "min_sol": 1
    },
    "seq": 190112,
    "instance": "9c8d7e6f5a4b"
  },
  "_event_named": {
    "channel": "kol:trades",
    "sub_id": "kol-buys",
    "event": "kol:trade",
    "id": "kol:trade:5K7j...",
    "seq": 190113,
    "data": {
      "kol_name": "Cented",
      "action": "buy",
      "sol_amount": 5.27,
      "token_symbol": "PEPE"
    },
    "ts": 1712160000000
  },
  "_update_named": {
    "type": "update",
    "sub_id": "kol-buys",
    "filters": {
      "action": "buy",
      "min_sol": 5
    }
  },
  "_updated_named": {
    "type": "updated",
    "sub_id": "kol-buys",
    "filters": {
      "action": "buy",
      "min_sol": 5
    }
  },
  "_list": {
    "type": "list"
  },
  "_subscriptions": {
    "type": "subscriptions",
    "list": [
      {
        "sub_id": "default",
        "channels": [
          "deployer:alerts"
        ],
        "filters": {}
      },
      {
        "sub_id": "kol-buys",
        "channels": [
          "kol:trades"
        ],
        "filters": {
          "action": "buy",
          "min_sol": 5
        }
      }
    ],
    "count": 2,
    "max": 5
  },
  "_unsubscribe_named": {
    "type": "unsubscribe",
    "sub_id": "kol-buys"
  },
  "_warning_named": {
    "type": "warning",
    "code": "too_many_subscriptions",
    "sub_id": "sixth",
    "max": 5,
    "tier": "PRO"
  },
  "_named_subscriptions_note": "Named subscriptions (Phase 2): one socket holds several independent subscriptions, each with its own channels and filters; the default subscription (no sub_id) is unchanged and its frames carry no sub_id. An event matching several subscriptions is delivered once per subscription, each frame stamped sub_id: dedupe by (sub_id, id). Cap per connection, default included: PRO 5 / ULTRA 10 / BUSINESS 20; token:prices mints are capped per connection across subscriptions. Resume per subscription: send every subscribe with the same resume cursor on reconnect; the server serves one replay per sub_id in turn (resume.queued:true on the acks that wait) and holds live frames until the last replay_end; commit at the smallest last_seq / last_ts across them.",
  "_subscribe_token_prices": {
    "type": "subscribe",
    "channels": [
      "token:prices"
    ],
    "filters": {
      "mints": [
        "8vdc...pump",
        "9aK2...pump"
      ]
    }
  },
  "_subscribe_candles": {
    "type": "subscribe",
    "sub_id": "candles",
    "channels": [
      "token:candles"
    ],
    "filters": {
      "mints": [
        "8vdc...pump"
      ],
      "updates": true
    }
  },
  "_event_candle_closed": {
    "channel": "token:candles",
    "sub_id": "candles",
    "event": "candle:closed",
    "id": "candle:solana:8vdc...pump:1790157600",
    "seq": 184220,
    "data": {
      "chain": "solana",
      "mint": "8vdc...pump",
      "bucket_start": "2026-09-23T10:00:00.000Z",
      "bucket_end": "2026-09-23T10:01:00.000Z",
      "closed_at": "2026-09-23T10:01:13.402Z",
      "open_price_usd": 0.0000412,
      "high_price_usd": 0.0000431,
      "low_price_usd": 0.0000409,
      "close_price_usd": 0.0000428,
      "close_mc_usd": 42800,
      "volume_usd": 1843.2,
      "trades": 37,
      "final": true,
      "source": "token_ohlc_1m"
    },
    "ts": 1790157673402
  },
  "_subscribe_risk": {
    "type": "subscribe",
    "sub_id": "risk",
    "channels": [
      "token:risk"
    ],
    "filters": {
      "mints": [
        "8vdc...pump"
      ]
    }
  },
  "_event_risk_authority": {
    "channel": "token:risk",
    "sub_id": "risk",
    "event": "risk:authority_changed",
    "id": "risk:authority_changed:8vdc...pump:freeze_authority:revoked",
    "seq": 184221,
    "data": {
      "chain": "solana",
      "mint": "8vdc...pump",
      "field": "freeze_authority",
      "before": {
        "revoked": false
      },
      "after": {
        "revoked": true
      },
      "observed_at": "2026-09-23T10:02:11.000Z",
      "previous_observed_at": "2026-09-23T09:58:40.000Z",
      "slot": null,
      "source": "token_prices"
    },
    "ts": 1790157731000
  },
  "_subscribe_wallet_scores": {
    "type": "subscribe",
    "sub_id": "scores",
    "channels": [
      "wallet:scores",
      "rhc:wallet_scores"
    ],
    "filters": {
      "wallets": [
        "7xKX...deployer",
        "0x9287...c0de"
      ]
    }
  },
  "_event_tier_changed": {
    "channel": "wallet:scores",
    "sub_id": "scores",
    "event": "deployer:tier_changed",
    "id": "deployer:tier_changed:7xKX...deployer:unranked>rising:81234567",
    "seq": 184222,
    "data": {
      "chain": "solana",
      "wallet": "7xKX...deployer",
      "tier_before": "unranked",
      "tier_after": "rising",
      "entered_ranking": true,
      "computed_at": "2026-09-23T10:03:02.118Z",
      "source": "live_write"
    },
    "ts": 1790157782118
  },
  "_connected": {
    "type": "connected",
    "seq": 184210,
    "instance": "6f1a2b3c4d5e",
    "replay": {
      "oldest_seq": 164210,
      "newest_seq": 184210,
      "size": 20000
    }
  },
  "_event_kol_trade": {
    "id": "kol:trade:5K7j...",
    "seq": 184211,
    "channel": "kol:trades",
    "event": "kol:trade",
    "data": {
      "kol_name": "Cented",
      "action": "buy",
      "sol_amount": 5.27,
      "token_symbol": "PEPE",
      "market_cap_usd_at_trade": 28430,
      "price_usd_at_trade": 0.0000284,
      "mc_change_pct": {
        "5m": 8.2,
        "1h": 62.1,
        "4h": 87
      },
      "volume_usd": {
        "5m": 42000,
        "1h": 340000,
        "4h": 920000
      },
      "mev_volume_pct": {
        "1h": 18.4
      }
    },
    "ts": 1712160000000
  },
  "_event_deployer": {
    "id": "deployer:alert:918273",
    "seq": 184212,
    "channel": "deployer:alerts",
    "event": "deployer:alert",
    "data": {
      "alert_id": 918273,
      "tx_signature": "3xQm...",
      "deployer_tier": "elite",
      "token_symbol": "NEW",
      "alert_type": "new_deploy",
      "deployer_sol_balance": 42.5301,
      "mc_change_pct": {
        "5m": 250,
        "15m": 480
      },
      "volume_usd": {
        "5m": 12000
      }
    },
    "ts": 1712160000000
  },
  "_event_graduation": {
    "id": "token:graduation:8vdc...pump",
    "seq": 184213,
    "channel": "token:graduations",
    "event": "token:graduation",
    "data": {
      "token_mint": "8vdc...pump",
      "token_symbol": "JUNIE",
      "time_to_bond_minutes": 38,
      "deployer_wallet": "7vfC...rXs2",
      "deployer_tier": "rising",
      "market_cap_usd": 24180,
      "bonded_at": "2026-06-07T09:00:00Z"
    },
    "ts": 1712160000000
  },
  "_channels": [
    "kol:trades",
    "kol:coordination",
    "kol:first_touches",
    "deployer:alerts",
    "wallet_tracker:events",
    "copytrade:signals",
    "price_alert:events",
    "sniper:deploys",
    "token:graduations",
    "token:prices",
    "token:locks",
    "token:fee_claims",
    "token:surges",
    "rhc:kol_trades",
    "rhc:dex_trades",
    "rhc:dex_trades_unattributed",
    "rhc:new_tokens",
    "rhc:copytrade:signals",
    "rhc:price_alert:events",
    "rhc:kol:coordination",
    "rhc:kol:first_touches",
    "rhc:token_locks",
    "rhc:token_prices",
    "rhc:lp_events",
    "token:candles",
    "rhc:token_candles",
    "token:risk",
    "rhc:token_risk",
    "wallet:scores",
    "rhc:wallet_scores"
  ],
  "_event_surge": {
    "channel": "token:surges",
    "event": "token:surge",
    "id": "token:surge:4812",
    "seq": 184214,
    "data": {
      "id": 4812,
      "kind": "surge",
      "tier": "strong",
      "mint": "9kQu...pump",
      "symbol": "RUNNER",
      "launchpad": "pumpfun",
      "fired_at": "2026-08-28T10:00:00Z",
      "age_seconds": 450,
      "market_cap_usd": 38400,
      "liquidity_usd": 9100,
      "baseline_mc_usd": 5600,
      "baseline_source": "launch",
      "mc_multiple": 6.857,
      "mc_change_3m_pct": 112.4,
      "tape": {
        "buys": 96,
        "sells": 31,
        "buy_volume_usd": 21300,
        "unique_buyers": 58,
        "wallet_data_available": true
      },
      "kol": {
        "buyers": 2,
        "names": [
          "alpha_scout",
          "degen_dan"
        ]
      },
      "early_buyers": {
        "count": 20,
        "bundled": 0,
        "sold": 3,
        "sniper_wallets": 1
      },
      "deployer_tier": "good",
      "risk_flags": []
    },
    "ts": 1788256800000
  },
  "_event_revival": {
    "channel": "token:surges",
    "event": "token:revival",
    "id": "token:revival:4813",
    "seq": 184215,
    "data": {
      "id": 4813,
      "kind": "revival",
      "tier": null,
      "mint": "8vdc...pump",
      "symbol": "GHOST",
      "primary_dex": "pumpswap",
      "fired_at": "2026-08-28T10:05:00Z",
      "dormant_hours": 412.6,
      "prev_mc_usd": 22100,
      "market_cap_usd": 61000,
      "mc_vs_prev_multiple": 2.76,
      "peak_mc_usd": 340000,
      "pct_of_peak": 17.94,
      "tape": {
        "buys": 27,
        "sells": 4,
        "buy_volume_usd": 8900,
        "unique_buyers": 19,
        "wallet_data_available": true
      },
      "kol": {
        "buyers": 1,
        "names": [
          "cto_hunter"
        ]
      },
      "early_buyers": {
        "count": 20,
        "bundled": 2,
        "sold": 17,
        "sniper_wallets": 0
      },
      "deployer_tier": "moderate",
      "risk_flags": [
        "early_buyers_exiting"
      ]
    },
    "ts": 1788257100000
  },
  "_surges_filters_note": "token:surges subscribe filters: kinds[] (surge|revival), tiers[] (surges only), launchpads[], exclude_flags[] (drop a frame carrying ANY listed risk flag), min_mc_usd/max_mc_usd, deployer_tier[] (fail-closed: a fire with no known deployer carries deployer_tier null and is dropped by that filter). Identical semantics on the webhook registry events token:surge / token:revival.",
  "_channel_gates_note": "30 channels. Solana channel gates: kol:coordination (user-scoped to your own /kol/coordination/alerts rules), kol:first_touches, copytrade:signals, price_alert:events and token:prices are PRO+; sniper:deploys PRO+ (PRO receives the curated elite/good deployers, ULTRA every tier); wallet_tracker:events ULTRA+; kol:trades, deployer:alerts, token:graduations, token:locks, token:fee_claims and token:surges have no channel-level gate beyond the PRO+ stream token. token:prices is MINT-SCOPED — filters.mints is required (max 25 mints on PRO, 100 on ULTRA, 250 on BUSINESS; a subscribe above the cap is rejected, not truncated) and delivers event token:price (~250 ms coalesced per mint). token:locks pushes every new Streamflow / Jupiter Lock / Bonfida lock or vesting contract (event token:lock); token:fee_claims pushes pump.fun fee distributions, social-handle claims and config changes. Lock lifecycle (2026-09-23, opt-in): subscribe token:locks with filters.lifecycle:true to also receive token:lock_claimed, token:lock_cancelled, token:lock_closed, token:lock_updated (change topup | extended | schedule_changed | recipient_changed), token:unlock_upcoming (the lock's next unlock within 24 h) and token:unlock_available (the unlock passed within 30 min: claimable per the schedule, NOT claimed); optional filters events[], unlock_kinds[], mints[] and include_automatic_claims (default false, hides Streamflow keeper-cranked withdrawals, about 90 % of claims). Without lifecycle the channel is unchanged. Events are deduplicated server-side and never emitted for history. Phase 4 (2026-09-23), all PRO+ and SCOPED with their OWN per-connection budget (25 PRO / 100 ULTRA / 250 BUSINESS each, reject never truncate): token:candles (filters.mints; event candle:closed = the stored 1-minute row, id candle:solana:<mint>:<bucket_start s>; filters.updates:true adds candle:update, the minute in progress, ≤ 1 per mint per second, never replayed; fully flat no-trade minutes are not sent), token:risk (filters.mints; risk:authority_changed = mint / freeze authority revoked or Token-2022 fee changed, risk:supply_inflated = first 0.5 % / 5 % supply-drift crossing; a risk:inputs snapshot per mint on subscribe unless risk_snapshot:false; optional risk_events[]; input changes, NOT a risk-band stream) and wallet:scores (filters.wallets, base58; deployer:tier_changed incl. an unranked wallet entering a ranked tier, kol:score_state_changed for is_cold / is_heating_up / auto_strategy_tag; every frame carries source + computed_at = \"recomputed at T\", not \"changed at T\"; optional score_events[]).",
  "_rhc_channels_note": "The 14 rhc:* channels are Robinhood Chain (chain id 4663) and ride the SAME socket as the Solana channels — one token, one connection. Payloads are EVM-native (evm_address, token_address, eth_amount, tx_hash), never the Solana field names. rhc:kol_trades (PRO+), rhc:dex_trades (ULTRA+, every attributed swap on the chain), rhc:dex_trades_unattributed (ULTRA+, swaps on pools where neither side is \"the token\" — quote/quote pairs such as WETH/USDG — raw leg data only, no buy/sell action; subscribe to both dex channels for full chain coverage), rhc:new_tokens (ULTRA+, fired once per token the moment its symbol/name/decimals first resolve on-chain, before its first trade lands), rhc:copytrade:signals (PRO+, user-scoped to your own /rhc/copytrade rules), rhc:price_alert:events (PRO+, user-scoped to your own /rhc/price-alerts), rhc:kol:coordination (PRO+, user-scoped to your own /rhc/kol/coordination/alerts), rhc:kol:first_touches (PRO+ broadcast — ULTRA gates only the filtered first-touch SUBSCRIPTION endpoint, not the channel), rhc:token_locks (PRO+ broadcast, one event per token lock or vesting contract created on chain; withdrawals are not tracked; with filters.lifecycle:true also rhc:token_unlock_upcoming / rhc:token_unlock_available, the unlock schedule only, since claims, extensions and cancels are not observable on RHC), rhc:token_prices (PRO+, ADDRESS-SCOPED: filters.addresses is required and capped per connection at 25 PRO / 100 ULTRA / 250 BUSINESS — over the cap is rejected, never truncated; event rhc:token_price: one snapshot per address on subscribe, then ticks derived from the RHC trade feed at most once per address per 250 ms, each with quality fresh | stale | unreliable and quality_reason, price_source, source_pool, liquidity_usd, observed_at and price_age_ms; state stream, no seq/id, a resume gets a fresh snapshot), rhc:lp_events (ULTRA+, RHC liquidity events: add / remove / pool_created on tracked Uniswap v2/v3/v4 pools with in_range + share + material; filters addresses, pools, dexes, actions, material_only, min_share), rhc:token_candles (PRO+, filters.addresses, own cap: rhc:candle_closed, rhc:candle_revised when a stored candle is rewritten — id …:r<n>, latest revision only on replay — and with filters.updates:true rhc:candle_update ≤ 1 per address per second), rhc:token_risk (PRO+, filters.addresses, own cap: rhc:risk_verdict_changed when a recheck stores a different verdict, before/after + checked_at + previous_checked_at — the change happened in that window, days to weeks today; score is higher = safer; rhc:risk_verdict snapshot on subscribe) and rhc:wallet_scores (PRO+, filters.wallets with 0x deployers, own cap: rhc:deployer_tier_changed from the 5-minute mv_rhc_deployers refresh, source matview_refresh). rhc:dex_trade / rhc:dex_trade_unattributed payloads carry additive enrichment since 2026-09-22: amount_in_raw / amount_out_raw as exact decimal strings, token + quote {address, symbol, decimals} (token_in_meta / token_out_meta on the unattributed channel), metadata_status, price_status / price_source / price_observed_at, mc_status, side + side_reason; a KOL trade appears on both rhc:kol_trades and rhc:dex_trades with the same tx_hash + log_index and different ids. Rule-backed RHC channels deliver nothing until you create the matching rule.",
  "_event_rhc_token_price": {
    "channel": "rhc:token_prices",
    "event": "rhc:token_price",
    "data": {
      "chain": "robinhood",
      "address": "0x4a0e...5eea",
      "symbol": "SPCX",
      "price_usd": 12.41,
      "price_native": null,
      "market_cap_usd": 1240000,
      "liquidity_usd": 88000,
      "source_pool": "0x9f1c...02ab",
      "source_dex": "uniswap-v4",
      "observed_at": "2026-09-22T19:30:14.000Z",
      "price_age_ms": 1320,
      "quality": "fresh",
      "quality_reason": null,
      "price_source": "swap_quote",
      "tx_hash": "0xab12...",
      "log_index": 7,
      "block_number": 62110455,
      "source": "rhc-dex-stream:trade"
    },
    "ts": 1758569415320
  },
  "_event_rhc_token_price_snapshot": {
    "channel": "rhc:token_prices",
    "event": "rhc:token_price",
    "snapshot": true,
    "data": {
      "chain": "robinhood",
      "address": "0x4a0e...5eea",
      "symbol": "SPCX",
      "price_usd": 12.38,
      "price_native": 0.0029,
      "market_cap_usd": 1238000,
      "liquidity_usd": 88000,
      "source_pool": "0x9f1c...02ab",
      "source_dex": "uniswap-v4",
      "observed_at": "2026-09-22T19:12:03.000Z",
      "price_age_ms": 1092000,
      "quality": "stale",
      "quality_reason": "price_age",
      "price_source": "swap_quote",
      "tx_hash": null,
      "log_index": null,
      "block_number": null,
      "source": "rhc_token_prices"
    },
    "ts": 1758568323000
  },
  "_velocity_note": "Every event carrying a token_mint is enriched with velocity context: mc_change_pct, volume_usd (organic, MEV-stripped), and mev_volume_pct keyed by 5m/15m/1h/2h/4h windows. Window keys are only present when the token has been tracked long enough — branch on history_age_seconds rather than probing for missing keys. Reorg-safe (sourced from CONFIRMED-commitment swap stream).",
  "_copytrade_note": "copytrade:signals is user-scoped — only signals from your own rules are delivered. Configure rules via POST /copytrade/subscriptions.",
  "_graduation_note": "token:graduations fires for EVERY pump.fun graduation (bonding curve complete → PumpSwap migration), tracked deployer or not — unlike deployer:bond on deployer:alerts, which covers tracked deployers only. deployer_tier is 'unranked' for unknown deployers; the deployer_tier array filter applies. Real-time detection paths only — reconciler-recovered bonds (rare, minutes-stale) are not emitted."
}
WSwss://madeonsol.com/ws/v1/dex-streamULTRA

DEX Firehose — Real-time DEX Trade Stream (Ultra)

Normalized real-time trade stream across 14 Solana DEX programs (Pump.fun, Pump AMM, Raydium AMM/CPMM/CLMM, Jupiter v6, Orca Whirlpool, Meteora DBC/DAMM/DLMM, LaunchLab/Bonk.fun, Moonshot) via direct WebSocket. Ultra-only (Business included). 2 concurrent connections per user on Ultra, 5 on Business, up to 10 named subscriptions per connection with independent filters, dynamic updates without disconnect, and optional historical replay (up to 500 trades).

Parameters

NameTypeDefaultDescription
tokenquery paramrequiredAuthentication token from POST /stream/token (Ultra tier)

Example Response

{
  "_subscribe": {
    "type": "subscribe",
    "sub_id": "fresh-pumpfun",
    "replay": 50,
    "replay_order": "asc",
    "filters": {
      "dex": "pumpfun",
      "token_age_max_seconds": 300,
      "min_sol": 0.5,
      "action": "buy"
    }
  },
  "_update": {
    "type": "update",
    "sub_id": "fresh-pumpfun",
    "filters": {
      "dex": [
        "pumpfun",
        "pumpswap"
      ],
      "min_sol": 1
    }
  },
  "_unsubscribe": {
    "type": "unsubscribe",
    "sub_id": "fresh-pumpfun"
  },
  "_list": {
    "type": "list"
  },
  "_event": {
    "channel": "dex:trades",
    "sub_id": "fresh-pumpfun",
    "data": {
      "wallet": "7vfC...rXs2",
      "mint": "EPjF...Dt1v",
      "action": "buy",
      "sol_amount": 2.5,
      "token_amount": 50000,
      "tx_signature": "5K7j...",
      "block_time": 1712160000,
      "program": "6EF8...wF6P",
      "dex": "pumpfun",
      "dust": false
    },
    "replay": false,
    "ts": 1712160000000
  },
  "_filters": "At least one targeting filter required. Targeting: token_mint(s) (max 50), wallet(s) (max 50), dex (pumpfun|pumpswap|raydium|jupiter|orca|meteora|launchlab|moonshot — single or array), program (raw program ID), deployer_tier (elite|good|moderate|rising|cold|unranked — single or array), token_age_max_seconds, market_cap_max_sol, market_cap_min_sol. Refinement: min_sol, max_sol, action (buy|sell). min_sol defaults to 0.05 when you don't set it (see _completeness) — the subscribed/updated ack echoes the effective value.",
  "_completeness": "2026-09-08: trades below 0.05 SOL (\"dust\" — roughly half of parsed volume, mostly bots sweeping thin/dead pools) used to never reach this stream — not filtered, dropped before broadcast. They now flow through like any other trade, each frame carrying dust:true. filters.min_sol defaults to 0.05 for any subscription that doesn't set it, so existing integrations see zero volume change; set min_sol explicitly (0 for literally everything, or your own floor) to receive dust.",
  "_notes": "token_age uses a persisted first-seen lookup (survives restarts). market_cap is computed from the in-memory price × cached supply (1h TTL); the first trade for an unseen mint won't match a market_cap filter while the supply fetch is in flight, but every following trade for that mint will. deployer_tier is null/'unranked' for any mint without a tracked deployer. Replay is served from a server-side buffer (not connection-scoped) holding roughly the last 5-6 minutes of firehose history at typical volume (120k trades, doubled 2026-09-08 to hold the same window now that dust is included) — it backfills trades from before your connection existed. Replayed trades are flagged replay:true and delivered newest-first by default (send replay_order:'asc' with the subscribe for oldest-first); you receive the N most recent trades matching your filters. A replay_done message ALWAYS follows (also when nothing matched): { type:'replay_done', sub_id, count, sent, requested, matched, complete, reason?, note?, order }. The server waits for your socket to drain during the replay, so live trades for the same subscription can arrive interleaved with the replayed ones (which stay marked replay:true) before replay_done; if the socket cannot drain, replay_done says complete:false, reason:'backpressure' and the socket is closed 4008. Firehose frames carry no seq; dedupe by tx_signature.",
  "_graduations": "Subscriptions that scope mints via token_mint(s) also receive in-band graduation frames: { channel: 'dex:graduations', sub_id, data: { token_mint, token_symbol, time_to_bond_minutes, deployer_wallet, deployer_tier, market_cap_usd, bonded_at }, ts } — the pump.fun bond lands on the same connection as the trade flow, no separate poll. Subs without mint scoping don't receive them (use the token:graduations channel on /ws/v1/stream for the global feed).",
  "_legs_subscribe": {
    "type": "subscribe",
    "sub_id": "legs",
    "legs": true,
    "filters": {
      "dex": [
        "pumpswap",
        "raydium"
      ],
      "min_sol": 1
    }
  },
  "_legs_route": {
    "channel": "dex:route",
    "sub_id": "legs",
    "data": {
      "signature": "2i8v...ZmQm",
      "slot": 449476673,
      "block_time": null,
      "signer": "7vfC...rXs2",
      "hop_count": 2,
      "leg_ids": [
        "2i8v...ZmQm:7.0",
        "2i8v...ZmQm:7.3"
      ],
      "shape": "chain",
      "decoded_complete": true,
      "undecoded_program_ids": [],
      "liquidity_actions": [],
      "entry_program": "JUP6...TaV4",
      "router_program": "JUP6...TaV4",
      "signer_net": [
        {
          "mint": "So11...1112",
          "delta_raw": "-995000000",
          "decimals": 9,
          "delta_ui": -0.995
        },
        {
          "mint": "Cgxx...pump",
          "delta_raw": "1234567890",
          "decimals": 6,
          "delta_ui": 1234.56789
        }
      ],
      "trade_mint": "Cgxx...pump",
      "legs_version": 1
    },
    "ts": 1712160000000
  },
  "_legs_leg": {
    "channel": "dex:leg",
    "sub_id": "legs",
    "data": {
      "leg_id": "2i8v...ZmQm:7.0",
      "signature": "2i8v...ZmQm",
      "slot": 449476673,
      "signer": "7vfC...rXs2",
      "leg_index": 0,
      "instruction_index": 7,
      "inner_index": 0,
      "program": "LBUZ...wxo",
      "venue": "meteora",
      "pool_model": "concentrated",
      "pool": "49fU...u6Jd",
      "pool_kind": "authority",
      "pool_authority": "49fU...u6Jd",
      "vault_in": "8k3p...4sx7",
      "vault_out": "GySU...VgAg",
      "token_in": {
        "mint": "So11...1112",
        "amount_raw": "995000000",
        "decimals": 9,
        "amount_ui": 0.995,
        "native": false
      },
      "token_out": {
        "mint": "C1MH...",
        "amount_raw": "741269499015",
        "decimals": 9,
        "amount_ui": 741.269499015,
        "native": false
      },
      "side": "buy",
      "amount_basis": "transfers",
      "extra_mints": 0,
      "is_route_member": true,
      "route_shape": "chain"
    },
    "ts": 1712160000000
  },
  "_legs": "Per-pool swap legs (2026-09-22, opt-in, legs_version 1). Add legs:true to a subscribe (or legs:'only' to drop the legacy frame) and every transaction whose dex:trades frame matches your filters is delivered as one dex:route (the whole path: hop_count, leg_ids, shape none|single|chain|split|parallel|mixed, decoded_complete, undecoded_program_ids, liquidity_actions, signer_net = the wallet-swap) plus one dex:leg per decoded pool swap (one DEX instruction hitting one pool: program, venue, pool + pool_kind state|authority|unresolved, pool_authority, vault_in/vault_out, token_in = what the pool received, token_out = what it paid out, amount_raw as an integer string, amount_basis transfers|vault_delta|ambiguous, side buy|sell|null, is_route_member), then the unchanged dex:trades frame exactly once. leg_id is <signature>:<instruction_index>[.<inner_index>], identical live and on replay; dedupe legs by leg_id. Liquidity deposits and withdrawals are never a leg. Coverage is honest: a route that touched a DEX we do not decode says decoded_complete:false and names the program in undecoded_program_ids; the subscribed ack lists coverage.decodable_programs (pump.fun, PumpSwap, Raydium v4/CPMM/CLMM, Orca Whirlpool, Meteora DBC/DAMM v1/DAMM v2/DLMM, LaunchLab, Moonshot; Jupiter v6 and the Raydium route program are routers whose inner legs are decoded). Measured at build time on 429 real trades: 97.4% of routes complete, every incomplete one an unlisted DEX. Replay emits the same frames with the same ids (replay:true); replay_done is unchanged. Legs never change what mc-tracker, candles, token_trades or any REST aggregate count.",
  "_liquidity_subscribe": {
    "type": "subscribe",
    "sub_id": "lp",
    "liquidity": "only",
    "filters": {
      "dex": [
        "raydium",
        "pumpswap",
        "meteora"
      ],
      "actions": [
        "remove"
      ],
      "material_only": true
    }
  },
  "_liquidity_event": {
    "channel": "dex:liquidity",
    "sub_id": "lp",
    "id": "4Rk2...9sQa:3",
    "data": {
      "id": "4Rk2...9sQa:3",
      "instruction_index": 3,
      "inner_index": null,
      "signature": "4Rk2...9sQa",
      "slot": 449480112,
      "block_time": 1712160000,
      "signer": "9xQe...Vf2L",
      "program": "pAMM...EXA",
      "venue": "pumpswap",
      "action": "remove",
      "instruction": "withdraw",
      "instruction_kind": "remove",
      "event": true,
      "event_reason": null,
      "pool": "Gf7h...2kLm",
      "pool_kind": "authority",
      "pool_authority": "Gf7h...2kLm",
      "pool_model": "constant_product",
      "mints": [
        {
          "mint": "Cgxx...pump",
          "amount_raw": "412000000000",
          "decimals": 6,
          "side": "out",
          "native": false,
          "vault": "7Tq1...aa3F"
        },
        {
          "mint": "So11...1112",
          "amount_raw": "38100000000",
          "decimals": 9,
          "side": "out",
          "native": false,
          "vault": "Bn4d...Qz8e"
        }
      ],
      "lp_mint": "Lp9k...4rTs",
      "lp_amount_raw": "125000000000",
      "lp_kind": "lp_token",
      "owner": "9xQe...Vf2L",
      "owner_source": "counterparty",
      "amount_basis": "transfers",
      "single_sided": false,
      "reserves_before": [
        {
          "mint": "Cgxx...pump",
          "vault": "7Tq1...aa3F",
          "amount_raw": "1210000000000",
          "decimals": 6,
          "native": false
        },
        {
          "mint": "So11...1112",
          "vault": "Bn4d...Qz8e",
          "amount_raw": "112000000000",
          "decimals": 9,
          "native": false
        }
      ],
      "reserves_after": [
        {
          "mint": "Cgxx...pump",
          "vault": "7Tq1...aa3F",
          "amount_raw": "798000000000",
          "decimals": 6,
          "native": false
        },
        {
          "mint": "So11...1112",
          "vault": "Bn4d...Qz8e",
          "amount_raw": "73900000000",
          "decimals": 9,
          "native": false
        }
      ],
      "share_of_reserves": 0.340495,
      "depth_effect": {
        "basis": "vault_reserves"
      },
      "material": true,
      "lp": "burn",
      "liquidity_version": 1
    },
    "ts": 1712160000000
  },
  "_liquidity": "Liquidity events (2026-09-23, opt-in, liquidity_version 1). Add liquidity:true to a subscribe (dex:liquidity frames in addition to the trade view) or liquidity:\"only\" (liquidity frames only; cannot be combined with legs). One dex:liquidity frame per liquidity instruction: action pool_created | add | remove, id <signature>:<ix>[.<inner>] (stable live and on replay; dedupe by (sub_id, id)), program, venue, instruction, pool + pool_kind, pool_model, mints[] with raw amount_raw and side in|out relative to the pool, lp_mint / lp_amount_raw / lp_kind, owner (the wallet or router that funded an add or received a remove) + owner_source, amount_basis transfers | vault_delta | ambiguous (ambiguous = amounts null, never guessed), reserves_before[] / reserves_after[] (raw vault balances), share_of_reserves (constant-product pools only), depth_effect, material (a removal of at least 25 % of reserves). Filters: token_mint(s), wallet(s), pool(s), dex, program (one is required with \"only\"), actions, min_share_of_reserves, material_only; trade-only filters such as min_sol never gate a liquidity event. Only instructions proven by a real transaction fixture are emitted (the subscribed ack lists liquidity_coverage.instructions with emits_events); a recognised but unverified instruction, and every fee or reward claim, stays on dex:route.liquidity_actions with event:false. Limits: concentrated pools (Raydium CLMM, Orca Whirlpool, Meteora DLMM) report share_of_reserves null and depth_effect unknown because tick and bin ranges are not decoded; Meteora DAMM v1, Raydium LaunchLab and Moonshot are not emitted; block_time is the receive clock, as on dex:trades; there is no USD field and min_usd is rejected. Recovery: replay from the in-memory buffer only (replay_done adds liquidity.captured_since); there is no durable resume for this view. Never an input to prices, candles or volume."
}
GET/stream/sessionsPRO

List Active Stream Sessions

List your live WebSocket sessions across both stream servers (event stream + DEX firehose). Reflects in-memory connection state, not historical logs, so every id returned can be passed to DELETE /stream/sessions/{id} to free that slot. Use this when a redeploy or process restart on your side leaves a half-open socket holding a connection slot and new connections are rejected with code 4002 (connection limit reached). Pro/Ultra.

Example Response

{
  "sessions": [
    {
      "id": "48213",
      "service": "ws-streaming",
      "tier": "ULTRA",
      "channels": [
        "kol:trades"
      ],
      "connected_at": "2026-06-29T19:42:11Z",
      "remote_ip": "203.0.113.7",
      "messages_sent": 142
    },
    {
      "id": "48217",
      "service": "dex-stream",
      "tier": "ULTRA",
      "channels": [
        "dex:trades"
      ],
      "connected_at": "2026-06-29T19:43:02Z",
      "remote_ip": "203.0.113.7",
      "messages_sent": 5310
    }
  ],
  "count": 2
}
DELETE/stream/sessions/{id}PRO

Terminate a Stream Session

Force-close one of your own live WebSocket sessions and release its connection slot immediately — the self-serve fix for a 4002 lockout after a deploy overlap (e.g. an old + new instance briefly running at once). The {id} is from GET /stream/sessions; you can only terminate your own sessions. The socket is closed with code 4002. Returns 404 if no live session with that id belongs to your key. Pro/Ultra.

Parameters

NameTypeDefaultDescription
idpath paramrequiredSession id from GET /stream/sessions

Example Response

{
  "evicted": true,
  "id": "48213"
}

Reference

Tiers, errors, SDKs, FAQ.

The boring but useful.

Deployer tiers

How we classify deployers.

Bond rate is the headline outcome: percent of launched tokens that graduate the bonding curve.

TierCriteriaAlert bond rate
Elite5+ deploys, 5+ bonds, 40%+ lifetime, 50%+ recent~56%
Good3+ deploys, 3+ bonds, 25%+ lifetime, 30%+ recent~17%
Rising1–3 deploys with 100% bond rateVaries
ModerateLower rates, not tracked for alerts—
ColdLast 10 outcomes all failed—

Errors

Status codes and bodies.

All errors return JSON with an error string. Rate-limit headers ship on every response.

401 Unauthorized

Missing or invalid API key.

{"error": "Unauthorized"}
403 Forbidden

Valid key but your tier doesn't have access to this endpoint.

{"error": "This endpoint requires PRO or ULTRA tier"}
422 Unprocessable Entity

Invalid request parameter (bad wallet address, out-of-range limit, etc.).

{"error": "Invalid wallet address"}
429 Too Many Requests

Rate limit hit. Check X-RateLimit-Remaining and retry after X-RateLimit-Reset.

{"error": "Rate limit exceeded. Resets at 2026-04-12T15:00:00Z"}
500 Internal Server Error

Something went wrong on our side. Check /api/v1/status for service health.

{"error": "Internal server error"}

Rate-limit headers on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (Unix timestamp).

Versioning

What we will and won't change.

Every endpoint lives under /v1. Here is exactly what that promise means.

Additive by default

New endpoints and new optional response fields ship within v1 without prior notice. Write parsers that tolerate unknown fields — that's the only forward-compatibility requirement we place on you.

No in-place breaking changes

Within v1, existing response fields never change type or meaning, and documented fields don't disappear. A change that would break a working integration ships as a new endpoint or a new version prefix — never as a mutation of a route you already depend on.

30-day deprecation window

If a v1 endpoint or field must be retired, you get at least 30 days' notice via the changelog and an email to every API key that called it in the preceding 90 days. The endpoint keeps working through the entire window.

Where changes land

Every API change — additive or deprecating — is recorded in the changelog. The machine-readable GET /api/v1/openapi.json spec and GET /api/v1/postman.json collection are regenerated with each release, so codegen pipelines can diff them.

SDKs

Install once. Forget the protocol.

TypeScript, Python and Rust for the REST API (the Python client ships in madeonsol-x402 and auto-detects an msk_ key). TypeScript and Python for keyless x402. MCP, ElizaOS and Solana Agent Kit packages for agents. A parallel robinhood-chain-* family covers /rhc/*.

TypeScript · npmopen →
$ npm install madeonsol
Typed REST client. Works in Node, Bun, Deno, and edge runtimes. madeonsol-x402 is the agent companion.
Python · PyPIopen →
$ pip install madeonsol-x402
Keyless x402 agent SDK with LangChain and CrewAI toolkits, plus a keyed REST client (MadeOnSolClient(api_key='msk_…')) for every /api/v1 endpoint. Sync + async.
Rust · crates.ioopen →
$ cargo add madeonsol
Fully typed REST client built on tokio + reqwest. Same endpoint surface, same msk_ auth.

FAQ

Quick answers.

Anything missing? Email [email protected].

How do I authenticate?+
Send Authorization: Bearer msk_… on every request. The key is generated at /developer — sign in with email or Google, no payment to start. AI agents that don't have an account can pay per call via /x402.
What are the rate limits?+
Free: 200 calls/day, 60/min burst. Pro: 10,000/day, 300/min. Ultra: 100,000/day, 600/min. On 429 we return X-RateLimit-Reset so your client can back off precisely. Daily counters reset at midnight UTC.
Should I poll the REST endpoint or subscribe to WebSocket?+
For dashboards, batch jobs, or anything human-paced, REST is fine — on paid tiers the cache is 5–15 s behind realtime (free-tier live feeds run 5 min behind). For trading bots and agents, use WebSocket or webhooks (Pro/Ultra) — events arrive within ~1–2 s of the on-chain swap.
How do I verify a webhook delivery?+
Every delivery includes X-MadeOnSol-Signature (HMAC-SHA256 of <timestamp>.<raw-body>). Hash the raw body — NOT the parsed JSON — with your webhook secret and compare with timingSafeEqual. See the payload format section for a Node verifier.
Does the free tier ship a downgraded payload?+
No. Every tier returns the full REST response shape — real wallets, full tx signatures, full precision. Paid gates are per-user infra (webhooks, WebSockets, rule engines), ULTRA-only data depth (bot signals, full pagination, cap-table top 20, all-DEX firehose), and freshness: live feeds are delayed 5 minutes on Free (real-time on PRO+ and x402) — delayed responses carry delay and as_of.
How do I pick between TypeScript, Python, and Rust?+
REST API: TypeScript (npm i madeonsol) or Rust (cargo add madeonsol). x402 agents: TypeScript or Python (pip install madeonsol-x402) — both ship LangChain and CrewAI toolkits, and the Python package doubles as the keyed REST client (pass api_key="msk_…" and it calls /api/v1 directly). Agents: MCP server, ElizaOS plugin and Solana Agent Kit plugin. Robinhood Chain has its own robinhood-chain-* family of seven packages for /rhc/*.
What's the WebSocket reconnect behavior?+
The server sends a 15-second heartbeat; if you miss two in a row, reconnect. Your stream token does not expire (since 2026-08-27), so reconnect with the same value — calling POST /stream/token again returns it unchanged. A 4001 close means the token really is invalid (subscription lapsed, or you rotated it, or your API key was revoked or rotated): mint again and reconnect. Subscriptions are not restored across reconnects: re-send the subscribe message with resume: {instance, seq, ts} taken from the last frame your handler finished processing. The server re-sends what you missed from memory, or, after a server restart, rebuilds it from storage (up to 60 minutes, 2,000 rows per channel), stamped replayed:true and bracketed by replay_start / replay_end, before live delivery resumes; replay_end says per channel what could not be recovered. Delivery is at-least-once, so dedupe by id. Gaps in seq are normal (one counter across all channels and customers) and are not a sign of loss. The older replay_since_seq / replay_since_ts fields still work, from memory only. The DEX firehose uses its own replay: N parameter instead.
Can I get historical data?+
KOL trades and deployer alerts are retained indefinitely; alpha scores recomputed nightly. Use before cursors on the time-series endpoints to page back through full history. Leaderboard and PnL rankings aggregate selectable windows up to 180 days. For bulk historical backfills email [email protected].

Ready when you are

Get a free key. Ship the bot. Upgrade when it works.

200 calls/day, no payment to start. Pay by card, USDC, or SOL when you outgrow it.

Get free API key View pricing API status