Protocol and channel list verified 2026-09-22 against the live registry.
Solana + Robinhood Chain API · real-time
One socket at wss://madeonsol.com/ws/v1/stream pushes KOL trades, deployer alerts, pre-confirmation deploys, price ticks, token surges and Robinhood Chain events the moment they are confirmed. Every event frame carries a sequence number and a stable id, a client that reconnects, even after a server restart, can resume up to 60 minutes of what it missed, and pushed events never spend your daily quota.
Heartbeat every 15 s · replay buffer 20,000 frames · slots PRO 2 / ULTRA 3 / BUSINESS 10 · stream token never expires
The stream
Counted from the live channel registry.
16 Solana · 15 RHC
ghosts reaped in ≤ 30 s
from storage · ~6-8 min in memory
pushed events are free
Why stream
A poller that asks every second spends 86,400 calls a day to learn about a few hundred events. A stream delivers each event once, when it happens, and the delivery is not a request.
Quota
Latency
Recovery
resume and gets the missed frames back, from memory or from storage after a server restart (up to 60 min), before live frames resume. replay_end says per channel what could not be recovered.Channels
Solana and Robinhood Chain channels ride the same socket and the same connection slots — subscribe to a mix in one message. A channel without an explicit gate is open to any tier that can mint a stream token (PRO and above). User-scoped channels deliver only your own rules' fires. The Resume column says what a resume can rebuild from storage after a server restart.
Solana (16)
| Channel | Events | What you get | Scope | Gate | Resume |
|---|---|---|---|---|---|
| kol:trades | kol:trade | Every buy/sell from tracked KOL wallets, with market cap and USD price at trade time. | broadcast | PRO+ | partial (no slot, fdv, liquidity, pool) |
| kol:coordination | kol:coordination | Fires from your own coordination alert rules: multi-KOL convergence on one token with a 0-100 score. | user-scoped | PRO+ | partial (no kols[]) |
| kol:first_touches | kol:first_touch | First tracked-KOL buy on a token — the scout signal, filterable by scout tier. | broadcast | PRO+ | full |
| deployer:alerts | deployer:alert · deployer:bond | Tracked-deployer launches and graduations with reputation fields. | broadcast | PRO+ | partial (new deploys lack tx and dev-buy fields) |
| wallet_tracker:events | wallet_tracker:event | Swaps and transfers on the wallets in your own watchlist. | user-scoped | ULTRA+ | full |
| copytrade:signals | copytrade:signal | Fires from your own copy-trade rules. | user-scoped | PRO+ | full |
| price_alert:events | price_alert:dip · price_alert:recovery | Your own market-cap dip / recovery alerts, evaluated every 250 ms on Solana. | user-scoped | PRO+ | full |
| sniper:deploys | sniper:deploy | Pre-confirmation pump.fun deploys from deshred; PRO receives elite/good deployers only. | broadcast | ULTRA+ | full |
| token:graduations | token:graduation | Every pump.fun graduation, tracked deployer or not. | broadcast | PRO+ | in-memory buffer only |
| token:prices | token:price | Per-mint price / MC ticks (~250 ms coalesced) for the mints you name. | mint-scoped | PRO+ | current price snapshot |
| token:locks | token:lock (+ lifecycle, opt-in) | New Streamflow / Jupiter Lock / Bonfida lock or vesting contracts. With filters.lifecycle: true also claims, cancels, closes, top-ups / extensions and the unlock schedule (upcoming within 24 h, available = claimable per the schedule, not claimed). Keeper-cranked automatic claims are hidden unless you ask for them. | broadcast | PRO+ | full (lifecycle events too, with filters.lifecycle) |
| token:fee_claims | token:fee_claim | pump.fun creator-fee distributions, social-handle claims, config changes. | broadcast | PRO+ | full |
| token:surges | token:surge · token:revival | Token momentum fires with risk flags — see /surges. | broadcast | PRO+ | full |
| token:candles | candle:closed (+ candle:update, opt-in) | Live 1-minute candles for the mints you name: each closed minute as it is written to our candle table (open/high/low/close price and market cap, volume, trade counts), usually 10–25 s after the minute ends. With filters.updates: true also the minute in progress, at most once per mint per second. Fully flat minutes with no trades are not sent. | mint-scoped | PRO+ | closed candles full, up to 10,000 rows; in-progress updates are not replayed |
| token:risk | risk:authority_changed · risk:supply_inflated (+ risk:inputs snapshot) | Changes to the stored risk INPUTS of the mints you name: a mint or freeze authority revoked, a Token-2022 transfer fee changed, the first supply-inflation crossing (0.5 % / 5 %). A snapshot of the current inputs arrives on subscribe. Not a risk-band stream: the band moves with price and is computed by GET /tokens/{mint}/risk. | mint-scoped | PRO+ | full, plus a snapshot of the current inputs |
| wallet:scores | deployer:tier_changed · kol:score_state_changed | Tier changes of the Solana deployers you name (including an unranked wallet entering a ranked tier) and categorical state changes of the KOLs you name (cold, heating up, strategy tag). Every frame carries source and computed_at: a KOL change means the recompute at that time found a new value, not that it changed at that moment. | wallet-scoped | PRO+ | full (deployer tiers + KOL state, one row budget) |
Robinhood Chain (15)
| Channel | Events | What you get | Scope | Gate | Resume |
|---|---|---|---|---|---|
| rhc:kol_trades | rhc:kol_trade | Tracked-KOL trades on Robinhood Chain (EVM-native fields). | broadcast | PRO+ | full |
| rhc:dex_trades | rhc:dex_trade | Robinhood Chain DEX firehose, token-attributed trades (Uniswap v2/v3/v4 + launchpads), ~40–55 trades/s at tip. Pair with rhc:dex_trades_unattributed for full chain coverage. | broadcast | ULTRA+ | partial (no liquidity_usd, quote.usd, quote.observed_at), last 10 min, up to 10,000 rows |
| rhc:dex_trades_unattributed | rhc:dex_trade_unattributed | The additive complement to rhc:dex_trades — trades where no single side could be named the token (e.g. WETH/USDG). Raw token_in/token_out/amount_in/amount_out, no decimals or buy/sell. Subscribe to both for full chain coverage. | broadcast | ULTRA+ | partial (no liquidity_usd), last 10 min, up to 10,000 rows |
| rhc:new_tokens | rhc:new_token | Fires once per RHC token, the moment its symbol/name/decimals resolve on-chain — not on first trade. | broadcast | ULTRA+ | in-memory buffer only |
| rhc:copytrade:signals | rhc:copytrade:signal | Fires from your own RHC copy-trade rules. | user-scoped | PRO+ | partial (no traded_at) |
| rhc:price_alert:events | rhc:price_alert:dip · rhc:price_alert:recovery | Your own RHC price alerts. Event-driven off the rhc:dex_trade feed (a few seconds, not the 250 ms Solana loop), with table polls and a tape replay as safety nets. | user-scoped | PRO+ | full |
| rhc:kol:coordination | rhc:kol:coordination | Your own RHC coordination rules. | user-scoped | PRO+ | partial (no market_cap_usd) |
| rhc:kol:first_touches | rhc:kol:first_touch | First tracked-KOL buy per RHC token. | broadcast | PRO+ | full |
| rhc:token_locks | rhc:token_lock (+ unlock schedule, opt-in) | New Robinhood Chain token lock / vesting contracts, one event per lock created. With filters.lifecycle: true also the unlock schedule (upcoming within 24 h, available = claimable per the schedule, not claimed). Claims, extensions and cancels are not observable on RHC. | broadcast | PRO+ | partial (no family_name, amount, amount_pct_of_supply); unlock-schedule events full |
| rhc:token_prices | rhc:token_price | Per-token Robinhood Chain price ticks for the addresses you name: one snapshot per address on subscribe, then updates derived from the RHC trade feed (at most one per address per 250 ms, latest value), each stamped quality fresh / stale / unreliable with a reason. | address-scoped | PRO+ | current price snapshot |
| rhc:lp_events | rhc:lp_event | Robinhood Chain liquidity events on the pools we track: adds, removals and pool creations, with the position's tick range, whether it was in range of the current price, its share of active liquidity (v3/v4) or of reserves (v2), and a material flag for removals of 25 % or more. The in-range and share fields are null when the pool's current tick was not known; the provider is usually a router or position manager. | broadcast | ULTRA+ | last 60 min, up to 10,000 rows (token symbol/decimals approximate on replay) |
| rhc:token_candles | rhc:candle_closed · rhc:candle_revised (+ rhc:candle_update, opt-in) | Live 1-minute Robinhood Chain candles for the addresses you name. A stored candle that is rewritten later (a restart merge or a spoofed-pool repair) is re-sent as rhc:candle_revised with a revision number. filters.updates: true adds the minute in progress, at most once per address per second. | address-scoped | PRO+ | closed candles full (latest revision only), up to 10,000 rows; in-progress updates are not replayed |
| rhc:token_risk | rhc:risk_verdict_changed (+ rhc:risk_verdict snapshot) | A recheck stored a different contract-risk verdict for an RHC token you name (sellable, proxy / upgradeable, owner model, mint / pause, LP custody, flags), with before / after. Detection is by a recheck sweep: the change happened somewhere between previous_checked_at and checked_at, currently days to weeks apart. Score is higher = safer. | address-scoped | PRO+ | full, plus a snapshot of the current verdict |
| rhc:wallet_scores | rhc:deployer_tier_changed | Robinhood Chain deployer tier changes (elite / good / spammer / neutral) for the 0x deployers you name, found by the 5-minute ranking refresh — recomputed at computed_at, not changed at that moment. | wallet-scoped | PRO+ | full |
| rhc:dev_activity | rhc:dev_activity (dev_buy · dev_sell) | The recorded developer of a Robinhood Chain token buying or selling it, from the launchpad creation or (labelled pool_creator) the first pool's creator. Buys and sells only: a developer moving tokens to another wallet is never on this channel, and a developer trading from a different wallet is not linked. Live since 2026-10-05; a reconnect replays only events still in memory. | broadcast | ULTRA+ | in-memory buffer only (no durable store yet) |
RHC frames carry EVM-native fields (lowercase 0x addresses, eth_amount, tx_hash) — do not reuse a Solana deserializer unchanged. The Solana all-DEX firehose (14 programs) is a separate endpoint, wss://madeonsol.com/ws/v1/dex-stream, on Ultra and Business; what teams build on it is covered under real-time DEX data. Since 2026-09-22 it also serves a per-pool view: subscribe with legs: true and each transaction arrives as one dex:route (hops, shape, decoded_complete, the programs we could not decode, the signer's net) plus one dex:leg per pool swap (program, venue, pool, vaults, exact raw amounts in and out, a stable leg_id of signature:instruction[.inner]), and the unchanged dex:trades frame once. Liquidity deposits and withdrawals are never a leg: since 2026-09-23 they have their own opt-in view, liquidity: true (or "only"), one dex:liquidity frame per pool creation, add or remove with raw amounts, vault reserves before and after, the share of reserves on constant-product pools and a material flag for removals of 25 % or more. Only instructions verified against a real transaction are emitted; concentrated pools report depth as unknown, there is no USD value, and replay comes from the in-memory buffer only. Protocol in the API docs.
ShredPrism (ULTRA+) uses a separate low-latency endpoint, wss://madeonsol.com/ws/v1/early, advertised as early_ws_url by the same stream-token call. It serves six supported outer-instruction families: early:deploys, early:locks, early:trades, early:liquidity, early:migrations and early:token_changes. Observations are provisional instruction intent; execution outcomes follow separately. Exact per-family fields, supported instructions, recovery and filters are in the ShredPrism contract, with measured client-side benchmarks on the solution page.
Since 2026-10-05 the DEX socket also carries realtime developer activity: send {"type":"dev_subscribe","filters":{"token_mints":[],"deployers":[],"types":[]}} and receive dev:activity when an attributed token's developer sells, buys or moves their own token (dev_sell, dev_buy, dev_token_transfer_out, dev_token_transfer_in; a transfer is never a sell), followed by dev:activity_enrichment with the same id. Transfer detection is the union of the legacy bounded wallet watch and the broad SPL Token/Token-2022 candidate source for attributed creators while that source is live. transfer_watch_coverage describes only the legacy watch, not total transfer coverage; the ack's transfer_sources reports broad-source state/gaps. Missing creator attribution, recorded source gaps and unsupported mixed swap+standalone-transfer cases can still produce misses. PRO+ can receive the same direct-developer events through the HMAC-signed dev:activity webhook; ULTRA+ gets the low-latency DEX-socket path and identity stitching. Also since 2026-10-05, swaps paid in USDC or USDT are sized by their stable leg on dex:trades: sol_amount is the SOL equivalent, with sol_amount_basis and stable_quote describing how it was derived.
Protocol
Everything a reconnect loop needs to know, in the order it will meet it.
Ordering
seq is one ordinal per server process, shared by all channels and all customers and assigned before your filters run, so gaps in the seq you receive are normal and are not evidence of loss. id is a stable identity for dedupe across reconnects, derived from the transaction signature or hash where the payload has one. token:price ticks carry neither. The connected frame carries the current seq, an instance id and the replay window; if the instance changes the server restarted and seq reset, so never compare seq across instances. The same event keeps the same id live, from memory and from storage: delivery is at-least-once, so dedupe by id.Resume
resume: {instance, seq, ts}, the last frame your handler finished. Same instance and inside the 20,000-frame buffer (~6-8 min): re-sent from memory. Otherwise each channel is rebuilt from storage from ts (up to 60 min, 2,000 rows per channel, 20,000 total) as seq: null, mode: "durable" frames; channels with no stored source get an explicit gap. replay_end reports sent, complete, retryable, a reason and a watermark per channel. Commit your cursor only on complete: true or on final gaps; after a retryable incomplete recovery, resume again from the old cursor. Recovery is bounded, never a completeness guarantee. The older replay_since_seq / replay_since_ts fields still work, from memory only.Liveness
{"type":"heartbeat"} frame plus a protocol ping every 15 s; a socket that does not pong by the next tick is closed 1006 ping-timeout, so a half-open ghost is gone within ~15–30 s. Miss two heartbeats: reconnect and resume.Connection slots
4002 naming how long the holder has been connected; GET /api/v1/stream/sessions lists your live sessions and DELETE /api/v1/stream/sessions/{id} frees a slot yourself. The DEX firehose has its own slots (ULTRA 2, BUSINESS 5).Named subscriptions
sub_id opens a subscription with its own channels and filters on the same socket; update, unsubscribe and list address it by that id. Frames under it carry sub_id; an event matching several subscriptions is delivered once per subscription (dedupe by sub_id + id). The cap counts the default subscription too; above it the subscribe is refused with too_many_subscriptions.Credential
POST /api/v1/stream/token returns the same token on every call; expires_at is always null. It ends only when the plan lapses (cut within ~6 min) or you send {"rotate":true} — the old value then works for 60 s and live sockets get a token_refresh frame. Present as Authorization: Bearer (preferred) or ?token=, masked in our access logs. A 4001 means mint again, never a timer.Subscribe
{"type":"subscribe","channels":[...],"filters":{...}} after connect; the server sends a hint frame after 10 s if no channel is active. Filters are server-side and connection-wide: one filter object applies to every channel on the socket (a later subscribe with filters replaces it), so {"action":"buy"} also drops deployer alerts, whose payload has no buy action. Use a second connection for channels that need different filters. A rejected channel comes back in channels_rejected with the reason, never a silent partial subscribe.Integration
curl for the token, wscat for the socket, one JSON line to subscribe. The SDKs wrap the same three steps with auto-reconnect and typed events.
TOKEN=$(curl -s -X POST https://madeonsol.com/api/v1/stream/token -H "Authorization: Bearer msk_YOUR_KEY" | jq -r .token)
wscat -c wss://madeonsol.com/ws/v1/stream -H "Authorization: Bearer $TOKEN"
> {"type":"subscribe","channels":["kol:trades","sniper:deploys","token:surges"],"filters":{"min_sol":1}}{"type":"connected","seq":48211,"instance":"a1b2c3d4e5f6","replay":{"oldest_seq":28212,"newest_seq":48211,"size":20000}}
{"type":"subscribed","channels":["kol:trades","sniper:deploys","token:surges"],"seq":48211}
{"channel":"kol:trades","event":"kol:trade","seq":48212,"id":"kol:trade:5Kd…","data":{...},"ts":1756382400123}
{"type":"heartbeat","ts":1756382415123}
// reconnect later with the last frame you processed:
{"type":"subscribe","channels":["kol:trades"],"resume":{"instance":"a1b2c3d4e5f6","seq":48212,"ts":1756382400123}}
{"type":"subscribed","channels":["kol:trades"],"resume":{"instance":"a1b2c3d4e5f6","seq":48212,"ts":1756382400123,"accepted":true},...}
{"type":"replay_start","mode":"ring","count":37,"replay_truncated":false,...}
{"type":"replay_end","sent":37,"matched":37,"complete":true,"reason":null,"live_from_seq":48290,"channels":{"kol:trades":{"mode":"ring","sent":37,"matched":37,"complete":true}},...}import { MadeOnSol } from "madeonsol";
const client = new MadeOnSol({ apiKey: "msk_YOUR_KEY" });
const stream = await client.stream.connect(); // getToken() on every (re)connect, auto-backoff
stream.on("kol:trade", (t) => console.log(t.token_symbol, t.action));
stream.on("token:surge", (e) => console.log(e.tier, e.symbol, e.risk_flags));from madeonsol_x402 import MadeOnSolClient
client = MadeOnSolClient(api_key="msk_YOUR_KEY")
stream = client.stream()
@stream.on("kol:trade")
async def on_trade(t): print(t["token_symbol"], t["action"])The alternative
Serverless, cron-shaped or behind a strict egress policy: register a URL instead. The registry accepts 11 event types; rule engines (copy-trade, price alerts, coordination, first-touch) deliver from the rule's own URL with a per-rule secret.
Events
Delivery
x-madeonsol-signature. 3 retries at 5 s / 30 s / 2 min. Auto-disabled after 10 consecutive failures — and the owner is emailed, not just us. A new webhook starts receiving within ≤ 15 s.Limits
Honest limits
Read before you design around it.
token:prices
filters.mints is required; a subscribe above the cap is rejected, not truncated. Ticks are ~250 ms coalesced pricing updates, not per-trade — per-trade is the ULTRA firehose.Resume depth
missing) and two, token:graduations and rhc:new_tokens, only from memory. Past that, backfill from REST. A row is stamped when it is written, not when it commits, so the server holds your committable position a few seconds back and re-scans the last minute on the next resume: a write that commits more than about a minute after it was stamped can still be missed (about 6 minutes while a long-running transaction has the hold-back capped), and the RHC DEX trade channels are bounded by the producer's 600 s freshness rule. Each channel states its own bound in watermark.guarantee. For hours of replay on raw chain data use gRPC from an RPC provider (Helius publishes 24 h) and decode yourself.RHC price alerts
PRO curation
Pricing for context: PRO €43/mo, ULTRA €131/mo (adds the all-DEX firehose), BUSINESS €400/mo (embed license, 10 slots). Competitors' parsed WebSocket starts at $199 (Birdeye), $350 (Codex) and €397 (Solana Tracker), verified 2026-08-16. Showing these feeds to your own users is covered in the data behind a terminal's chart, candles and trade tape.
FAQ
More for developers
ShredPrism stream
Six early Solana families, private wallet lists and transparent benchmarks. ULTRA+.
Token surge & revival alerts
Momentum fires with risk flags and out-of-sample +1h outcomes.
Early launch signals
ULTRA+ ShredPrism signals for supported pump.fun and LaunchLab instructions, with execution outcomes reported separately.
MCP servers & SDKs
Two MCP servers, 14 packages, one free key.
Full surface: Solana API overview, Robinhood Chain API, endpoint docs and the 9-provider data API comparison.
Start building
31 channels from PRO at €43/month; the all-DEX firehose from ULTRA at €131/month. Pushed events never spend quota.