{"openapi":"3.1.0","info":{"title":"MadeOnSol — Robinhood Chain API","version":"1.20.0","description":"Robinhood Chain (chain id 4663) endpoints: live KOL trades, token discovery & bundles, the DEX trade tape, and OHLC candles — from our self-hosted node. Same API key, same base URL, bundled into every tier at no extra cost.","contact":{"name":"MadeOnSol","url":"https://madeonsol.com/contact"},"license":{"name":"Proprietary","url":"https://madeonsol.com/terms"}},"servers":[{"url":"https://madeonsol.com/api/v1","description":"Production"}],"tags":[{"name":"Robinhood Chain","description":"Robinhood Chain (chain id 4663) coverage — same intel, EVM-native contracts (0x addresses, eth_amount, tx_hash). Bundled into existing tiers at no extra cost."}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"msk_...","description":"Get a free API key at https://madeonsol.com/developer"}},"schemas":{"RhcHolderGrowthWindow":{"type":"object","nullable":true,"description":"One holder-growth window on /rhc/tokens/{address}/holders. Pools and burn addresses are excluded from every count.","properties":{"cutoff_block":{"type":"integer","nullable":true,"description":"Lowest block observed at-or-after now()−window (resolved from our trade ingest, ~10 blocks/s)."},"entered":{"type":"integer","nullable":true,"description":"Addresses whose first Transfer of this token landed at-or-after cutoff_block (any current balance)."},"entered_still_holding":{"type":"integer","nullable":true,"description":"entered ∩ balance > 0."},"exited":{"type":"integer","nullable":true,"description":"Pre-existing holders whose last Transfer in the window left them at zero."},"net":{"type":"integer","nullable":true,"description":"entered_still_holding − exited ≈ change in holder_count over the window."}}},"RhcTokenRiskSummary":{"type":"object","nullable":true,"description":"Precomputed risk summary for a Robinhood Chain token, from the same engine as `/rhc/tokens/{address}/risk` (proxy resolution, capability scan, and a live router sell-simulation).\n\n**`null` means NOT ASSESSED, not safe.** The sweep covers tokens with liquidity on a ~24h rotation, so a brand-new or illiquid token has no row yet.\n\nThese values are a SNAPSHOT — always read `checked_at`. Sellability can change the moment an owner flips a setting, which is why `/rhc/tokens/{address}/risk` is computed live and never served from this cache. Use this to triage a feed; use the live endpoint before acting on a single token.","properties":{"sellable":{"type":"string","nullable":true,"enum":["yes","no","unknown"],"description":"`no` means a sell was simulated through the router and REVERTED — bought-but-cannot-sell."},"upgradeable":{"type":"boolean","nullable":true,"description":"Token is a proxy whose implementation can be swapped (EIP-1967 / beacon / legacy). EIP-1167 minimal proxies are NOT upgradeable — the target is baked into immutable code."},"score":{"type":"integer","nullable":true,"description":"0–100, conservative. Absence of evidence is not evidence of safety."},"checked_at":{"type":"string","format":"date-time","description":"When this assessment was computed."}}},"TokenBundle":{"type":"object","properties":{"mint":{"type":"string"},"bundle":{"type":"object","properties":{"wallet_count":{"type":"integer","description":"Number of same-slot bundle wallets (is_bundle: ≥3 buying in one slot)"},"bundle_kind":{"type":"string","enum":["atomic_tx","same_slot","none"],"description":"atomic_tx = ≥3 wallets share one buy tx (definitively atomic); same_slot = the ≥3-same-slot heuristic (possible coincidence); none = no cohort"},"held_pct_of_supply":{"type":"number","nullable":true,"description":"HEADLINE. Cohort net held ÷ circulating supply, 0–1 (clamped). null when supply is unknown"},"held_ratio":{"type":"number","nullable":true,"description":"Cohort net held ÷ buy_volume, 0–1. Churn-sensitive — secondary to held_pct_of_supply"},"fully_exited":{"type":"boolean"},"buy_volume":{"type":"number","description":"Cumulative buy-side token volume — NOT distinct tokens; can exceed supply on round-tripping"},"tokens_held":{"type":"number","description":"Swap-derived net position (Σbuys−Σsells) — a proxy for on-chain balance, not a holder census"},"holdings_basis":{"type":"string","enum":["swap_only","swap_and_transfers"],"description":"swap_only = token transfers are not applied: a member that transferred tokens out and sold elsewhere still reads as holding."},"bundle_detection":{"type":"string","enum":["same_batch_block_time_second"],"description":"How cohort membership is decided today: ≥3 wallets buying the mint in one ingest batch with the same block_time second (ingest wall-clock), not the same slot. A future value `same_slot` ships with BUNDLE_SLOT_DETECTION=on."}}},"wallets":{"type":"array","description":"BASIC: empty. PRO: top-10, flags only. ULTRA: full cohort + identity fields.","items":{"type":"object","properties":{"rank":{"type":"integer"},"wallet":{"type":"string"},"held_ratio":{"type":"number","nullable":true},"has_sold":{"type":"boolean"},"atomic":{"type":"boolean","description":"This wallet is part of an atomic single-tx bundle"},"is_kol":{"type":"boolean"},"kol_name":{"type":"string","nullable":true,"description":"ULTRA only"},"win_rate":{"type":"number","nullable":true,"description":"ULTRA only, 0–1"},"bot_confidence":{"type":"string","nullable":true,"description":"ULTRA only"},"tokens_held":{"type":"number","description":"ULTRA only"},"balance_now":{"type":"object","nullable":true,"description":"Only with include_balances=true: this wallet's current balance of the mint (null when the cohort read failed).","properties":{"amount_raw":{"type":"string"},"decimals":{"type":"integer","nullable":true},"amount":{"type":"string"},"holding":{"type":"boolean"},"token_accounts":{"type":"integer"},"slot":{"type":"integer"}}}}}},"held_now":{"type":"object","description":"Only with include_balances=true (PRO+, 2026-10-15): the cohort's CURRENT balances, one owner read per wallet (every token account of the owner for the mint, either program). Totals only when every wallet was read; the bundle answer itself never fails on a balance read.","properties":{"source":{"type":"string","enum":["solana_rpc_getTokenAccountsByOwner"]},"checked_at":{"type":"string","format":"date-time"},"wallets":{"type":"integer"},"verified_wallets":{"type":"integer"},"holding_wallets":{"type":"integer"},"complete":{"type":"boolean"},"incomplete_reason":{"type":"string","nullable":true},"slot_min":{"type":"integer","nullable":true},"slot_max":{"type":"integer","nullable":true},"tokens_held_raw":{"type":"string","nullable":true},"tokens_held":{"type":"string","nullable":true},"held_pct_of_supply":{"type":"number","nullable":true,"description":"RATIO in [0, 1] of circulating_supply_raw, like bundle.held_pct_of_supply."},"supply_basis":{"type":"string","nullable":true,"enum":["circulating_supply_raw",null]}}},"coverage":{"$ref":"#/components/schemas/TradeCoverage"}}},"Error":{"type":"object","description":"Generic error envelope. `error` is always present (SDKs match on it). Errors returned after authentication also carry `_rid` and, on paid tiers, `support`; authentication-stage errors (missing/invalid key, origin) carry neither.","properties":{"error":{"type":"string","description":"Error message or machine code (e.g. `tier_required`, `rate_limit_exceeded`). Never changed once shipped."},"message":{"type":"string","description":"Human-readable explanation, when `error` is a machine code."},"code":{"type":"string","description":"Machine-readable sub-code on some errors (e.g. `invalid_query`, `invalid_wallet`, `origin_not_allowed`)."},"error_kind":{"type":"string","description":"Machine-readable category on some errors (e.g. `statement_timeout`, `concurrency`, `daily`)."},"detail":{"type":"string","description":"Extra human-readable context."},"hint":{"type":"string"},"retry_after_seconds":{"type":"number","description":"When present on a 429/503, the same value is sent as the `Retry-After` header."},"signup_url":{"type":"string","format":"uri","description":"On the missing-key / bad-format 401: where to get a free key."},"docs_url":{"type":"string","format":"uri"},"support":{"type":"string","description":"Paid tiers, errors after authentication: priority support contact."},"_rid":{"type":"string","description":"Request ID — include when reporting issues"}},"required":["error"]},"TierRequiredError":{"type":"object","description":"403 when the key's tier is below the endpoint's (or a parameter's) gate. `required_tier` matches the operation's `x-madeonsol-tier` or `x-madeonsol-feature-tiers`. ENTERPRISE gates return `contact` instead of `upgrade`.","required":["error","message","your_tier","required_tier"],"properties":{"error":{"type":"string","enum":["tier_required"]},"message":{"type":"string"},"feature":{"type":"string"},"your_tier":{"type":"string","enum":["BASIC","PRO","ULTRA","BUSINESS","ENTERPRISE"]},"required_tier":{"type":"string","enum":["PRO","ULTRA","BUSINESS","ENTERPRISE"]},"upgrade":{"type":"object","description":"The plan that lifts this limit, with price and a checkout link.","properties":{"tier":{"type":"string","enum":["PRO","ULTRA","BUSINESS","ENTERPRISE"]},"price_eur_per_month":{"type":"number"},"price_usdc_per_month":{"type":"number"},"daily_limit":{"type":"integer"},"burst_limit":{"type":"integer"},"pitch":{"type":"string"},"url":{"type":"string"},"upgrade_url":{"type":"string","format":"uri"},"reactivate":{"type":"boolean","description":"Present (true) when the key's paid subscription has just lapsed and `tier` is the plan it held."},"prior_tier":{"type":"string","enum":["PRO","ULTRA","BUSINESS"]}}},"contact":{"type":"object","properties":{"url":{"type":"string"},"contact_url":{"type":"string"},"pitch":{"type":"string"}}},"support":{"type":"string"},"_rid":{"type":"string"}}},"DemoKeyNotAllowedError":{"type":"object","description":"403 for the public demo key (`msk_demo_…`) outside its three-endpoint allow-list. `endpoint_tier` is the endpoint's real minimum plan (null when unknown).","required":["error","message","allowed_endpoints"],"properties":{"error":{"type":"string","enum":["demo_key_endpoint_not_allowed"]},"message":{"type":"string"},"endpoint_tier":{"type":"string","nullable":true,"enum":["FREE","PRO","ULTRA","BUSINESS","ENTERPRISE",null]},"allowed_endpoints":{"type":"array","items":{"type":"string"}},"signup_url":{"type":"string","format":"uri"},"upgrade_url":{"type":"string","format":"uri","description":"Only when the endpoint's tier can be bought at /checkout."}}},"RateLimitError":{"type":"object","description":"429 when a quota is exhausted: the daily quota, the per-minute burst, or a free-tier network/key-rotation cap. `datasets` is added on `daily` only.","required":["error","error_kind","message","tier","limit","resets_at"],"properties":{"error":{"type":"string","enum":["rate_limit_exceeded"]},"error_kind":{"type":"string","enum":["daily","burst","ip_cap","ip_rotation"]},"message":{"type":"string"},"tier":{"type":"string","enum":["BASIC","PRO","ULTRA","BUSINESS","ENTERPRISE"]},"limit":{"type":"integer"},"resets_at":{"type":"string","format":"date-time"},"upgrade":{"type":"object","description":"The plan that lifts this limit, with price and a checkout link.","properties":{"tier":{"type":"string","enum":["PRO","ULTRA","BUSINESS","ENTERPRISE"]},"price_eur_per_month":{"type":"number"},"price_usdc_per_month":{"type":"number"},"daily_limit":{"type":"integer"},"burst_limit":{"type":"integer"},"pitch":{"type":"string"},"url":{"type":"string"},"upgrade_url":{"type":"string","format":"uri"},"reactivate":{"type":"boolean","description":"Present (true) when the key's paid subscription has just lapsed and `tier` is the plan it held."},"prior_tier":{"type":"string","enum":["PRO","ULTRA","BUSINESS"]}}},"datasets":{"type":"object","properties":{"pitch":{"type":"string"},"url":{"type":"string","format":"uri"}}}}},"ConcurrencyLimitError":{"type":"object","description":"429 from the heavy-query limiter: too many heavy requests in flight for this key (`concurrency`) or for the whole server (`capacity`). Clears as soon as in-flight requests finish.","required":["error","error_kind","retry_after_seconds"],"properties":{"error":{"type":"string"},"error_kind":{"type":"string","enum":["concurrency","capacity"]},"retry_after_seconds":{"type":"number"},"max_concurrent":{"type":"integer"},"support":{"type":"string"},"_rid":{"type":"string"}}},"ServiceUnavailableError":{"type":"object","description":"503: a temporary capacity or maintenance condition (e.g. a Postgres statement timeout during a partition move, or the API-key lookup itself being unavailable). Retry after `Retry-After` seconds.","required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string","description":"Machine-readable code where one exists, e.g. `auth_backend_unavailable`."},"error_kind":{"type":"string","description":"e.g. `statement_timeout`, `auth_backend`"},"retry_after_seconds":{"type":"number"},"retryable":{"type":"boolean"},"support":{"type":"string"},"_rid":{"type":"string"}}},"RhcCopytradeTrackedWallets":{"type":"array","items":{"type":"string"},"nullable":true,"description":"DEPRECATED 2026-10-04 (kept, still filled): subset of source_wallets in the tracked KOL set (kol_evm_wallets, the set behind /rhc/kol/wallets). KOL enrichment only once source_admission is any_wallet; under the legacy kol_only engine only these can produce a signal. null when the reference read failed."},"RhcCopytradeUntrackedWallets":{"type":"array","items":{"type":"string"},"nullable":true,"description":"DEPRECATED 2026-10-04 (kept, still filled): subset of source_wallets NOT in the tracked KOL set. Under source_admission any_wallet they fire like any other wallet; under the legacy kol_only engine they never produce a signal. null when the reference read failed."},"RhcCopytradeOperationalState":{"type":"string","enum":["eligible","monitoring_pending","monitoring_unavailable","source_capacity_unavailable","no_tracked_sources","unknown"],"description":"Whether the rule can fire at all, separate from is_active (the customer switch). Under source_admission any_wallet (2026-10-04) every valid source wallet is followed, KOL or not: eligible; monitoring_pending = the rule changed after the engine's last rule load (live within seconds); monitoring_unavailable = the engine or the trade stream is not reporting, and it fires nothing until it is (see monitoring_reasons); source_capacity_unavailable = the engine's source-wallet cap is reached. Legacy (source_admission kol_only or absent): no_tracked_sources = none of source_wallets is a tracked KOL wallet (kol_evm_wallets on Robinhood Chain, active kol_wallets on Solana), so the rule cannot fire; unknown = the tracking read failed."},"RhcCopytradeSourceAdmission":{"type":"string","enum":["kol_only","any_wallet"],"description":"Which trades the RUNNING copy-trade engine admits (shared by the Solana and Robinhood Chain rules). any_wallet: a qualifying trade by any source wallet, KOL or not (Robinhood Chain: the ERC-4337 userOp sender on bundled transactions; Solana: the same effective-trader rule as KOL attribution). kol_only: only tracked KOL wallets (kol_evm_wallets / active kol_wallets), legacy. Absent when the engine state could not be read (legacy semantics). Added 2026-10-04."},"RhcCopytradeMonitoringReasons":{"type":"array","items":{"type":"string"},"description":"Present only with operational_state monitoring_unavailable: the infrastructure reasons (e.g. dex_stream_stale, trade_stream_stale, source_producer_stale, map_stale, bus_disconnected, engine_state_stale). Added 2026-10-04."},"RhcCopytradeRuleWarnings":{"type":"array","description":"Present only when something needs attention (the key is omitted otherwise, never null). Additive — status codes and existing fields never change. Emitted only under source_admission kol_only (legacy); under any_wallet an untracked wallet is not a problem and no warning is attached.","items":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["untracked_source_wallets","source_wallet_tracking_unavailable"]},"message":{"type":"string"}}}},"CopytradeSubscription":{"type":"object","description":"A copy-trade rule: source wallets to mirror, sizing, delivery, and optional MC bounds.","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"},"description":"Wallets being copied. Any valid Solana wallet once source_admission is any_wallet; under the legacy kol_only engine only active tracked KOL wallets fire — see source_admission and operational_state."},"min_trade_sol":{"type":"number","nullable":true,"description":"Skip source trades below this SOL size"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number","description":"fixed = SOL amount, proportional = multiplier (0.5 = half size), percent_source = 0..1"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","description":"GET only"},"updated_at":{"type":"string","format":"date-time"},"source_wallets_tracked":{"type":"array","items":{"type":"string"},"nullable":true,"description":"DEPRECATED 2026-10-04 (kept, still filled): subset of source_wallets that are active tracked Solana KOL wallets (the set behind /kol/wallets). KOL enrichment only once source_admission is any_wallet; under the legacy kol_only engine only these produce signals. null when the lookup failed. Added 2026-09-25."},"source_wallets_untracked":{"type":"array","items":{"type":"string"},"nullable":true,"description":"DEPRECATED 2026-10-04 (kept, still filled): subset of source_wallets that are not tracked KOL wallets. Under source_admission any_wallet they fire like any other wallet (no Wallet Tracker entry needed, no Wallet Tracker quota used); under the legacy kol_only engine they never produce a signal. null when the lookup failed. Added 2026-09-25."},"operational_state":{"$ref":"#/components/schemas/RhcCopytradeOperationalState"},"source_admission":{"$ref":"#/components/schemas/RhcCopytradeSourceAdmission"},"monitoring_reasons":{"$ref":"#/components/schemas/RhcCopytradeMonitoringReasons"},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}},"WebhookFilters":{"type":"object","description":"Optional per-event delivery filters on a webhook. wallet_tracker:event (since 2026-09-25): only min_sol, action and conditions on its own fields apply, after the subscriber check; on a webhook subscribed to wallet_tracker:event alone any other named filter is a 400.","properties":{"min_sol":{"type":"number","description":"Minimum sol_amount (kol:trade, wallet_tracker:event)"},"action":{"type":"string","enum":["buy","sell"],"description":"kol:trade, wallet_tracker:event (transfers have no action and are excluded)"},"kol_name":{"type":"string"},"deployer_tier":{"type":"array","items":{"type":"string"}},"min_kols":{"type":"integer"},"kinds":{"type":"array","items":{"type":"string","enum":["surge","revival"]},"description":"token:surge / token:revival only"},"tiers":{"type":"array","items":{"type":"string","enum":["early","strong","breakout"]},"description":"token:surge / token:revival only"},"launchpads":{"type":"array","items":{"type":"string"},"description":"token:surge / token:revival only"},"exclude_flags":{"type":"array","items":{"type":"string"},"description":"token:surge / token:revival only"},"min_mc_usd":{"type":"number"},"max_mc_usd":{"type":"number"},"types":{"type":"array","items":{"type":"string","enum":["dev_sell","dev_buy","dev_token_transfer_out","dev_token_transfer_in"]},"description":"dev:activity and rhc:dev_activity: event types to deliver. rhc:dev_activity carries dev_buy / dev_sell only (developer token transfers are never delivered on Robinhood Chain in v1), so the transfer types never match there."},"token_mints":{"type":"array","items":{"type":"string"},"maxItems":500,"description":"dev:activity only: mints"},"addresses":{"type":"array","items":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"maxItems":500,"description":"rhc:dev_activity only: 0x token addresses (case-insensitive)"},"deployers":{"type":"array","items":{"type":"string"},"maxItems":500,"description":"dev:activity (base58) and rhc:dev_activity (0x, case-insensitive): matches deployer_wallet or actor_wallet"},"conditions":{"type":"array","maxItems":10,"description":"ULTRA+ (2026-09-08). Custom { field, op, value } triples ANDed together and evaluated against the raw event payload, on top of the named filters. `field` must be a documented payload field of one of the webhook's subscribed event types (one level of dot-path allowed, e.g. `triggering_trade.sol_amount`); anything else is a 400. Number fields take eq/neq/gt/gte/lt/lte/in, strings eq/neq/in/contains, booleans eq/neq. On PRO the request is a 403 tier_required.","items":{"type":"object","required":["field","op","value"],"properties":{"field":{"type":"string","example":"sol_amount"},"op":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","in","contains"]},"value":{"description":"number | string | boolean, or a non-empty array (≤20) for `in`.","anyOf":[{"type":"number"},{"type":"string"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}}}}}},"Webhook":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string","format":"uri"},"events":{"type":"array","description":"dev:activity (live since 2026-10-05): developer dev_sell / dev_buy / dev_token_transfer_out / dev_token_transfer_in, projected per tier at delivery (PRO: the developer's own events, raw facts, no identity keys; ULTRA+: identity fields and linked-wallet events from proven links only). Dedupe on data.id. Solana transfers combine the legacy bounded wallet watch with the broad SPL Token / Token-2022 candidate source for attributed creators; transfer_watch_coverage describes the legacy watch only, while broad-source state/gaps are reported separately. Recovered broad-source rows can appear in REST history but are not retroactively re-sent as WS/webhook alerts. rhc:dev_activity: Robinhood Chain developer dev_buy / dev_sell ONLY (the token's recorded deployer trading it; developer token transfers are never delivered), PRO+, same projection and dedupe; payload fields as dev:activity with chain=robinhood, signature=tx hash, slot=block number. Live since 2026-10-05.","items":{"type":"string","enum":["kol:trade","kol:coordination","deployer:alert","deployer:bond","wallet_tracker:event","sniper:deploy","rhc:kol_trade","token:surge","token:revival","dev:activity","rhc:dev_activity"]}},"filters":{"$ref":"#/components/schemas/WebhookFilters"},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"last_delivered_at":{"type":"string","format":"date-time","nullable":true},"consecutive_failures":{"type":"integer"}}},"TradeCoverage":{"type":"object","description":"Coverage disclosure for endpoints backed by our persisted trade capture (`token_trades` / early-buyer data). Capture starts 2026-04-12 and persistence is gated to the launchpad pipeline (pump.fun, LaunchLab/bonk, bags) — it is NOT a full Solana trade history. Three separate answers (2026-09-21): `data_observed`/`in_scope` = at least one persisted row (presence, not completeness — a brand-new in-scope mint with no trades yet also reads false), `eligibility` = whether the CURRENT gate admits the subject, `completeness` = always `not_verified`. When no rows exist, zero/empty values mean 'not captured' (see eligibility for why), never 'no activity'.","properties":{"history_start":{"type":"integer","example":1775984757,"description":"Epoch seconds of the first persisted trade (2026-04-12)."},"scope":{"type":"string","example":"pump.fun pipeline (pump.fun, LaunchLab/bonk, bags)"},"in_scope":{"type":"boolean","nullable":true,"description":"Kept for compatibility — same value as data_observed: true = we hold ≥1 persisted trade for this subject · false = none persisted (see eligibility for why — a brand-new in-scope mint also reads false) · null = probe unavailable"},"data_observed":{"type":"boolean","nullable":true},"eligibility":{"type":"string","nullable":true,"enum":["eligible","lapsed","excluded","unknown","admitted_previously","not_applicable",null],"description":"Resolved against the EFFECTIVE production capture settings (refreshed every few minutes; if they cannot be confirmed the answer narrows, never widens). eligible = admitted by the current gate · lapsed = launched via our pipeline, capture window closed under the current settings · excluded = blacklisted · unknown = no evidence the gate admits it (most likely outside the launchpad pipeline; basis capture_state_unavailable = settings could not be confirmed, no claim either way) · admitted_previously = persisted rows prove past admission, current status not established · not_applicable = wallet subjects · null = lookup failed"},"eligibility_basis":{"type":"string","nullable":true,"description":"Evidence behind eligibility (e.g. unresolved_launch, recently_bonded, revived_curve, pipeline_known, launchlab_pool, bags_vanity_mint, launchpad_proven, resolved_launch, bonded_over_7d, revival_expired, blacklisted, persisted_rows, capture_state_unavailable, lookup_failed)"},"completeness":{"type":"string","enum":["not_verified"]},"size_floor":{"type":"object","description":"Persistence size floor of the same write path (added 2026-09-30). Buys under 0.05 SOL (under $3.50 when paid in USDC/USDT) are not stored; sells that receive SOL are kept at any size. Live streams, prices and candles are not subject to it.","properties":{"min_sol":{"type":"number","example":0.05},"min_stable_usd":{"type":"number","example":3.5},"applies_to":{"type":"string","example":"buys and SOL-spending legs; SOL-receiving sells of any size are kept"}}},"note":{"type":"string","description":"How to read the values (always present since 2026-09-21: eligibility-specific when no rows exist, a completeness caveat when they do)."}}},"LaunchCoverage":{"type":"object","description":"Dataset-scope disclosure injected on every 200 from the launch-pipeline feeds (`/deployer-hunter/*`, `/sniper/*`, `/alpha/*`, `/tokens/almost-bonded`, `/tokens/batch/risk`, `/wallet/batch/classify`) unless the route already carries a more precise per-subject `coverage`. Static: these datasets are built from launchpad ingest (in practice ~99% pump.fun), so an absent wallet/token, an empty profile or a `false` reputation flag means 'not observed by this pipeline', never 'clean' or 'no activity'.","properties":{"scope":{"type":"string","example":"launchpad pipeline (pump.fun and LaunchLab/bonk deploys; bags.fm tokens are covered in trade data but their deploys are not attributed here; no direct-to-DEX launches)"},"note":{"type":"string","description":"How to read absences and zeros in this response."}}},"KolTrade":{"type":"object","properties":{"wallet_address":{"type":"string"},"kol_name":{"type":"string"},"kol_twitter":{"type":"string","format":"uri","nullable":true},"token_mint":{"type":"string"},"token_name":{"type":"string","nullable":true},"token_symbol":{"type":"string","nullable":true},"action":{"type":"string","enum":["buy","sell"]},"sol_amount":{"type":"number","nullable":true,"description":"SOL size of the trade. null on a sell whose SOL proceeds are unknown (they went to another wallet or cannot be proven; since 2026-10-18): the sell still happened and reduced the KOL's tokens. Never read null as 0."},"token_amount":{"type":"number"},"market_cap_usd_at_trade":{"type":"number","nullable":true,"description":"Token market cap in USD at the moment of trade (real-time, from our in-memory price tracker — not the post-hoc Dexscreener spot)"},"price_usd_at_trade":{"type":"number","nullable":true,"description":"Token price in USD at the moment of trade"},"tx_signature":{"type":"string"},"traded_at":{"type":"string","format":"date-time"},"token_image_url":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true,"description":"Launchpad of origin (`pumpfun` / `launchlab` / `bags`); null for non-launchpad mints."},"token_age_minutes":{"type":"integer","nullable":true,"description":"Minutes between the token's first observed trade and now (not at trade time); null when the mint has no first-seen record."},"kol_strategy_tag":{"type":"string","nullable":true,"description":"Manual strategy tag from the roster, falling back to the auto-classified tag."},"kol_auto_strategy_tag":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing_trader","hodler","mixed",null],"description":"Auto-classified trader style — the value `strategy=` filters on."},"kol_winrate_7d":{"type":"number","nullable":true,"description":"KOL's 7-day win rate (0-100)."},"kol_winrate_30d":{"type":"number","nullable":true,"description":"KOL's 30-day win rate (0-100)."},"kol_early_entry_pct_30d":{"type":"number","nullable":true,"description":"Share of the KOL's 30-day buys that were early entries."},"kol_is_heating_up":{"type":"boolean","description":"KOL's recent performance is trending up vs their own baseline."},"kol_percentile_pnl_7d":{"type":"number","nullable":true,"description":"KOL's 7-day PnL percentile across the roster (0-100)."},"kol_percentile_winrate_7d":{"type":"number","nullable":true,"description":"KOL's 7-day win-rate percentile across the roster (0-100)."},"deployer":{"type":"object","description":"Present only when the token has a tracked deployer.","properties":{"wallet":{"type":"string"},"tier":{"type":"string","nullable":true,"enum":["elite","good","moderate","rising","cold","unranked",null]},"bonding_rate":{"type":"number","nullable":true}}},"deployer_tier":{"type":"string","nullable":true,"description":"Shortcut for `deployer.tier`; present only when `deployer` is."},"token":{"type":"object","nullable":true,"description":"Present only with `include=token` — the `/token/{mint}` snapshot for this row (null past the 20-distinct-mint cap)."}}},"LeaderboardRow":{"type":"object","properties":{"name":{"type":"string"},"wallet":{"type":"string"},"pnl":{"type":"number","description":"Realized PnL in SOL"},"buy_count":{"type":"integer"},"sell_count":{"type":"integer"},"volume":{"type":"number"},"win_rate":{"type":"number","description":"0-100. Over positions with known proceeds only (migration 512)."},"completeness":{"type":"string","enum":["complete","incomplete"],"description":"Realized-PnL completeness for the KOL (migration 512). incomplete when at least one KOL sell in the window has unknown SOL proceeds (they went to another wallet or cannot be proven; kol_trades valuation_status unvalued, sol_amount null): those positions still reduce holdings but are left out of realized PnL, win rate, ROI and the ranking, never booked as 0 proceeds or a loss. This is realized-PnL completeness. It is NOT `coverage.completeness` (source-coverage verification: verified / not_verified / ...), which says whether the trade capture for this subject is proven complete."},"incomplete_reasons":{"type":"array","items":{"type":"string","enum":["proceeds_unattributed"]},"description":"Empty when complete; proceeds_unattributed when unknown_realizations > 0."},"unknown_realizations":{"type":"integer","description":"Migration 512: (KOL, token) positions with a sell whose proceeds are unknown, excluded from realized PnL / win rate / ROI. 0 when complete."},"unknown_proceeds_sells":{"type":"integer","description":"Migration 512: KOL sells with unknown proceeds (sol_amount null) in the window. 0 when complete."},"median_hold_minutes_30d":{"type":"number","nullable":true,"description":"Median hold time in minutes over the last 30 days."},"percentile_early_entry_30d":{"type":"number","nullable":true,"minimum":0,"maximum":100,"description":"Percentile rank for early entry timing over the last 30 days."}}},"CoordinationCluster":{"type":"object","properties":{"token_mint":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"kol_count":{"type":"integer"},"total_buys":{"type":"integer"},"total_sells":{"type":"integer"},"net_sol_flow":{"type":"number"},"signal":{"type":"string","enum":["accumulating","distributing"]},"avg_winrate_7d":{"type":"number","nullable":true,"description":"Mean 7d winrate across the cluster's KOLs"},"entry_rank_avg":{"type":"number","nullable":true,"description":"Avg early-entry percentile (lower = earlier in the trade)"},"unique_strategies":{"type":"integer","description":"Count of distinct auto_strategy_tag values across the KOLs"},"strategies":{"type":"array","items":{"type":"string"}},"first_buy_at":{"type":"string","format":"date-time","nullable":true},"last_buy_at":{"type":"string","format":"date-time","nullable":true},"time_to_consensus_sec":{"type":"integer","nullable":true,"description":"Seconds between first and last KOL buy (full-period span)"},"peak_window_start":{"type":"string","format":"date-time","nullable":true,"description":"Start of densest buy cluster (default 15-min window)"},"peak_window_end":{"type":"string","format":"date-time","nullable":true},"peak_kols":{"type":"integer","nullable":true,"description":"Distinct KOLs buying inside the peak window"},"peak_buys":{"type":"integer","nullable":true,"description":"Total buys inside the peak window"},"exited_count":{"type":"integer","description":"KOLs in the cluster whose sell_sol > buy_sol (net-flow-negative)"},"holders_count":{"type":"integer","description":"kol_count − exited_count (still net-long)"},"coordination_score":{"type":"integer","minimum":0,"maximum":100,"description":"Composite 0-100 signal score. Weighting exposed via top-level score_version."},"market_cap_usd_at_first_buy":{"type":"number","nullable":true,"description":"Market cap (USD) stamped on the cluster's chronologically-first KOL buy. Distinguishes coordinated accumulation at micro-cap from late-stage chasing."},"market_cap_usd":{"type":"number","nullable":true,"description":"Current market cap (USD) of the token, sourced from token_prices. Compare against market_cap_usd_at_first_buy for the cluster's MC delta."},"last_price_usd":{"type":"number","nullable":true,"description":"Current last-trade price (USD)."},"mc_change_pct":{"type":"object","description":"Market-cap % change over each window (e.g. 12.4 = +12.4%). Sparse — only windows with enough mc-tracker history are present. Use to tell whether the cluster is firing into a moving token or before the move.","properties":{"5m":{"type":"number","nullable":true},"15m":{"type":"number","nullable":true},"1h":{"type":"number","nullable":true},"2h":{"type":"number","nullable":true},"4h":{"type":"number","nullable":true}}},"volume_usd":{"type":"object","description":"Organic (non-MEV) USD volume over each window. Sparse — same gating as mc_change_pct.","properties":{"5m":{"type":"number"},"15m":{"type":"number"},"1h":{"type":"number"},"2h":{"type":"number"},"4h":{"type":"number"}}},"mev_volume_pct":{"type":"object","description":"MEV-share of total volume over each window (0-100). High value = bot-heavy / sandwich-heavy flow.","properties":{"5m":{"type":"number","nullable":true},"15m":{"type":"number","nullable":true},"1h":{"type":"number","nullable":true},"2h":{"type":"number","nullable":true},"4h":{"type":"number","nullable":true}}},"history_age_seconds":{"type":"integer","nullable":true,"description":"Seconds of mc-tracker history available for this token (capped at 4h05m). Tells you which windows can be trusted. Null when token is untracked."},"kols":{"type":"array","items":{},"description":"BASIC: array of KOL names (first 3). PRO+: objects {name, wallet, buy_sol, sell_sol, exited} — full wallet addresses on every tier that can call the endpoint (BASIC gets 403 on /kol/coordination)."}}},"CoordinationAlertRule":{"type":"object","description":"A saved /kol/coordination/alerts rule. `created_at` is present on list/GET-one responses; `updated_at` is present on GET-one/PATCH responses (list omits it).","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"min_kols":{"type":"integer"},"window_minutes":{"type":"integer"},"min_score":{"type":"integer"},"include_majors":{"type":"boolean"},"cooldown_min":{"type":"integer"},"score_jump_break":{"type":"integer"},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FirstTouchSubscription":{"type":"object","description":"A saved /kol/first-touches/subscriptions subscription. `created_at` is present on list/GET-one/PATCH responses; `updated_at` is present on GET-one/PATCH responses (list omits it).","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"filters":{"type":"object","properties":{"kol":{"type":"string","nullable":true,"description":"Wallet address (32-44 base58 chars)"},"mint_suffix":{"type":"string","nullable":true},"min_first_buy_sol":{"type":"number","nullable":true},"min_scout_tier":{"type":"string","nullable":true,"enum":["S","A","B","C"]},"min_n_touches":{"type":"integer","nullable":true}}},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"BuyerQuality":{"type":"object","properties":{"mint":{"type":"string"},"score":{"type":"number","description":"0-100 composite buyer-quality score"},"confidence":{"type":"string","enum":["insufficient_data","low","medium","high"],"description":"Confidence in the PREDICTIVE inputs: counts only buyers whose win rate fed the score (≥3 tokens of history, not bot-flagged, not zero-cost-dump dominated). insufficient_data = none did — the score is the neutral-50 default plus penalties. 1 → low, 5+ → medium, 11+ → high."},"signal":{"type":"string","enum":["positive","neutral","negative"]},"breakdown":{"type":"object","properties":{"alpha_wallet_count":{"type":"integer"},"kol_count":{"type":"integer"},"bundle_buyer_count":{"type":"integer"},"avg_historical_win_rate":{"type":"number","nullable":true,"description":"null when no buyer's win rate qualified (confidence insufficient_data)"},"bot_dominated":{"type":"boolean"},"wallets_with_history":{"type":"integer","description":"Buyers with ≥3 tokens of history (cohort identification — not predictive)"},"qualified_win_rate_wallets":{"type":"integer","description":"Buyers whose win rate fed the score — the basis of confidence"},"dump_cluster_count":{"type":"integer","description":"First-20 buyers on the rolling dump-cluster list (wallets whose 5+ recent first-20 appearances are exclusively on tokens that peaked <15 min after deploy; trailing 42d, refreshed daily). Out-of-sample: 3+ such wallets predicted a sub-15-min peak 94% of the time vs 61% base. Informational — does not move the score."},"recycled_early_buyer_count":{"type":"integer","description":"First-20 buyers with 5+ recent first-20 cohort appearances of any kind. The count alone predicts nothing; a heavily recycled cohort with dump_cluster_count 0 historically leans runner."}}},"cached_at":{"type":"string","format":"date-time"},"coverage":{"$ref":"#/components/schemas/TradeCoverage"},"note":{"type":"string","description":"Present only when no early-buyer data exists for the mint — the score is then a neutral 50 placeholder (\"Insufficient buyer data\"); check coverage to tell 'no early buyers captured' from 'mint outside the write-gate'."},"signal_stats":{"type":"object","description":"Present only when breakdown.dump_cluster_count ≥ 1 and the daily signal-performance snapshot has a bucket for it. The live, out-of-sample efficacy of that value, so the raw count is readable.","properties":{"dump_cluster_count":{"type":"object","properties":{"value":{"type":"integer","description":"The token's own dump_cluster_count."},"bucket":{"type":"string","enum":["k>=1","k>=3","k>=5"],"description":"Most specific cumulative-threshold bucket the value qualifies for."},"outcome":{"type":"string","enum":["dump","runner"],"description":"Outcome the hit rate is measured against."},"hit_rate":{"type":"number","description":"P(outcome | bucket), 0-1."},"base_rate":{"type":"number","description":"P(outcome | all tokens), 0-1."},"lift":{"type":"number","description":"hit_rate / base_rate."},"sample_n":{"type":"integer"},"window_days":{"type":"integer"},"as_of":{"type":"string","format":"date-time","description":"Snapshot time of the signal_performance row."},"summary":{"type":"string","example":"dump_cluster_count=3 (k>=3): 95% of such tokens dumped vs 75% base (1.27× lift), n=349, 14d OOS"}}}}},"dump_cluster_held_now":{"type":"object","description":"Only with include_balances=true (PRO+, 2026-10-15, TR-09): the early buyers counted in dump_cluster_count and what they hold NOW from balances. Totals only when every member was read.","properties":{"cohort_size":{"type":"integer"},"members":{"type":"integer","description":"Dump-cluster members among the early buyers (= dump_cluster_count)."},"held_now":{"type":"object","description":"Same shape as the bundle held_now of this chain: source, checked_at, wallets, verified_wallets, holding_wallets, complete, incomplete_reason, tokens_held_raw, tokens_held, held_pct_of_supply (ratio), supply_basis."},"wallets":{"type":"array","items":{"type":"object","properties":{"wallet":{"type":"string"},"balance_now":{"type":"object","nullable":true}}}},"note":{"type":"string"}}}}},"BuyerQualityBatchItem":{"type":"object","description":"Per-mint item of POST /tokens/batch/buyer-quality: the GET /tokens/{mint}/buyer-quality shape WITHOUT `signal_stats` (the batch path does not attach the signal-performance snapshot).","properties":{"mint":{"type":"string"},"score":{"type":"number","description":"0-100 composite buyer-quality score"},"confidence":{"type":"string","enum":["insufficient_data","low","medium","high"],"description":"Confidence in the PREDICTIVE inputs: counts only buyers whose win rate fed the score (≥3 tokens of history, not bot-flagged, not zero-cost-dump dominated). insufficient_data = none did — the score is the neutral-50 default plus penalties. 1 → low, 5+ → medium, 11+ → high."},"signal":{"type":"string","enum":["positive","neutral","negative"]},"breakdown":{"type":"object","properties":{"alpha_wallet_count":{"type":"integer"},"kol_count":{"type":"integer"},"bundle_buyer_count":{"type":"integer"},"avg_historical_win_rate":{"type":"number","nullable":true,"description":"null when no buyer's win rate qualified (confidence insufficient_data)"},"bot_dominated":{"type":"boolean"},"wallets_with_history":{"type":"integer","description":"Buyers with ≥3 tokens of history (cohort identification — not predictive)"},"qualified_win_rate_wallets":{"type":"integer","description":"Buyers whose win rate fed the score — the basis of confidence"},"dump_cluster_count":{"type":"integer","description":"First-20 buyers on the rolling dump-cluster list (wallets whose 5+ recent first-20 appearances are exclusively on tokens that peaked <15 min after deploy; trailing 42d, refreshed daily). Out-of-sample: 3+ such wallets predicted a sub-15-min peak 94% of the time vs 61% base. Informational — does not move the score."},"recycled_early_buyer_count":{"type":"integer","description":"First-20 buyers with 5+ recent first-20 cohort appearances of any kind. The count alone predicts nothing; a heavily recycled cohort with dump_cluster_count 0 historically leans runner."}}},"cached_at":{"type":"string","format":"date-time"},"coverage":{"$ref":"#/components/schemas/TradeCoverage"},"note":{"type":"string","description":"Present only when no early-buyer data exists for the mint — the score is then a neutral 50 placeholder (\"Insufficient buyer data\"); check coverage to tell 'no early buyers captured' from 'mint outside the write-gate'."}}},"WalletTrackerSummary":{"type":"object","description":"Per-wallet activity for your Solana tracked wallets over `period` (newest-added first). An empty tracker returns `{ wallets: [], period }` without `interval`.","properties":{"wallets":{"type":"array","items":{"type":"object","properties":{"wallet_address":{"type":"string"},"label":{"type":"string","nullable":true},"added_at":{"type":"string","format":"date-time"},"stats":{"type":"object","properties":{"swap_count":{"type":"integer"},"transfer_count":{"type":"integer"},"buys":{"type":"integer"},"sells":{"type":"integer"},"sol_bought":{"type":"number"},"sol_sold":{"type":"number"},"last_event_at":{"type":"string","format":"date-time","nullable":true}}}}}},"period":{"type":"string","enum":["24h","7d","30d"]},"interval":{"type":"string","description":"Postgres interval for the period, e.g. \"7 days\"."}}},"WalletStats":{"type":"object","properties":{"address":{"type":"string"},"completeness":{"type":"string","enum":["complete","incomplete"],"description":"Realized-PnL completeness. incomplete when at least one sell in the response has proceeds that went to another wallet (price_status proceeds_unattributed, migration 508): realized PnL and ROI then cover the known basis only, and the basis those sells consumed is reported as unknown_realized_cost_basis_sol, never as 0 proceeds or a loss. This is realized-PnL completeness. It is NOT `coverage.completeness` (source-coverage verification: verified / not_verified / ...), which says whether the trade capture for this subject is proven complete."},"incomplete_reasons":{"type":"array","items":{"type":"string","enum":["proceeds_unattributed","unknown_consideration"]},"description":"Empty when complete. /wallet/{address} and /tokens/{mint}/top-traders emit only proceeds_unattributed; unknown_consideration is shared with the FIFO routes (/pnl, /positions)."},"pnl_basis_note":{"type":"string","description":"Fixed sentence: realized_pnl_sol and ROI cover the known basis only; unattributed sells are excluded and the basis they consumed is unknown_realized_cost_basis_sol."},"stats":{"type":"object","nullable":true,"properties":{"first_seen":{"type":"string","format":"date-time"},"last_seen":{"type":"string","format":"date-time"},"total_trades":{"type":"integer"},"buys":{"type":"integer"},"sells":{"type":"integer"},"bought_sol":{"type":"number"},"sold_sol":{"type":"number"},"unique_tokens":{"type":"integer"},"unknown_realized_cost_basis_sol":{"type":"number","description":"Migration 508: cost basis consumed by sells whose proceeds went to another wallet. NOT in realized_pnl_sol or ROI (neither a loss nor a gain). 0 when complete."},"unattributed_sells":{"type":"integer","description":"Migration 508: sells with price_status proceeds_unattributed. 0 when complete."},"window_days":{"type":"integer","description":"Lookback window — currently 90"}}},"flags":{"type":"object","properties":{"is_kol":{"type":"boolean"},"kol_name":{"type":"string","nullable":true},"is_alpha_tracked":{"type":"boolean"},"bot_confidence":{"type":"string","nullable":true,"enum":["none","low","medium","high"],"description":"Bot-likeness classification from alpha-wallet rules"},"alpha_win_rate":{"type":"number","nullable":true},"alpha_net_pnl_sol":{"type":"number","nullable":true},"alpha_tokens_traded":{"type":"integer","nullable":true},"is_deployer":{"type":"boolean"},"deployer_tokens_deployed":{"type":"integer","nullable":true},"deployer_bonding_rate":{"type":"number","nullable":true},"coverage_note":{"type":"string","description":"Fixed disclosure: is_sniper/is_bundler/is_dumper derive from the launchpad trade pipeline — false means 'not observed in covered trades', not 'verified clean'."},"is_sniper":{"type":"boolean","description":">=5 tokens early-bought & >=80% flipped <5min (behavior-updated hourly). Pump.fun-pipeline scoped; false = not observed, not verified clean"},"is_bundler":{"type":"boolean","description":"Bought >1 token in the same block, ever (lifetime flag)"},"is_dumper":{"type":"boolean","description":">=5 dump cohorts + 0 runner cohorts in rolling 42d window (recomputed daily)"},"dump_cluster":{"type":"object","nullable":true,"description":"Raw dump-cluster cohort counts (present when the wallet has >=5 recent early-buyer cohort appearances)","properties":{"dump_cohorts":{"type":"integer"},"runner_cohorts":{"type":"integer"},"total_cohorts":{"type":"integer"},"as_of":{"type":"string","format":"date-time"}}}}},"top_tokens":{"type":"array","description":"Top traded tokens (90d window) with realized PnL. Cross-joined with deployer-tokens for symbol + peak MC where available.","items":{"type":"object","properties":{"token_mint":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"buys":{"type":"integer"},"sells":{"type":"integer"},"sol_in":{"type":"number"},"sol_out":{"type":"number"},"realized_pnl_sol":{"type":"number","description":"Known basis only (migration 508): sells whose proceeds went to another wallet are excluded, see unknown_realized_cost_basis_sol."},"current_mc_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"last_traded_at":{"type":"string","format":"date-time"},"unknown_realized_cost_basis_sol":{"type":"number","description":"Migration 508: cost basis consumed by sells whose proceeds went to another wallet. NOT in realized_pnl_sol or ROI (neither a loss nor a gain). 0 when complete."},"unattributed_sells":{"type":"integer","description":"Migration 508: sells with price_status proceeds_unattributed. 0 when complete."},"realized_status":{"type":"string","enum":["known","partial","unknown"],"description":"known = no unattributed sell; partial = some sells unattributed (realized on the known basis); unknown = every sell unattributed: the outcome is unknown, not a loss (same vocabulary as /pnl closed_positions)."}}}},"trading_style":{"type":"object","nullable":true,"description":"Behavioural signals: avg trade size, sniper rate, round-trip rate, median hold time.","properties":{"total_trades":{"type":"integer"},"avg_trade_size_sol":{"type":"number"},"sniper_rate":{"type":"number","description":"0–1: fraction of trades with early_buyer_rank ≤ 10."},"early_entries":{"type":"integer"},"round_trip_rate":{"type":"number","description":"0–1: fraction of tokens with both buys and sells."},"tokens_with_round_trips":{"type":"integer"},"median_hold_minutes":{"type":"number","nullable":true,"description":"Median minutes between first buy and first sell across tokens."},"dominant_action":{"type":"string","enum":["buy","sell","balanced"]}}},"deployer_breakdown":{"type":"object","nullable":true,"description":"Tier distribution of pump.fun deployers this wallet has bought from. Useful for spotting alpha-buyers vs random degens.","properties":{"total_tokens":{"type":"integer"},"tracked_deployers":{"type":"integer"},"by_tier":{"type":"array","items":{"type":"object","properties":{"tier":{"type":"string","description":"elite / good / rising / moderate / cold / unranked"},"count":{"type":"integer"}}}}}},"recent_trades":{"type":"array","description":"Last 10 trades regardless of window (raw timeline, cross-joined with deployer-tokens for symbol).","items":{"type":"object","properties":{"token_mint":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"action":{"type":"string","enum":["buy","sell"]},"sol_amount":{"type":"number"},"block_time":{"type":"integer"},"traded_at":{"type":"string","format":"date-time"},"tx_signature":{"type":"string"}}}},"derived":{"type":"object","description":"Derived wallet stats computed from the enrichments above (src/lib/wallet-enrichments.ts DerivedStats: standout trades, biggest miss, realized/unrealized PnL rollups)."},"coverage":{"$ref":"#/components/schemas/TradeCoverage"},"stats_unavailable":{"type":"boolean","description":"Present (true) only when the 90-day trade aggregation failed. `stats` null is then UNPROVEN, not an inactive wallet."},"enrichment_unavailable":{"type":"boolean","description":"Present (true) only when one or more enrichment queries failed; `degraded_fields` names them. Absent on a fully measured response."},"degraded_fields":{"type":"array","items":{"type":"string","enum":["top_tokens","trading_style","deployer_breakdown","recent_trades","biggest_miss"]},"description":"Enrichment blocks whose query failed (e.g. a database timeout under load). Their null / [] value is UNKNOWN, not 'no data'; retry later. `biggest_miss` refers to `derived.biggest_miss`. Present only together with `enrichment_unavailable: true`."}},"required":["address","flags"]},"WalletHolding":{"type":"object","description":"One chain-verified token holding. `transfer_delta` = on-chain amount minus trade-derived net (non-null only when the mint was traded in-window); a large positive delta flags tokens received without a swap.","properties":{"mint":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"amount":{"type":"number"},"amount_raw":{"type":"string","description":"Raw integer amount (pre-decimals) as a string."},"decimals":{"type":"integer"},"token_program":{"type":"string","enum":["spl","token2022"]},"price_usd":{"type":"number","nullable":true},"value_usd":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"is_bonded":{"type":"boolean","nullable":true},"trade_derived_amount":{"type":"number","nullable":true},"transfer_delta":{"type":"number","nullable":true}}},"WalletPnl":{"type":"object","properties":{"address":{"type":"string"},"window_days":{"type":"integer"},"completeness":{"type":"string","enum":["complete","incomplete"],"description":"incomplete when at least one disposal's realized PnL is unknown (a sell whose proceeds provably went to another wallet, price_status proceeds_unattributed; or a trade with unknown consideration). Such a disposal consumes the FIFO lots (holdings are right) but is excluded from realized_sol, wins/losses, win_rate, profit_factor and best/worst — never booked as 0 proceeds. Absent on analyses cached before this field existed. This is realized-PnL completeness. It is NOT `coverage.completeness` (source-coverage verification: verified / not_verified / ...), which says whether the trade capture for this subject is proven complete."},"incomplete_reasons":{"type":"array","items":{"type":"string","enum":["proceeds_unattributed","unknown_consideration"]},"description":"Empty when complete."},"summary":{"type":"object","properties":{"realized_sol":{"type":"number","description":"Known realizations only; see unknown_realized_cost_basis_sol and completeness."},"unrealized_sol":{"type":"number"},"total_pnl_sol":{"type":"number"},"total_bought_sol":{"type":"number"},"total_sold_sol":{"type":"number"},"unknown_realized_cost_basis_sol":{"type":"number","description":"Cost basis of FIFO lots consumed by disposals whose realization is unknown. It left the open positions and is NOT in realized_sol (neither a loss nor a gain). 0 when complete."},"wins":{"type":"integer"},"losses":{"type":"integer"},"win_rate":{"type":"number","nullable":true},"profit_factor":{"type":"number","nullable":true,"description":"Gross wins / gross losses. null if no losses (undefined math)."},"avg_hold_minutes":{"type":"integer","nullable":true},"median_hold_minutes":{"type":"integer","nullable":true},"max_drawdown_sol":{"type":"number"},"open_positions_count":{"type":"integer"},"closed_positions_count":{"type":"integer"},"total_tokens_traded":{"type":"integer"},"best_realized":{"type":"object","nullable":true,"properties":{"token_mint":{"type":"string"},"realized_sol":{"type":"number"}}},"worst_realized":{"type":"object","nullable":true,"properties":{"token_mint":{"type":"string"},"realized_sol":{"type":"number"}}}}},"pnl_curve":{"type":"array","description":"Sparse daily UTC buckets — only days with at least one realized event are returned.","items":{"type":"object","properties":{"date":{"type":"string","description":"YYYY-MM-DD UTC"},"day_pnl":{"type":"number"},"cumulative_pnl":{"type":"number"},"trades":{"type":"integer"}}}},"closed_positions":{"type":"array","description":"Tokens where the wallet's position has been fully closed AND there was an observable buy in window. Sorted by pnl_sol DESC (winners first).","items":{"$ref":"#/components/schemas/WalletClosedPosition"}},"open_positions":{"type":"array","items":{"$ref":"#/components/schemas/WalletOpenPosition"}},"notes":{"type":"object","properties":{"cost_basis_observable_from":{"type":"string","format":"date-time","description":"Cost basis can only be reconstructed from trades inside our data window. Overflow sells (no matching buy in window) are silently discarded rather than fabricated."},"trades_through":{"type":"string","format":"date-time","description":"Newest trade included — the cache watermark (a later trade invalidates the cached analysis)"},"trades_through_block_time":{"type":"integer","description":"trades_through as epoch seconds"},"trades_through_same_second":{"type":"integer","description":"Trades at exactly trades_through_block_time that were included (block_time is second-granular; used to detect a same-second trade ingested after the compute)"},"partial":{"type":"boolean","description":"Present (true) only when the wallet exceeded the trade analysis cap and the summary was computed from the most recent trades only."},"analyzed_trades":{"type":"integer","description":"Present only when partial is true — the number of most-recent trades the summary was computed from (the cap)."},"partial_reason":{"type":"string","description":"Present only when partial is true — human-readable explanation of what the cap excludes (realized PnL for positions opened before cost_basis_observable_from; open positions limited to the analyzed window)."},"sells_without_cost_basis":{"type":"object","properties":{"tokens":{"type":"integer","description":"Tokens with sells beyond in-window buys; excluded from realized PnL."},"cost_basis":{"type":"string","enum":["unknown"]}}},"unknown_realizations":{"type":"object","description":"Disposals whose realized PnL is unknown (see completeness). Their consumed cost basis is reported here and excluded from every realized figure.","properties":{"proceeds_unattributed_sells":{"type":"integer","description":"Sells with price_status proceeds_unattributed (proceeds went to another wallet or reached nobody we can prove)."},"tokens":{"type":"integer","description":"Tokens with at least one unknown disposal (realized_status partial or unknown)."},"unknown_realized_cost_basis_sol":{"type":"number"},"realized_pnl":{"type":"string","enum":["excluded"]}}}}},"holding_check":{"type":"object","description":"COV-21: summary of the proven-holding check over the returned open positions (SOLANA_POSITION_HOLDING; mode off = every position unverified/not_checked).","properties":{"mode":{"type":"string","enum":["off","cache"]},"source":{"type":"string","nullable":true,"enum":["wallet_holdings_cache"]},"verified_at":{"type":"string","nullable":true,"format":"date-time"},"verified":{"type":"integer"},"unverified":{"type":"integer"},"held":{"type":"integer"},"partially_reduced":{"type":"integer"},"transferred_or_disposed":{"type":"integer"},"external_inflow":{"type":"integer"},"note":{"type":"string"}}},"cache_hit":{"type":"boolean","description":"true when served from wallet_analyses cache"},"computed_at":{"type":"string","format":"date-time","description":"Always returned — when the analysis was computed (the fresh compute time on a miss, the cached row's analyzed_at on a hit)"},"cache_age_seconds":{"type":"integer","description":"Seconds since computed_at — the source age survives a cache hit (0 on a fresh compute)"},"cache_validation":{"type":"string","enum":["head_checked","unverified"],"description":"Cache hits only (audit F16): head_checked = the wallet has no persisted trade newer than the analysis watermark, so the cached analysis is current; unverified = the trade-head probe failed and the unexpired cache was served flagged. A hit whose wallet traded after the watermark is never served — it is recomputed."},"cache_invalidated":{"type":"string","enum":["new_activity"],"description":"Present on a recompute that happened because a cached analysis existed but the wallet traded after it"},"ttl_seconds":{"type":"integer","description":"Only present on cache misses — TTL for this row in wallet_analyses (5min / 1h / 24h based on activity)"}}},"WalletOpenPosition":{"type":"object","properties":{"token_mint":{"type":"string"},"token_amount":{"type":"number"},"cost_basis_sol":{"type":"number"},"avg_entry_price_sol":{"type":"number"},"current_price_sol":{"type":"number","nullable":true,"description":"Live from market-cap tracker. null if the mint has no current price (e.g. delisted)."},"current_value_sol":{"type":"number","nullable":true},"unrealized_sol":{"type":"number","nullable":true},"unrealized_pct":{"type":"number","nullable":true},"first_buy_at":{"type":"string","format":"date-time","nullable":true},"buys_in_position":{"type":"integer"},"position_basis":{"type":"string","enum":["swap_derived"],"description":"Positions are FIFO-open DEX buys from token_trades (trade position), not a proven holding."},"holding_status":{"type":"string","enum":["verified","unverified"]},"holding_unverified_reason":{"type":"string","nullable":true,"enum":["not_checked","no_fresh_snapshot","snapshot_unreadable","snapshot_older_than_trades","decimals_mismatch","balance_invalid"]},"cost_basis_status":{"type":"string","enum":["known","partial"],"description":"partial = a verified balance exceeds the trade position; the excess arrived without a swap and has no cost basis."},"holding":{"type":"object","nullable":true,"properties":{"status":{"type":"string","enum":["HELD","PARTIALLY_REDUCED","TRANSFERRED_OR_DISPOSED","EXTERNAL_INFLOW"]},"onchain_balance":{"type":"number"},"held_known_amount":{"type":"number"},"external_inflow_amount":{"type":"number"},"cost_basis_held_sol":{"type":"number"},"unrealized_known_sol":{"type":"number","nullable":true},"cost_basis_not_held_sol":{"type":"number","description":"Cost of FIFO lots no longer in the wallet (transfer out / unindexed disposal). Outcome unknown: neither realized nor unrealized."},"verified_at":{"type":"string","format":"date-time"},"source":{"type":"string","enum":["wallet_holdings_cache"]}}}}},"WalletClosedPosition":{"type":"object","properties":{"token_mint":{"type":"string"},"buy_count":{"type":"integer"},"sell_count":{"type":"integer"},"bought_sol":{"type":"number"},"sold_sol":{"type":"number"},"pnl_sol":{"type":"number"},"roi_pct":{"type":"number","nullable":true,"description":"realized_sol / total_bought_sol × 100; null when realized_status is not known"},"hold_minutes":{"type":"integer","nullable":true,"description":"first buy to last sell"},"result":{"type":"string","enum":["win","loss","breakeven","unknown"],"description":"unknown = at least one disposal's realization is unknown (proceeds_unattributed / unknown consideration): not a win, not a loss, not counted in win_rate or profit_factor; sorted after the known positions"},"realized_status":{"type":"string","enum":["known","partial","unknown"],"description":"known = every disposal realized; partial = some unknown (pnl_sol is the known part); unknown = only unknown disposals"},"unknown_realized_cost_basis_sol":{"type":"number","description":"Cost basis of the lots consumed by unknown disposals of this token; not in pnl_sol."},"first_trade":{"type":"string","format":"date-time","nullable":true},"last_trade":{"type":"string","format":"date-time","nullable":true}}},"TradeRawAmounts":{"type":"object","description":"Exact on-chain amounts of this trade (#508). Present only once exact amounts are enabled server-side. Integers are decimal STRINGS (u64 base units exceed the JSON double range). `raw_known: false` = a row stored before exact amounts existed: every field is null = UNKNOWN, never 0. With `raw_known: true`: `token_raw` is the wallet's net change of the traded mint in base units (token_amount = token_raw / 10^token_decimals, exact — 1 base unit of a 9-decimal token is \"1\" here while token_amount rounds to 0); `sol_net_lamports` is the signed SOL settlement (negative = paid) with the tx fee and token-account rent EXCLUDED, null unless SOL is the proven settlement; `quote_*` is the one non-SOL token the wallet moved the other way (USDC, PUMP, an xStock …); both null = settlement unknown (never guessed).","properties":{"token_raw":{"type":"string","nullable":true,"pattern":"^[0-9]+$","description":"abs net change of the traded mint, base units"},"token_decimals":{"type":"integer","nullable":true},"sol_net_lamports":{"type":"string","nullable":true,"pattern":"^-?[0-9]+$","description":"signed lamports, fee + token-account rent excluded; null unless SOL is the proven settlement"},"quote_mint":{"type":"string","nullable":true},"quote_raw":{"type":"string","nullable":true,"pattern":"^[0-9]+$","description":"abs net change of quote_mint, base units"},"quote_decimals":{"type":"integer","nullable":true},"raw_known":{"type":"boolean","description":"false = legacy row, every raw field null (unknown)"}},"required":["token_raw","token_decimals","sol_net_lamports","quote_mint","quote_raw","quote_decimals","raw_known"]},"TradeEventFacts":{"type":"object","description":"Event identity and attribution labels of this trade row (migration 493). Present on /tokens/{mint}/trades and /wallet/{address}/trades once event reads are enabled server-side (live since 2026-10-16). Every field null = a netted legacy row: one row per (transaction, wallet, mint), the pre-493 shape, and today every stored row (the event-row writer is not on). Values are open-ended labels: treat an unrecognised value as not proven, never as a normal trade. Never deduplicate on (tx_signature, wallet_address): N event rows of one transaction share tx_signature and differ in event_id.","properties":{"event_id":{"type":"string","nullable":true,"description":"`signature:outer_ix[.inner_ix]` of the decoded swap instruction; null = netted row (one row for the wallet's whole net change of the mint in this transaction)"},"trader_status":{"type":"string","nullable":true,"description":"signer | non_signer | unproven (a non-signer whose swap is proven by its legs but whose ownership is not: shown on the token tape, excluded from every wallet-scoped read and count); null = legacy row. Later labels may appear; only null, signer and non_signer count as the wallet's own trade."},"price_status":{"type":"string","nullable":true,"description":"null = priced as before | quote_unpriced (non-SOL quote leg without a price: sol_amount is the wallet's fee, not the consideration; price_sol / price_usd are null) | proceeds_unattributed (a sell whose proceeds went to another wallet or to nobody provable: token_amount counts, sol_amount is NOT the proceeds, price_sol / price_usd are null; not written until the attribution writer is enabled)"},"block_time_source":{"type":"string","nullable":true,"description":"chain | ingest_clock (the live stream carries no block time, so block_time is our ingest clock); null = legacy row (ingest clock on the live path)"}},"required":["event_id","trader_status","price_status","block_time_source"]},"WalletTrade":{"type":"object","properties":{"tx_signature":{"type":"string"},"token_mint":{"type":"string"},"action":{"type":"string","enum":["buy","sell"]},"sol_amount":{"type":"number"},"token_amount":{"type":"number"},"price_sol":{"type":"number","nullable":true,"description":"This trade's executed price (sol_amount / token_amount); null on dust / zero-SOL legs"},"price_usd":{"type":"number","nullable":true},"market_price_sol":{"type":"number","nullable":true,"description":"mc-tracker's canonical pool price sampled near this trade's slot — not this trade's price"},"market_price_usd":{"type":"number","nullable":true},"block_time":{"type":"integer","description":"Unix epoch seconds"},"traded_at":{"type":"string","format":"date-time"},"amounts":{"$ref":"#/components/schemas/TradeRawAmounts"},"event":{"$ref":"#/components/schemas/TradeEventFacts"}}},"CopyTradeSubscription":{"type":"object","properties":{"id":{"type":"integer","description":"Numeric rule id (used in /copytrade/subscriptions/{id})"},"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"},"description":"Base58 wallets being mirrored (1-50)"},"min_trade_sol":{"type":"number"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"source_wallets_tracked":{"type":"array","items":{"type":"string"},"nullable":true,"description":"DEPRECATED 2026-10-04 (kept): source wallets that are tracked KOL wallets. Enrichment only under source_admission any_wallet; under kol_only only these can produce a signal. null when the tracking read failed. Since 2026-09-25."},"source_wallets_untracked":{"type":"array","items":{"type":"string"},"nullable":true,"description":"DEPRECATED 2026-10-04 (kept): source wallets that are not tracked KOL wallets. They fire under source_admission any_wallet; under kol_only they never produce a signal."},"operational_state":{"$ref":"#/components/schemas/RhcCopytradeOperationalState"},"source_admission":{"$ref":"#/components/schemas/RhcCopytradeSourceAdmission"},"monitoring_reasons":{"$ref":"#/components/schemas/RhcCopytradeMonitoringReasons"},"warnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"description":"Present only when something needs attention (untracked source wallets, tracking unavailable)."}}}},"parameters":{"Limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}},"headers":{"XRequestId":{"description":"Unique id of this response. On responses built after authentication it is also the `request_id` of the audit-log row for the call, so quote it in a support request. Present on every response of the keyed API.","required":true,"schema":{"type":"string","format":"uuid"},"example":"3f6c1d2e-8a4b-4f7e-9c21-5b0d7e6a9f13"},"XRateLimitLimit":{"description":"Size of the rate-limit window this call was counted against: the daily quota for your tier on data endpoints, the per-minute bucket on `/stream/token` (10) and `/stream/sessions` (30), the hourly allowance for the public demo key. Sent once the key has been authenticated and rate-limited, so it is absent on authentication-stage errors.","schema":{"type":"integer","minimum":0},"example":10000},"XRateLimitRemaining":{"description":"Calls left in that window. `0` on a quota 429.","schema":{"type":"integer","minimum":0},"example":9412},"XRateLimitUsed":{"description":"Calls used in that window (`limit − remaining`).","schema":{"type":"integer","minimum":0},"example":588},"XRateLimitReset":{"description":"When the window resets, as a Unix epoch in SECONDS (next 00:00 UTC for the daily quota; about 60 s ahead for a per-minute bucket).","schema":{"type":"integer"},"example":1791158400},"RetryAfter":{"description":"Seconds to wait before retrying (RFC 9110 delay-seconds, at least 1). Sent on every 429 (quota, concurrency, authentication-failure) and every 503; when the body carries `retry_after_seconds` it is the same value.","required":true,"schema":{"type":"integer","minimum":1},"example":10},"XDataDelay":{"description":"Free-tier only: the feed in this body is delayed by this many seconds (same value as the body's `delay_seconds`). Absent on real-time responses.","schema":{"type":"integer","minimum":1},"example":300},"XMadeOnSolQuotaWarning":{"description":"Free-tier only, past about 70 % of the daily quota: a human-readable usage line with an upgrade link.","schema":{"type":"string"},"example":"150/200 used - upgrade for 50x higher limits: https://madeonsol.com/checkout?tier=PRO"}},"responses":{"BadRequest":{"description":"Invalid path or query parameter, or an invalid request body.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_query":{"summary":"Invalid parameter","value":{"error":"Invalid query parameters","code":"invalid_query","_rid":"eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9"}}}}}},"Unauthorized":{"description":"Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing_key":{"summary":"No Bearer key","value":{"error":"Missing authentication — use API key (Authorization: Bearer msk_...)","hint":"Get a free API key — 200 calls/day, no payment","signup_url":"https://madeonsol.com/developer","docs_url":"https://madeonsol.com/api-docs"}},"bad_format":{"summary":"Malformed key","value":{"error":"Invalid API key format","hint":"Get a free API key — 200 calls/day, no payment","signup_url":"https://madeonsol.com/developer","docs_url":"https://madeonsol.com/api-docs"}}}}}},"TierForbidden":{"description":"Forbidden. One of: the key's tier is below this endpoint's or parameter's gate (`tier_required` with an `upgrade` block); the public demo key used outside its allow-list (`demo_key_endpoint_not_allowed`); an invalid or revoked key; an origin-restricted key called from a disallowed origin (`code` `origin_not_allowed` / `origin_required`). `X-RateLimit-*` headers are present only on `tier_required`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TierRequiredError"},{"$ref":"#/components/schemas/DemoKeyNotAllowedError"},{"$ref":"#/components/schemas/Error"}]},"examples":{"tier_required":{"summary":"Tier below the gate","value":{"error":"tier_required","message":"This endpoint requires ULTRA tier — you're on PRO.","feature":"This endpoint","your_tier":"PRO","required_tier":"ULTRA","upgrade":{"tier":"ULTRA","price_eur_per_month":131,"price_usdc_per_month":149,"daily_limit":100000,"burst_limit":1200,"pitch":"…","url":"https://madeonsol.com/pricing","upgrade_url":"https://madeonsol.com/checkout?tier=ULTRA"},"support":"Priority support: info@madeonsol.com","_rid":"eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9"}},"demo_key":{"summary":"Demo key outside its allow-list","value":{"error":"demo_key_endpoint_not_allowed","message":"The public demo key works on /kol/feed, /deployer-hunter/alerts, and /alpha/leaderboard only. This endpoint requires the PRO plan or higher; a free API key will not unlock it. See https://madeonsol.com/pricing.","endpoint_tier":"PRO","allowed_endpoints":["/api/v1/kol/feed","/api/v1/deployer-hunter/alerts","/api/v1/alpha/leaderboard"],"signup_url":"https://madeonsol.com/developer","upgrade_url":"https://madeonsol.com/checkout?tier=PRO"}},"revoked_key":{"summary":"Invalid or revoked key","value":{"error":"Invalid or revoked API key"}}}}}},"NotFound":{"description":"The addressed resource does not exist or is not yours.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":"Not found","_rid":"eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9"}}}}}},"Conflict":{"description":"The request conflicts with existing state (e.g. a duplicate or a per-tier limit on stored rules).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests. Every 429 carries `Retry-After`. A quota 429 (`rate_limit_exceeded`, with `X-RateLimit-*`), a heavy-query concurrency 429 (`error_kind` `concurrency`/`capacity`), or the per-IP authentication-failure block (30 failed auths/min; plain `error` + `retry_after_seconds`, no `X-RateLimit-*`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RateLimitError"},{"$ref":"#/components/schemas/ConcurrencyLimitError"},{"$ref":"#/components/schemas/Error"}]},"examples":{"daily":{"summary":"Daily quota exhausted","value":{"error":"rate_limit_exceeded","error_kind":"daily","message":"Daily rate limit exceeded — 200/day for BASIC tier. Resets at midnight UTC.","tier":"BASIC","limit":200,"resets_at":"2026-10-05T00:00:00.000Z","upgrade":{"tier":"PRO","price_eur_per_month":43,"price_usdc_per_month":49,"daily_limit":10000,"burst_limit":300,"pitch":"…","url":"https://madeonsol.com/pricing","upgrade_url":"https://madeonsol.com/checkout?tier=PRO"},"datasets":{"pitch":"…","url":"https://madeonsol.com/datasets"}}},"concurrency":{"summary":"Too many heavy queries in flight","value":{"error":"Too many concurrent heavy queries. Up to 8 of these endpoints may be in flight at once per key — retry in a moment, or lower your request concurrency.","error_kind":"concurrency","retry_after_seconds":2,"max_concurrent":8,"_rid":"eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9"}},"auth_failures":{"summary":"Per-IP authentication-failure block","value":{"error":"Too many authentication failures from this IP. Retry in 60s.","retry_after_seconds":42}}}}}},"InternalError":{"description":"Unexpected server error from the route (`Internal server error`, with `_rid`). Safe to retry with backoff. A failed API-key lookup is a 503 `auth_backend_unavailable`, never a 500.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"route":{"summary":"Route error","value":{"error":"Internal server error","_rid":"eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9"}}}}}},"ServiceUnavailable":{"description":"Temporarily unavailable — a Postgres statement timeout while the dataset is under load or maintenance (`statement_timeout`, with `X-RateLimit-*` and `_rid`), or the API-key lookup itself unavailable (`auth_backend_unavailable`, authentication stage: no `X-RateLimit-*`, no `_rid`, not counted as a failed authentication). Always carries `Retry-After`; honour it.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"},"examples":{"statement_timeout":{"summary":"Statement timeout","value":{"error":"Query timed out — this dataset is under load or being maintained. Retry shortly.","error_kind":"statement_timeout","retry_after_seconds":10,"_rid":"eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9"}},"auth_backend":{"summary":"API-key lookup unavailable","value":{"error":"Authentication temporarily unavailable — please retry.","code":"auth_backend_unavailable","error_kind":"auth_backend","retryable":true,"retry_after_seconds":5}}}}}},"AuthBackendUnavailable":{"description":"The API-key or subscription lookup could not be answered (authentication stage). Retryable and not your fault: it is never counted as a failed authentication. Honour `Retry-After`; no `X-RateLimit-*`, no `_rid`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"},"examples":{"auth_backend":{"summary":"API-key lookup unavailable","value":{"error":"Authentication temporarily unavailable — please retry.","code":"auth_backend_unavailable","error_kind":"auth_backend","retryable":true,"retry_after_seconds":5}}}}}}}},"security":[{"BearerAuth":[]}],"paths":{"/rhc/kol/feed":{"get":{"tags":["Robinhood Chain"],"summary":"KOL trade feed on Robinhood Chain (BASIC+; 5-min delay on free)","description":"Every buy/sell from tracked Solana KOLs' verified EVM wallets on Robinhood Chain (chain id 4663), attributed to the effective trading account from our self-hosted node (tx.from normally, or the ERC-4337 userOp sender when bundled — never the bundler) — DEX swaps and launchpad curve snipes, within seconds of execution on PRO and up (the free tier serves this feed on a 5-minute delay). The KOL→EVM mapping is recovered by tracing each KOL's Solana→EVM bridge deposits (deBridge / Relay / Mayan / Wormhole) — a dataset unique to MadeOnSol. Every row is enriched with the token's current MC/liquidity/peak, the deployer's reputation tier, and `mc_multiple_since_trade` (current MC ÷ MC when the KOL bought — 'did the call run'). Tier: **BASIC** (any valid key).","parameters":[{"$ref":"#/components/parameters/Limit"},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"Cursor: return trades strictly older than this ISO timestamp. Pass `next_before` from the previous response to page backwards."},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":200},"description":"PREFERRED pagination (audit F09 follow-up): the `next_cursor` from a previous page — an opaque strict (traded_at, id) keyset, so paging never repeats or skips rows that share a timestamp and progresses with limit=1 through runs of identical timestamps. Malformed or tampered → 400. Cannot be combined with `before=` (400); `before=` stays supported as the legacy bound."},{"name":"action","in":"query","schema":{"type":"string","enum":["buy","sell"]},"description":"Only buys or only sells."},{"name":"kol","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Filter to a single KOL by their EVM wallet address (0x, 40 hex)."},{"name":"min_eth","in":"query","schema":{"type":"number","minimum":0},"description":"Minimum trade size in ETH."},{"name":"exclude_sells","in":"query","schema":{"type":"string","enum":["true","false","1","0"]},"description":"Convenience alias for `action=buy` — drops sells from the feed. Ignored if `action` is set explicitly."},{"name":"min_mc_usd","in":"query","schema":{"type":"number","minimum":0},"description":"Only trades where the token's market cap at trade time was at least this (USD)."},{"name":"max_mc_usd","in":"query","schema":{"type":"number","minimum":0},"description":"Only trades where the token's market cap at trade time was at most this (USD). Combine with `min_mc_usd` for a band; `min_mc_usd` must be <= `max_mc_usd` or the request 400s."},{"name":"token_age_max_min","in":"query","schema":{"type":"integer","minimum":1,"maximum":43200},"description":"Only trades on tokens first seen at most this many minutes ago — the 'fresh launches KOLs are buying' filter. Tokens with unknown first-seen time are excluded."},{"name":"min_kol_winrate","in":"query","schema":{"type":"number","minimum":0,"maximum":1},"description":"Only trades by KOLs whose 7-day win rate (mv_rhc_kol_scores.winrate_7d, CLOSED positions only — sold ≥ 90 % of bought) is at least this (0–1). KOLs with no closed positions have a NULL win rate and are dropped, so `min_kol_winrate=0` is NOT a no-op: it means \"scored\"."},{"name":"strategy","in":"query","schema":{"type":"string","enum":["scalper","day_trader","swing","inactive","unscored"]},"description":"Only trades by KOLs in this hold-time bucket (mv_rhc_kol_scores.strategy). An RHC-specific bucket, not Solana's auto_strategy_tag."}],"responses":{"200":{"description":"`chain` echoes `robinhood`; `next_before` is the pagination cursor; `data_age_seconds` is the age of the newest row.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"trades":{"type":"array","items":{"type":"object","properties":{"evm_address":{"type":"string","description":"The KOL's Robinhood-Chain wallet (0x)."},"kol_name":{"type":"string","nullable":true},"kol_twitter":{"type":"string","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true,"description":"pons | flap | clanker | hood.fun | virtuals | null."},"is_graduated":{"type":"boolean","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"],"description":"Reputation tier of the token's deployer."},"token_age_minutes":{"type":"integer","nullable":true,"description":"Token age at request time (first-seen → now)."},"action":{"type":"string","enum":["buy","sell"]},"eth_amount":{"type":"number","nullable":true,"description":"Trade size in ETH."},"token_amount":{"type":"number","nullable":true},"price_usd_at_trade":{"type":"number","nullable":true},"market_cap_usd_at_trade":{"type":"number","nullable":true,"description":"Token market cap when the KOL traded."},"current_mc_usd":{"type":"number","nullable":true,"description":"Token market cap now."},"peak_mc_usd":{"type":"number","nullable":true,"description":"All-time-high market cap observed since ingestion."},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. uniswap-v4 has no per-pool balances, so its figure is virtual reserves clamped to the PoolManager's total holdings — a provable CEILING, not measured per-pool TVL. All other venues are measured from real balances."},"risk":{"$ref":"#/components/schemas/RhcTokenRiskSummary"},"mc_multiple_since_trade":{"type":"number","nullable":true,"description":"current_mc_usd ÷ market_cap_usd_at_trade — how far the token ran after the KOL's trade."},"dex":{"type":"string","description":"uniswap-v2/v3/v4 or the launchpad name for curve trades."},"pool":{"type":"string","nullable":true},"tx_hash":{"type":"string"},"block_number":{"type":"integer"},"traded_at":{"type":"string","format":"date-time"},"kol_score":{"type":"object","nullable":true,"description":"The KOL's row in mv_rhc_kol_scores. null = no row yet (too few closed positions), never \"not looked up\".","properties":{"winrate_7d":{"type":"number","nullable":true,"description":"0–1, CLOSED positions only (sold ≥ 90 % of bought)."},"winrate_30d":{"type":"number","nullable":true},"strategy":{"type":"string","nullable":true,"description":"Hold-time bucket: scalper | day_trader | swing | inactive | unscored."},"closed_positions_30d":{"type":"integer","nullable":true}}}}}},"count":{"type":"integer"},"filtered_by":{"type":"object","description":"Echo of the KOL-score filters (null = not applied).","properties":{"min_kol_winrate":{"type":"number","nullable":true},"strategy":{"type":"string","nullable":true}}},"matched_kols":{"type":"integer","nullable":true,"description":"KOLs matching min_kol_winrate/strategy; null when neither filter is set."},"data_age_seconds":{"type":"integer","nullable":true},"next_before":{"type":"string","format":"date-time","nullable":true},"next_cursor":{"type":"string","nullable":true,"description":"Opaque keyset cursor for the next (older) page — pass as `cursor=`. PREFERRED over next_before, which is a strict timestamp bound that skips same-timestamp siblings of the boundary row."},"has_more":{"type":"boolean","description":"false only when the feed is exhausted (not merely when the page is short)."},"scan":{"type":"object","description":"Present when a filter had to be applied after the candidate fetch (audit F09): has_more is then false only when the candidates ran out, and scan_truncated=true means the per-request scan budget ran out first — more matches MAY exist past next_cursor.","properties":{"post_filtered":{"type":"boolean"},"scanned":{"type":"integer","description":"Candidate rows examined"},"scan_truncated":{"type":"boolean","description":"The per-request scan budget ran out before `limit` matches — more matches MAY exist past the cursor/offset"},"scan_budget":{"type":"integer"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/kol/scouts/leaderboard":{"get":{"tags":["Robinhood Chain"],"summary":"Scout KOL leaderboard on Robinhood Chain (PRO+)","description":"Robinhood Chain port of `GET /kol/scouts/leaderboard` (2026-10-15). A first touch is a KOL buy of a token no KOL bought before (chain order). Per KOL: first touches in the last 30 days that are at least 4 hours old, how many other KOLs bought within 4 hours (`avg_followers_4h`), and the share that drew ≥3 / ≥5 (`swarm_3plus_pct` / `swarm_5plus_pct`). `scout_tier` S ≥ 40 / A ≥ 25 / B ≥ 15 / C on `swarm_3plus_pct`, null below 30 first touches.\n\nDifferences from Solana: identity is the KOL (a KOL with several EVM addresses is one scout and never its own follower; `evm_addresses` lists them), and KOLs below `min_first_touches` (default 30) are left out instead of listed with a null tier. Computed point in time as of `as_of` (no MV), cached 5 minutes. 503 `scout_scores_unavailable` when the score cannot be computed (never an empty ranking).","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"scout_tier","in":"query","schema":{"type":"string","enum":["S","A","B","C"]}},{"name":"sort","in":"query","schema":{"type":"string","enum":["scout_score","n_first_touches_30d","swarm_3plus_pct","swarm_5plus_pct","avg_followers_4h"],"default":"swarm_3plus_pct"},"description":"`scout_score` is an alias for `swarm_3plus_pct`. Nulls last; ties break on first touches, then kol_id."},{"name":"min_first_touches","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":30},"description":"Leave out KOLs with fewer first touches. Below 30 the tier stays null."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"as_of":{"type":"string","format":"date-time"},"scouts":{"type":"array","items":{"type":"object","properties":{"kol_id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"twitter_url":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"evm_addresses":{"type":"array","items":{"type":"string"}},"as_of":{"type":"string","format":"date-time"},"first_touches_30d":{"type":"integer"},"avg_followers_4h":{"type":"number","nullable":true},"swarm_3plus_pct":{"type":"number","nullable":true},"swarm_5plus_pct":{"type":"number","nullable":true},"scout_tier":{"type":"string","nullable":true,"enum":["S","A","B","C"]}}}},"count":{"type":"integer"},"min_first_touches":{"type":"integer"},"method":{"type":"object","properties":{"tier_min_first_touches":{"type":"integer"},"note":{"type":"string"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Tier gate - PRO required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"scout_scores_unavailable (hood rhc/038 not applied) or scout_scores_temporarily_unavailable.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/kol/leaderboard":{"get":{"tags":["Robinhood Chain"],"summary":"KOL activity leaderboard on Robinhood Chain (BASIC+)","description":"KOLs on Robinhood Chain ranked by trade count, then net ETH flow, over the chosen window. Tier: **BASIC**. (Net ETH is buy−sell flow, not realized PnL.)\n\n**Win-rate ranking (PRO+, 2026-10-14).** `?sort=winrate_7d` or `winrate_30d` ranks KOLs by FIFO win rate instead: the share of fully closed positions (last sell in the window) with positive realized PnL, precomputed from the same 90-day wallet snapshot as `/rhc/kol/{wallet}?include_performance` (identical numbers, see `data_fingerprint`). Only scores computed in the last 2 hours with at least `min_closed` closed positions (default 3) are ranked; ties break on realized PnL. Rows then carry `evm_address`, `winrate_7d`/`winrate_30d`, `closed_positions_*`, `pnl_*_eth`, `median_hold_minutes_30d`, `auto_strategy_tag` and `computed_at` instead of the activity fields, and `period` is ignored. 503 `kol_scores_unavailable` when the precomputed scores cannot be read (never an empty ranking).","parameters":[{"name":"period","in":"query","schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"},"description":"Rolling window (activity ranking only)."},{"$ref":"#/components/parameters/Limit"},{"name":"sort","in":"query","schema":{"type":"string","enum":["trades","winrate_7d","winrate_30d"],"default":"trades"},"description":"`trades` = activity ranking (BASIC). `winrate_7d` / `winrate_30d` = FIFO win-rate ranking (PRO+)."},{"name":"min_closed","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":3},"description":"Win-rate sorts only: minimum fully closed positions in the window to be ranked."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"period":{"type":"string","enum":["24h","7d","30d"]},"leaderboard":{"type":"array","items":{"type":"object","properties":{"kol_name":{"type":"string","nullable":true},"kol_twitter":{"type":"string","nullable":true},"trades":{"type":"integer"},"buys":{"type":"integer"},"sells":{"type":"integer"},"buy_eth":{"type":"number","description":"Total ETH bought in the window."},"sell_eth":{"type":"number","description":"Total ETH sold in the window."},"net_eth":{"type":"number","description":"buy_eth − sell_eth (flow, not realized PnL)."},"tokens_traded":{"type":"integer","description":"Distinct tokens traded in the window."},"last_trade_at":{"type":"string","format":"date-time"},"evm_address":{"type":"string","description":"Win-rate sorts only."},"status":{"type":"string","enum":["available","partial"],"description":"Win-rate sorts only. partial = wallet over the 50,000-trade analysis cap."},"winrate_7d":{"type":"number","nullable":true,"description":"Win-rate sorts only. Percent (0-100)."},"winrate_30d":{"type":"number","nullable":true},"closed_positions_7d":{"type":"integer"},"closed_positions_30d":{"type":"integer"},"pnl_7d_eth":{"type":"number","nullable":true},"pnl_30d_eth":{"type":"number","nullable":true},"median_hold_minutes_30d":{"type":"number","nullable":true},"auto_strategy_tag":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing_trader","hodler"]},"data_fingerprint":{"type":"string","nullable":true},"computed_at":{"type":"string","format":"date-time"}}}},"count":{"type":"integer"},"sort":{"type":"string","enum":["winrate_7d","winrate_30d"],"description":"Win-rate sorts only."},"min_closed":{"type":"integer","description":"Win-rate sorts only."},"scores_meta":{"type":"object","description":"Win-rate sorts only: source, fresh_within_minutes, definition."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"sort=winrate_* requires PRO+.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"kol_scores_unavailable: precomputed win-rate scores cannot be read.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}],"x-madeonsol-feature-tiers":[{"tier":"PRO","feature":"Robinhood Chain KOL win-rate leaderboard (sort=winrate_*)"}]}},"/rhc/kol/hot-tokens":{"get":{"tags":["Robinhood Chain"],"summary":"Consensus tokens — bought by 2+ KOLs on Robinhood Chain (BASIC+)","description":"Robinhood Chain tokens bought by **2 or more distinct tracked KOLs** inside the window (a consensus signal), ranked by KOL-buyer count then buy volume. Each row is enriched with launchpad, deployer reputation tier, graduation status and current market cap. Tier: **BASIC**.","parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["5m","15m","1h","6h","24h"],"default":"1h"},"description":"Rolling consensus window."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"window":{"type":"string","enum":["5m","15m","1h","6h","24h"]},"tokens":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true,"description":"noxa | flap | pons | hood.fun | clanker | null."},"is_graduated":{"type":"boolean","nullable":true},"deployer_tier":{"type":"string","nullable":true,"description":"elite | good | neutral | spammer | null."},"kols_buying":{"type":"integer","description":"Distinct KOL buyers in the window (>= 2)."},"buys":{"type":"integer"},"sells":{"type":"integer"},"buy_eth":{"type":"number"},"net_eth":{"type":"number","description":"buy_eth − sell_eth."},"market_cap_usd":{"type":"number","nullable":true,"description":"Current market cap."},"last_trade_at":{"type":"string","format":"date-time"}}}},"count":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/tokens/hot":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/kol/hot-tokens (BASIC+)","description":"Same handler as `/rhc/kol/hot-tokens` — tokens bought by 2+ tracked KOLs in the window. Added 2026-09-05 because customers guess this URL; `window` passes through. Prefer the canonical path in new code.","parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["5m","15m","1h","6h","24h"],"default":"1h"}}],"responses":{"200":{"description":"Identical to /rhc/kol/hot-tokens.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/tokens/trending":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/kol/hot-tokens (BASIC+)","description":"Same handler as `/rhc/kol/hot-tokens` — tokens bought by 2+ tracked KOLs in the window. Added 2026-09-05 because customers guess this URL; `window` passes through. Prefer the canonical path in new code.","parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["5m","15m","1h","6h","24h"],"default":"1h"}}],"responses":{"200":{"description":"Identical to /rhc/kol/hot-tokens.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/kol/coordination":{"get":{"tags":["Robinhood Chain"],"summary":"KOL coordination / consensus clustering on Robinhood Chain (BASIC+)","description":"Tokens being bought by **multiple distinct tracked KOLs** inside a time window on Robinhood Chain (chain id 4663) — the coordination / consensus signal. Full-window SQL aggregation (including exact 15m), not the 1,000-row hot-token sample; computes window buys grouped by token, distinct KOL wallets counted, then enriched with in-window sells (net-flow / exit math), token metadata, current price/MC/liquidity and the deployer's reputation tier. EVM-native fields (`eth_amount`, `evm_address`, 0x). Ranked by distinct KOL count, then buy ETH, then recency. Tier: **BASIC** (any valid key).","parameters":[{"name":"period","in":"query","schema":{"type":"string","enum":["15m","1h","6h","24h","7d"],"default":"24h"},"description":"Rolling window (alias: `window`). Filters on `traded_at`."},{"name":"min_kols","in":"query","schema":{"type":"integer","minimum":2,"maximum":50,"default":2},"description":"Minimum distinct KOL buyers for a token to qualify."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"min_mc_usd","in":"query","schema":{"type":"number","minimum":0,"maximum":1000000000000},"description":"Filter on market cap at the first KOL buy (USD). Tokens with unknown MC at first buy are excluded when a band is set."},{"name":"max_mc_usd","in":"query","schema":{"type":"number","minimum":0,"maximum":1000000000000},"description":"Upper bound on MC at first KOL buy (USD). Must be ≥ min_mc_usd."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"coordination":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"]},"token_age_minutes":{"type":"integer","nullable":true},"kol_count":{"type":"integer","description":"Distinct KOL buyers in the window (≥ min_kols)."},"total_buys":{"type":"integer"},"buy_eth":{"type":"number","description":"Total ETH bought by KOLs in the window."},"sell_eth":{"type":"number","description":"Total ETH sold by those KOLs in the window."},"net_eth":{"type":"number","description":"buy_eth − sell_eth."},"signal":{"type":"string","enum":["accumulating","distributing"],"description":"accumulating when net_eth ≥ 0, else distributing."},"exited_count":{"type":"integer","description":"KOLs whose in-window sells exceed their buys."},"holders_count":{"type":"integer","description":"kol_count − exited_count."},"first_buy_at":{"type":"string","format":"date-time"},"last_buy_at":{"type":"string","format":"date-time"},"time_to_consensus_sec":{"type":"integer","description":"Seconds between the first and last KOL buy."},"market_cap_usd_at_first_buy":{"type":"number","nullable":true},"current_mc_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. v4_virtual_ceiling = uniswap-v4 virtual reserves clamped to the PoolManager's total holdings — a provable ceiling, not measured per-pool TVL."},"kols":{"type":"array","items":{"type":"object","properties":{"evm_address":{"type":"string","description":"The KOL's Robinhood-Chain wallet (0x)."},"name":{"type":"string","nullable":true},"twitter_url":{"type":"string","nullable":true},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"exited":{"type":"boolean","description":"sell_eth > buy_eth for this KOL."}}}}}}},"count":{"type":"integer"},"period":{"type":"string","enum":["15m","1h","6h","24h","7d"]},"min_kols":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters (e.g. min_mc_usd > max_mc_usd).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/kol/first-touches":{"get":{"tags":["Robinhood Chain"],"summary":"Earliest KOL entry per token on Robinhood Chain (BASIC+)","description":"The **first time any tracked KOL bought** each token on Robinhood Chain — an early-entry / discovery signal. Computed read-time from `rhc_kol_trades` (a DISTINCT-ON per token yielding the global earliest KOL buy), enriched with token metadata and current/peak MC. EVM-native fields (`eth_amount`, `evm_address`, `tx_hash`, 0x). Tier: **BASIC** — but below the API-access tiers (PRO/ULTRA/BUSINESS) `limit` is clamped to 20, and the first KOL's `evm_address` is revealed only to **ULTRA/BUSINESS**.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Clamped to 20 for keys below the API-access tiers."},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only first-touches at/after this ISO8601 timestamp."},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"Cursor: only first-touches before this ISO8601 timestamp. Pass `next_before` to page."},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":200},"description":"PREFERRED pagination (audit F09 follow-up): the `next_cursor` from a previous page — an opaque strict (first_buy_at, id) keyset, so paging never repeats or skips rows that share a timestamp and progresses with limit=1 through runs of identical timestamps. Malformed or tampered → 400. Cannot be combined with `before=` (400); `before=` stays supported as the legacy bound."},{"name":"min_eth","in":"query","schema":{"type":"number","minimum":0,"maximum":100000},"description":"Minimum ETH size of the first KOL buy (alias: `min_sol`)."},{"name":"token_age_max_min","in":"query","schema":{"type":"integer","minimum":1,"maximum":43200},"description":"Only tokens younger than N minutes at first touch."},{"name":"launchpad","in":"query","schema":{"type":"string","pattern":"^[a-zA-Z0-9._-]{1,32}$"},"description":"Filter to one launchpad."},{"name":"min_mc_usd","in":"query","schema":{"type":"number","minimum":0,"maximum":1000000000000},"description":"Minimum MC at first buy (USD)."},{"name":"max_mc_usd","in":"query","schema":{"type":"number","minimum":0,"maximum":1000000000000},"description":"Maximum MC at first buy (USD; alias: `mc_max`). Must be ≥ min_mc_usd."}],"responses":{"200":{"description":"`next_before` is the pagination cursor (oldest first_buy_at on the page); `data_age_seconds` is the age of the newest event.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"events":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"first_buy_at":{"type":"string","format":"date-time"},"eth_amount":{"type":"number","nullable":true,"description":"Size of the first KOL buy in ETH."},"token_amount":{"type":"number","nullable":true},"tx_hash":{"type":"string"},"token_age_minutes":{"type":"integer","nullable":true,"description":"Token age at first touch."},"market_cap_usd_at_first_buy":{"type":"number","nullable":true},"price_usd_at_first_buy":{"type":"number","nullable":true},"current_mc_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"first_kol":{"type":"object","properties":{"evm_address":{"type":"string","description":"The KOL's Robinhood-Chain wallet (0x). Present only for ULTRA/BUSINESS keys."},"name":{"type":"string","nullable":true},"twitter_url":{"type":"string","nullable":true}}}}}},"count":{"type":"integer"},"next_before":{"type":"string","format":"date-time","nullable":true},"next_cursor":{"type":"string","nullable":true,"description":"Opaque keyset cursor for the next (older) page — pass as `cursor=`. PREFERRED over next_before, which is a strict timestamp bound that skips same-timestamp siblings of the boundary row. null on a server that predates the rhc_kol_first_touches_page migration (legacy path: no id tiebreak)."},"has_more":{"type":"boolean","nullable":true,"description":"Exact (limit+1 probe). null when the server is on the legacy path and cannot tell — page on next_before until an empty page."},"data_age_seconds":{"type":"integer","nullable":true}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters (e.g. min_mc_usd > max_mc_usd).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/kol/{wallet}":{"get":{"tags":["Robinhood Chain"],"summary":"Single KOL profile on Robinhood Chain (BASIC+)","description":"Aggregate stats over one KOL's last 200 RHC trades plus their 50 most recent trades. Tier: **BASIC**.\n\n**Win rate and strategy (opt-in, PRO+, 2026-10-14).** `?include_performance=true` adds `performance`: `winrate_7d` / `winrate_30d` (percent of fully closed positions with positive realized PnL), `closed_positions_*`, `pnl_*_eth`, `median_hold_minutes_30d` and `auto_strategy_tag` (`scalper` < 30 min, `day_trader` < 6 h, `swing_trader` < 24 h, else `hodler`: the Solana `mv_kol_scores` thresholds). Computed from the same 90-day FIFO wallet snapshot as `/rhc/wallet/{address}/pnl`. A position counts in a window when it is fully closed with an observable buy and its last sell falls in the window. Empty windows are `null`, never 0. `status`: `available`, `partial` (wallet over the 50,000-trade analysis cap) or `unavailable` (`reason`), and a failed read never takes the profile down. BASIC with the opt-in → 403.","parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"KOL EVM wallet address (0x, 40 hex)."},{"name":"include_performance","in":"query","schema":{"type":"boolean","default":false},"description":"PRO+. Adds `performance` (7d/30d win rate, realized PnL and strategy classification from the FIFO wallet snapshot)."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"evm_address":{"type":"string"},"kol_name":{"type":"string","nullable":true},"kol_twitter":{"type":"string","nullable":true},"stats":{"type":"object","properties":{"trades":{"type":"integer"},"buys":{"type":"integer"},"sells":{"type":"integer"},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"net_eth":{"type":"number"},"tokens_traded":{"type":"integer"},"window":{"type":"string","example":"last 200 trades"}}},"trades":{"type":"array","description":"50 most recent trades (token, action, eth_amount, price/MC at trade, dex, tx_hash, traded_at). Each row carries `liquidity_basis` (`v4_virtual_ceiling` | `measured`) — uniswap-v4 liquidity_usd is a virtual-reserve ceiling, not measured per-pool TVL.","items":{"type":"object"}},"performance":{"type":"object","description":"Only with `include_performance=true` (PRO+).","properties":{"status":{"type":"string","enum":["available","partial","unavailable"]},"reason":{"type":"string","nullable":true,"description":"Set when unavailable: source_error, no_wallet_trades_in_window, no_sized_trades."},"winrate_7d":{"type":"number","nullable":true,"description":"Percent (0-100, 2 dp) of fully closed positions whose last sell is in the last 7 days with positive realized PnL. null = none closed."},"winrate_30d":{"type":"number","nullable":true},"closed_positions_7d":{"type":"integer"},"closed_positions_30d":{"type":"integer"},"pnl_7d_eth":{"type":"number","nullable":true},"pnl_30d_eth":{"type":"number","nullable":true},"windows":{"type":"object","description":"Per window (`7d`, `30d`): closed_positions, wins, losses, breakeven, winrate, realized_pnl_eth."},"median_hold_minutes_30d":{"type":"number","nullable":true},"auto_strategy_tag":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing_trader","hodler"]},"strategy_reason":{"type":"string","nullable":true},"window_days":{"type":"integer"},"definition":{"type":"string"},"notes":{"type":"object","description":"Snapshot provenance: window_start, attribution_complete_from, data_through, data_fingerprint, cost_basis_observable_from, trades_seen/analyzed/unattributed/unsized, partial_reason, cache_hit."}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid include_performance (expected true or false).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"include_performance requires PRO+.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No RHC activity found for this address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}],"x-madeonsol-feature-tiers":[{"tier":"PRO","feature":"Robinhood Chain KOL performance (include_performance)"}]}},"/rhc/trades":{"get":{"tags":["Robinhood Chain"],"summary":"Robinhood Chain DEX trade tape (PRO+)","description":"Every Uniswap v2/v3/v4 swap on chain 4663 from our self-hosted node, within seconds of execution. Each row carries the **real trader wallet** (`trader_eoa` — the userOp sender on ERC-4337 transactions, never the router or the bundler), gas/ordering for MEV analysis, pool state, and flags for whether the trader is a tracked KOL or a known deployer. Cursor via `next_before`. Tier: **PRO+**.\n\n**Where the rows come from** (*added 2026-08-29*): closed months older than the newest three move from Postgres to a Parquet archive; pages are split at `history.postgres_from` (ISO) — rows at/after it from Postgres, older rows from the archive reader, same ordering and `before` cursor. `history.archive_used`, `archive_months`, `archive_available` (`null` = not configured) and `truncated` (older history requested but the archive did not answer — retry rather than treating `has_more:false` as the end) mirror `/tokens/{mint}/trades`. Header `X-Read-Source`: `core`, `core+archive` or `archive`.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"token","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Filter to one token address."},{"name":"dex","in":"query","schema":{"type":"string","enum":["uniswap-v2","uniswap-v3","uniswap-v4"]},"description":"Filter by DEX version."},{"name":"action","in":"query","schema":{"type":"string","enum":["buy","sell"]}},{"name":"min_eth","in":"query","schema":{"type":"number","minimum":0},"description":"Minimum trade size in ETH."},{"name":"before","in":"query","schema":{"type":"string"},"description":"Opaque cursor from next_before; a bare ISO block_time is also accepted for backward compatibility (loses intra-second position)."}],"responses":{"200":{"description":"OK. `next_before` is the opaque pagination cursor — pass it back as `before` to page losslessly; `has_more` says whether another page exists.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"trades":{"type":"array","items":{"type":"object","properties":{"block_number":{"type":"integer"},"block_time":{"type":"string","format":"date-time"},"tx_hash":{"type":"string"},"log_index":{"type":"integer"},"dex":{"type":"string"},"pool":{"type":"string"},"trader":{"type":"string","nullable":true,"description":"Swap-log recipient — the ROUTER for aggregated swaps. Use trader_eoa for wallet analytics."},"trader_eoa":{"type":"string","nullable":true,"description":"Authoritative trader wallet. Normally tx.from; on ERC-4337 transactions this is the userOp sender (the account that actually traded) and tx.from — the bundler — is not returned."},"router":{"type":"string","nullable":true,"description":"Router/aggregator contract (tx.to)."},"pair_status":{"type":"string","enum":["attributed","quote_quote","equity_equity","unsupported_pair"],"description":"Pool-pair attribution state of the swap (present only when recorded; requires the rhc/030 column and the server read flag). `attributed`: one side is a recognized quote, so `token_address`/`action` are set. `quote_quote` / `equity_equity` / `unsupported_pair`: no basis to call either side the token, so `token_address`/`action` are null. Absent = not recorded (older rows, curve-event rows, archive rows) and never implies attributed."},"token_address":{"type":"string","nullable":true},"action":{"type":"string","enum":["buy","sell"],"nullable":true},"eth_amount":{"type":"number","nullable":true},"price_native":{"type":"number","nullable":true},"price_usd":{"type":"number","nullable":true},"mc_usd_at_trade":{"type":"number","nullable":true},"gas_price":{"type":"number","nullable":true,"description":"Effective gas price, gwei."},"tx_index":{"type":"integer","nullable":true,"description":"Transaction position within the block (ordering / sandwich detection)."},"method_selector":{"type":"string","nullable":true,"description":"4-byte calldata selector."},"liquidity":{"type":"number","nullable":true,"description":"v3/v4 in-range liquidity at the trade."},"launchpad":{"type":"string","nullable":true},"is_kol":{"type":"boolean","description":"True if trader_eoa is a tracked KOL wallet."},"kol_name":{"type":"string","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"],"description":"Set if trader_eoa is a known deployer."}}}},"count":{"type":"integer"},"has_more":{"type":"boolean","description":"True when another page exists beyond this one."},"next_before":{"type":"string","nullable":true,"description":"Opaque (block_time, id) keyset cursor for the next page; null when has_more is false."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/equities":{"get":{"tags":["Robinhood Chain"],"summary":"Tokenized stocks & ETFs on Robinhood Chain (BASIC+)","description":"Every official Robinhood tokenized equity (stocks + ETFs, e.g. NVDA, SPY, AAPL) with live price / MC / liquidity and 24h trades / ETH volume / buyer-seller split. **Identity is the issuer BEACON, not the name**: a token is listed only if its contract is an EIP-1967 beacon proxy on Robinhood's issuer beacon 0xe10b6f6b…151b00, read from our own node (scripts/rhc-classify-tokens.mjs, every 10 min). The day this shipped there were 20 fake 'GameStop • Robinhood Token' contracts and 8 fake NVDAs with the exact official suffix — none appear here. Tier: **BASIC** (discovery surface; per-token drill-downs keep their own gates). 24h stats cached 60 s.","parameters":[{"name":"sort","in":"query","schema":{"type":"string","enum":["volume","trades","market_cap","last_trade","symbol"],"default":"volume"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":300,"default":100}},{"name":"symbol","in":"query","schema":{"type":"string"},"description":"Exact ticker, case-insensitive (NVDA)."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Substring of symbol or name."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"equities":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"Underlying name with the '• Robinhood Token' suffix stripped (display only)."},"onchain_name":{"type":"string","nullable":true},"asset_class":{"type":"string","enum":["equity"]},"verified":{"type":"boolean","description":"Always true here — beacon-verified by construction."},"issuer_beacon":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"listed_at":{"type":"string","format":"date-time","nullable":true},"price_usd":{"type":"number","nullable":true},"price_native":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","nullable":true},"primary_dex":{"type":"string","nullable":true},"primary_pool":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true},"trades_24h":{"type":"integer"},"volume_eth_24h":{"type":"number"},"buys_24h":{"type":"integer"},"sells_24h":{"type":"integer"},"buyers_24h":{"type":"integer"},"sellers_24h":{"type":"integer"}}}},"count":{"type":"integer"},"total_equities":{"type":"integer"},"sort":{"type":"string"},"identity":{"type":"object","description":"method:'beacon', issuer_beacon, note."},"stats_window":{"type":"string","enum":["24h"]},"stats_as_of":{"type":"string","format":"date-time"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters (code invalid_query).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/tokens/new":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/tokens?sort=newest (PRO+)","description":"The launch feed: newest tokens first by first_seen_at. Same handler as /rhc/tokens with sort pinned; since=, limit, asset_class, launchpad and min_* pass through. Tier: **PRO+** (inherits the /rhc/tokens gate).","parameters":[{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"asset_class","in":"query","schema":{"type":"string","enum":["equity","other"]}}],"responses":{"200":{"description":"Identical to /rhc/tokens?sort=newest.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"tokens":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"asset_class":{"type":"string","nullable":true,"enum":["equity"],"description":"'equity' = beacon-verified Robinhood tokenized stock/ETF; null = everything else."},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"deployer_address":{"type":"string","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"]},"price_usd":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"peak_mc_at":{"type":"string","format":"date-time","nullable":true},"drawdown_from_peak_pct":{"type":"integer","nullable":true,"description":"Percent below all-time-high MC."},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"]},"primary_dex":{"type":"string","nullable":true},"primary_pool":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true}}}},"count":{"type":"integer"},"sort":{"type":"string","enum":["newest"]},"since":{"type":"string","format":"date-time","nullable":true},"next_since":{"type":"string","format":"date-time","nullable":true,"description":"Feed back as since= to poll for launches newer than this page."},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/recent":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/tokens?sort=newest (PRO+)","description":"Same as /rhc/tokens/new.","parameters":[{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Identical to /rhc/tokens?sort=newest.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"tokens":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"asset_class":{"type":"string","nullable":true,"enum":["equity"],"description":"'equity' = beacon-verified Robinhood tokenized stock/ETF; null = everything else."},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"deployer_address":{"type":"string","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"]},"price_usd":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"peak_mc_at":{"type":"string","format":"date-time","nullable":true},"drawdown_from_peak_pct":{"type":"integer","nullable":true,"description":"Percent below all-time-high MC."},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"]},"primary_dex":{"type":"string","nullable":true},"primary_pool":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true}}}},"count":{"type":"integer"},"sort":{"type":"string","enum":["newest"]},"since":{"type":"string","format":"date-time","nullable":true},"next_since":{"type":"string","format":"date-time","nullable":true,"description":"Feed back as since= to poll for launches newer than this page."},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens":{"get":{"tags":["Robinhood Chain"],"summary":"Robinhood Chain token discovery (PRO+)","description":"Live-priced Robinhood Chain tokens with market cap, liquidity, peak MC + drawdown, launchpad, and deployer reputation tier. Sortable and filterable. Filters the candidate query cannot express are served by a bounded scan (`scan` block) — a short or empty page never implies exhaustion unless has_more is false. Tier: **PRO+**.","parameters":[{"$ref":"#/components/parameters/Limit"},{"name":"sort","in":"query","schema":{"type":"string","enum":["last_trade","market_cap","liquidity","peak_mc","newest","oldest"],"default":"last_trade"},"description":"Ordering (all descending unless noted): most recent trade, market cap, current liquidity, all-time-high MC, newest (first_seen_at DESC — the launch feed; unpriced tokens list with null price fields; response adds next_since), or oldest (first_seen_at ASC — a resumable backfill walk through the full historical token set; response adds next_after + has_more)."},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only with sort=newest: tokens first seen at or after this ISO8601 time (inclusive — first_seen_at is block-second granularity and several tokens can share one second, so the cursor row repeats; dedupe on token_address). Feed back the response's next_since to poll for launches."},{"name":"after","in":"query","schema":{"type":"string","format":"date-time"},"description":"LEGACY — prefer cursor=. Only with sort=oldest: tokens first seen at or after this ISO8601 time (inclusive). With more same-second tokens than `limit` it cannot advance — use cursor=. Feed back next_after (dedupe on token_address); stop when has_more is false."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Only with sort=oldest (PREFERRED over after=): the next_cursor from a previous page — a strict compound (first_seen_at, address) keyset, so the walk never repeats or skips a row and progresses with limit=1 through runs of identical timestamps. Malformed → 400; cannot be combined with after=."},{"name":"has_pool","in":"query","schema":{"type":"string","enum":["true","false"]},"description":"Filter on whether the token has a discovered pool (primary_pool from rhc_token_prices non-null). A token can be listed (first_seen_at set) before its pool is found — pair with sort=oldest&has_pool=true for a one-time backfill of every RHC token with a pool."},{"name":"asset_class","in":"query","schema":{"type":"string","enum":["equity","other"]},"description":"equity = beacon-verified Robinhood tokenized stock/ETF (issuer beacon read from our node — never the name); other = everything else."},{"name":"min_mc_usd","in":"query","schema":{"type":"number","minimum":0},"description":"Minimum current market cap (USD)."},{"name":"min_liquidity_usd","in":"query","schema":{"type":"number","minimum":0},"description":"Minimum current liquidity (USD)."},{"name":"launchpad","in":"query","schema":{"type":"string"},"description":"Filter by launchpad: pons, flap, clanker, hood.fun, noxa, virtuals."},{"name":"max_age_days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30},"description":"Value sorts only (market_cap / liquidity / peak_mc): exclude tokens whose last trade is older than this many days. Default 30 — a screener ranks what is tradeable; widen explicitly for dormant tokens."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"tokens":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true,"description":"From rhc_tokens. Added 2026-09-08 — needed to parse on-chain raw amounts correctly."},"asset_class":{"type":"string","nullable":true,"enum":["equity"],"description":"`equity` = beacon-verified Robinhood tokenized stock/ETF (issuer beacon read from our node — never the name); null = everything else."},"first_seen_at":{"type":"string","format":"date-time","nullable":true,"description":"When OUR node first saw the token trade or get a pool — not the contract creation block."},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"deployer_address":{"type":"string","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"]},"price_usd":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"peak_mc_at":{"type":"string","format":"date-time","nullable":true},"drawdown_from_peak_pct":{"type":"integer","nullable":true,"description":"Percent below all-time-high MC."},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. uniswap-v4 has no per-pool balances, so its figure is virtual reserves clamped to the PoolManager's total holdings — a provable CEILING, not measured per-pool TVL. All other venues are measured from real balances."},"primary_dex":{"type":"string","nullable":true},"primary_pool":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true}}}},"count":{"type":"integer"},"sort":{"type":"string"},"since":{"type":"string","format":"date-time","nullable":true,"description":"sort=newest only — echoes the request's since=."},"next_since":{"type":"string","format":"date-time","nullable":true,"description":"sort=newest only. Feed back as since= to poll for newer launches."},"note":{"type":"string","description":"sort=newest / sort=oldest only — constant explanation of the first_seen_at semantics and the cursor contract."},"after":{"type":"string","format":"date-time","nullable":true,"description":"sort=oldest only — echoes the request's after=."},"has_more":{"type":"boolean","description":"sort=oldest only — false ONLY when the candidates ran out (never inferred from a short filtered page)."},"cursor":{"type":"string","nullable":true,"description":"sort=oldest only — echoes the request's cursor=."},"next_cursor":{"type":"string","nullable":true,"description":"sort=oldest only (PREFERRED). Feed back as cursor= — strict (first_seen_at, address) keyset; null = walk complete."},"next_after":{"type":"string","format":"date-time","nullable":true,"description":"sort=oldest only, LEGACY inclusive cursor. Feed back as after= (dedupe on token_address). When a scanned page matched nothing it advances to the last scanned row."},"scan":{"type":"object","description":"Present when a filter (launchpad / has_pool / price criteria) had to be scanned after the candidate fetch (audit F09): has_more is then false only when the candidates ran out, and scan_truncated=true means the per-request budget ran out first — more matches MAY exist.","properties":{"post_filtered":{"type":"boolean"},"scanned":{"type":"integer","description":"Candidate rows examined"},"scan_truncated":{"type":"boolean","description":"The per-request scan budget ran out before `limit` matches — more matches MAY exist past the cursor/offset"},"scan_budget":{"type":"integer"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}":{"get":{"tags":["Robinhood Chain"],"summary":"Robinhood Chain token bundle (BASIC+)","description":"Full snapshot for one token: metadata, live price/MC/FDV, peak MC + drawdown, graduation status, deployer reputation block (+ other tokens by the same deployer), KOL activity summary, and pool inventory with reserves. Tier: **BASIC**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"graduated_pool":{"type":"string","nullable":true},"graduated_at":{"type":"string","format":"date-time","nullable":true},"deployer_address":{"type":"string","nullable":true},"deployer_identity_status":{"type":"string","enum":["known","unresolved","unavailable"],"description":"known = the token row names its creator (identity does not depend on reputation); unresolved = no creator recorded; unavailable = the token lookup failed"},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"token_age_minutes":{"type":"integer","nullable":true},"price_usd":{"type":"number","nullable":true},"price_native":{"type":"number","nullable":true},"price_observed_at":{"type":"string","format":"date-time","nullable":true,"description":"The last trade that set the native price — the price's own age anchor (same stale-price contract as GET /token/{mint})"},"price_age_seconds":{"type":"integer","nullable":true},"price_is_stale":{"type":"boolean","description":"true when price_age_seconds > 900"},"price_updated_at":{"type":"string","format":"date-time","nullable":true,"description":"Row write time — can move without a trade (USD re-derivation); not a price-age anchor"},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"peak_mc_at":{"type":"string","format":"date-time","nullable":true},"drawdown_from_peak_pct":{"type":"integer","nullable":true},"total_supply_raw":{"type":"string","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. uniswap-v4 has no per-pool balances, so its figure is virtual reserves clamped to the PoolManager's total holdings — a provable CEILING, not measured per-pool TVL."},"liquidity_note":{"type":"string","description":"Human-readable statement of the uniswap-v4 ceiling semantics; constant."},"liquidity_source":{"type":"string","enum":["pool_balances","v4_virtual_ceiling","bonding_curve_reserve","unknown_venue"],"description":"Where liquidity_usd comes from: pool_balances = uniswap-v2/v3 pool token balances; v4_virtual_ceiling = uniswap-v4 virtual reserves clamped to the PoolManager (a ceiling); bonding_curve_reserve = 2x a launchpad curve quote reserve from contract state (pons-v2, flap, hood.fun, bags); unknown_venue = no recognised primary venue."},"liquidity_status":{"type":"string","enum":["available","verified_zero","unavailable"],"description":"available = positive figure; verified_zero = explicit 0 from chain state; unavailable = liquidity_usd is null (unknown, not yet measured, unresolved quote asset, or graduated curve awaiting its pool figure). Null never means zero."},"primary_dex":{"type":"string","nullable":true},"primary_pool":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true},"deployer":{"type":"object","nullable":true,"description":"Deployer identity + reputation. Non-null whenever the creator address is known, even before the reputation view has it (history_status pending).","properties":{"identity_status":{"type":"string","enum":["known"]},"history_status":{"type":"string","enum":["computed","pending","unavailable"],"description":"computed = in the reputation view · pending = known creator, reputation not computed yet (NOT \"new\") · unavailable = the reputation lookup failed"},"address":{"type":"string"},"tier":{"type":"string","enum":["elite","good","neutral","spammer"]},"tokens_deployed":{"type":"integer"},"graduation_rate":{"type":"number","nullable":true},"runner_rate":{"type":"number","nullable":true},"runners":{"type":"integer"},"best_peak_mc_usd":{"type":"number","nullable":true},"launchpads":{"type":"array","items":{"type":"string"}}}},"deployer_other_tokens":{"type":"array","items":{"type":"string"},"description":"Up to 10 other tokens by the same deployer (symbol or address)."},"kol_activity":{"type":"object","description":"Complete aggregate over the token's whole KOL history (rhc_token_kol_activity), keyed on the stable KOL id — two KOLs sharing a display name no longer collapse. If the aggregate is unavailable it falls back to a LABELLED newest-200 sample (basis latest_200_trades, complete=false when truncated, sample_size).","properties":{"distinct_kols":{"type":"integer","description":"Distinct KOL ids (not display names)"},"names":{"type":"array","items":{"type":"string"}},"buys":{"type":"integer"},"sells":{"type":"integer"},"net_eth":{"type":"number"},"distinct_wallets":{"type":"integer"},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"participants":{"type":"array","description":"Up to 20 KOLs, most recent first","items":{"type":"object","properties":{"kol_id":{"type":"string"},"name":{"type":"string","nullable":true},"twitter_url":{"type":"string","nullable":true},"buys":{"type":"integer"},"sells":{"type":"integer"},"last_trade_at":{"type":"string","format":"date-time"}}}},"identity":{"type":"string","enum":["kol_wallet_id"]},"window":{"type":"object","properties":{"kind":{"type":"string","enum":["all_time","latest_trades"]},"first_trade_at":{"type":"string","format":"date-time","nullable":true},"last_trade_at":{"type":"string","format":"date-time","nullable":true}}},"basis":{"type":"string","description":"all_trades (complete aggregate) or latest_N_trades (fallback sample)"},"complete":{"type":"boolean"},"sample_size":{"type":"integer","description":"Fallback sample only"}}},"degraded_fields":{"type":"array","items":{"type":"string"},"description":"Blocks whose lookup failed (e.g. deployer_other_tokens) — their values are unknown, not empty"},"pools":{"type":"array","description":"Up to 20 pools with reserves/liquidity/sqrt_price. Each entry carries `liquidity_basis` (`v4_virtual_ceiling` | `measured`) for its own `liquidity_usd`.","items":{"type":"object"}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Token not found on Robinhood Chain.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/tokens/{address}/candles":{"get":{"tags":["Robinhood Chain"],"summary":"OHLC candles on Robinhood Chain (PRO+)","description":"Chronological OHLC candles aggregated from the 1-minute base series: price + market-cap OHLC, close liquidity, volume with buy/sell split, and trade/buy/sell counts. Tier: **PRO+**, with every field and the full available history on PRO (unlike the Solana `/tokens/{mint}/candles`, which limits PRO to 30 days). Windows over 999 buckets are paged newest-first on the timeframe grid; `truncated` reports a page budget that ran out.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address."},{"name":"tf","in":"query","schema":{"type":"string","enum":["1m","5m","15m","1h","4h","1d"],"default":"1m"},"description":"Candle timeframe, rolled up server-side from the 1-minute base series. Also accepted as `timeframe`. Defaults to `1m` (this endpoint's original behaviour), unlike the Solana `/tokens/{mint}/candles` route which defaults to `1h`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1500,"default":240},"description":"Number of candles (most recent first, returned chronological). 1500 = one full day of 1m bars with margin."},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"},"description":"Lower bound on bucket_start (inclusive). If neither `from` nor `to` is given, the window is anchored on the token's most recent candle — so quiet tokens still return their last `limit` candles."},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"},"description":"Upper bound on bucket_start (exclusive)."}],"responses":{"200":{"description":"OK. Candles ordered oldest→newest.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"timeframe":{"type":"string","enum":["1m","5m","15m","1h","4h","1d"],"example":"1m","description":"Echoes the timeframe actually served."},"from":{"type":"string","format":"date-time","nullable":true},"to":{"type":"string","format":"date-time","nullable":true},"candles":{"type":"array","items":{"type":"object","properties":{"bucket_start":{"type":"string","format":"date-time"},"open_price_usd":{"type":"number"},"high_price_usd":{"type":"number"},"low_price_usd":{"type":"number"},"close_price_usd":{"type":"number"},"open_mc_usd":{"type":"number","nullable":true},"high_mc_usd":{"type":"number","nullable":true},"low_mc_usd":{"type":"number","nullable":true},"close_mc_usd":{"type":"number","nullable":true},"close_liquidity_usd":{"type":"number","nullable":true},"close_supply":{"type":"number","nullable":true},"volume_usd":{"type":"number"},"volume_buy_usd":{"type":"number","nullable":true},"volume_sell_usd":{"type":"number","nullable":true},"trades":{"type":"integer"},"buy_count":{"type":"integer","nullable":true},"sell_count":{"type":"integer","nullable":true},"dex":{"type":"string","nullable":true},"pool_address":{"type":"string","nullable":true}}}},"count":{"type":"integer"},"truncated":{"type":"boolean","description":"true when the 3-page budget (up to 999 buckets each) ran out before `limit` candles or `from` were reached."},"covered_from":{"type":"string","format":"date-time","nullable":true,"description":"Oldest instant actually searched; equals `from` when the whole window was scanned."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/kol-consensus":{"get":{"tags":["Robinhood Chain"],"summary":"KOL consensus on a Robinhood Chain token (PRO+)","description":"How the tracked-KOL cohort is positioned on a token: distinct KOL buyers vs sellers, exit rate (bought AND sold), net ETH flow, median entry MC, and first-touch wallet/time. Full parity with the Solana `/tokens/{mint}/kol-consensus` (sourced from `rhc_kol_trades`), EVM-denominated (`net_flow_eth`). ULTRA additionally returns the `buyers` and `exited` wallet lists. Tier: **PRO+**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."}],"responses":{"200":{"description":"OK. `consensus` is null when no tracked KOL has traded the token.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"current_mc_usd":{"type":"number","nullable":true},"current_price_usd":{"type":"number","nullable":true},"consensus":{"type":"object","nullable":true,"properties":{"total_kol_buyers":{"type":"integer"},"total_kol_sellers":{"type":"integer"},"kol_exit_rate":{"type":"number","description":"Fraction of KOL buyers who also sold (0–1)."},"net_flow_eth":{"type":"number"},"total_buy_eth":{"type":"number"},"total_sell_eth":{"type":"number"},"first_kol_buy_at":{"type":"string","format":"date-time","nullable":true},"last_kol_buy_at":{"type":"string","format":"date-time","nullable":true},"first_touch_wallet":{"type":"string","nullable":true},"first_touch_at":{"type":"string","format":"date-time","nullable":true},"median_entry_mc_usd":{"type":"number","nullable":true,"description":"Median MC at KOL buy — over the buys that carried an MC-at-trade (see entry_mc_samples). Null when the RHC pricer withheld MC under its liquidity gate."},"entry_mc_samples":{"type":"integer","description":"Number of buys with a market_cap_usd_at_trade — the median's sample size."},"total_trades":{"type":"integer"},"buyers":{"type":"array","items":{"type":"string"},"description":"ULTRA only — distinct KOL buyer wallets."},"exited":{"type":"array","items":{"type":"string"},"description":"ULTRA only — KOL wallets that bought and sold."}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/buyer-quality":{"get":{"tags":["Robinhood Chain"],"summary":"Early-buyer quality on a Robinhood Chain token (BASIC+)","description":"A 0–100 quality read on a token's earliest distinct buyer cohort (first 20), derived live from `rhc_trades` and enriched with `mv_rhc_alpha_wallets` history. Full parity with the Solana scorer: win-rate, KOL-presence, bot-domination and **bundle-buyer** legs (a bundled early buyer in the top 10 costs −5; a heavily bundled cohort of >10 costs −15), plus the **dump-cluster ensemble** — `dump_cluster_count` counts early buyers that repeatedly sit in launches that crashed off their own peak (rolling 42-day model, out-of-sample validated on RHC). Dump-cluster is **informational**: it flags the pattern but does not move the score. Tier: **BASIC** (any valid key).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"include_balances","in":"query","schema":{"type":"boolean","default":false},"description":"PRO+ (2026-10-15): add `dump_cluster_held_now`, the current balanceOf(token) of the early buyers counted in dump_cluster_count (one Multicall3 batch on our node). The base response is unchanged."}],"responses":{"200":{"description":"OK. Neutral score (50) with `note` when the token has no buyer history yet.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"current_mc_usd":{"type":"number","nullable":true},"cohort_selection":{"type":"string","enum":["distinct_first_buy","legacy_row_window"],"description":"distinct_first_buy = the first 20 DISTINCT buyer EOAs by their first buy (block, tx index, log index), selected before the limit. legacy_row_window = pre-rhc/011 fallback (oldest 300 buy rows, deduped — a repeat buyer can crowd out later distinct buyers); served only until that migration is applied."},"dump_cluster_held_now":{"type":"object","description":"Only with include_balances=true (PRO+, 2026-10-15, TR-09): the early buyers counted in dump_cluster_count and what they hold NOW from balances. Totals only when every member was read.","properties":{"cohort_size":{"type":"integer"},"members":{"type":"integer","description":"Dump-cluster members among the early buyers (= dump_cluster_count)."},"held_now":{"type":"object","description":"Same shape as the bundle held_now of this chain: source, checked_at, wallets, verified_wallets, holding_wallets, complete, incomplete_reason, tokens_held_raw, tokens_held, held_pct_of_supply (ratio), supply_basis."},"wallets":{"type":"array","items":{"type":"object","properties":{"wallet":{"type":"string"},"balance_now":{"type":"object","nullable":true}}}},"note":{"type":"string"}}},"quality":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100},"confidence":{"type":"string","enum":["insufficient_data","low","medium","high"],"description":"Confidence in the PREDICTIVE inputs: counts only buyers whose win rate fed the score (≥3 tokens of history, not bot-flagged, not zero-cost-dump dominated). insufficient_data = none did — the score is the neutral-50 default plus penalties. 1 → low, 5+ → medium, 11+ → high."},"signal":{"type":"string","enum":["positive","neutral","negative"]},"breakdown":{"type":"object","properties":{"wallets_with_history":{"type":"integer","description":"Buyers with ≥3 tokens of history (cohort identification — not predictive)"},"qualified_win_rate_wallets":{"type":"integer","description":"Buyers whose win rate fed the score — the basis of confidence"},"early_buyers_analyzed":{"type":"integer"},"alpha_wallet_count":{"type":"integer"},"kol_count":{"type":"integer"},"bundle_buyer_count":{"type":"integer","description":"Early buyers flagged as part of a same-block launch bundle (mig 255)."},"dump_cluster_count":{"type":"integer","description":"Early buyers on the rolling dump-cluster list (≥5 crashed-off-peak cohorts, 0 runner cohorts, trailing 42d, OOS-validated). Informational — high count = strong dump signal."},"recycled_early_buyer_count":{"type":"integer","description":"Early buyers with ≥5 recent early-buyer appearances of any kind (dump_cluster_count is a subset)."},"avg_historical_win_rate":{"type":"number","nullable":true,"description":"Percent (0–100), non-bot buyers with ≥3 tokens of history."},"bot_dominated":{"type":"boolean"}}}}},"coverage":{"type":"object","description":"Signal availability. Dump-cluster is available but informational (does not move the score).","properties":{"bundle_detection":{"type":"string","enum":["available"]},"dump_cluster_signal":{"type":"string","enum":["available"]},"note":{"type":"string"},"earliest_buyers_caveat":{"type":"string","description":"For launches before 2026-07-18 the earliest-buyers cohort is the earliest 20 ATTRIBUTED buyers (trader_eoa backfill pending), not necessarily the first 20 buyers."}}},"note":{"type":"string","description":"Present only when buyer data is insufficient."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"include_balances=true needs PRO.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}],"x-madeonsol-feature-tiers":[{"tier":"PRO","feature":"Robinhood Chain dump-cluster current holdings (include_balances)"}]}},"/rhc/tokens/{address}/bundle-share":{"get":{"tags":["Robinhood Chain"],"summary":"Share of supply held now by all bundle wallets on a Robinhood Chain token (PRO+)","description":"ONE figure for a terminal (2026-10-15): `bundled_pct_of_supply_now`, the share of total supply held RIGHT NOW by every bundle wallet: the launch bundle plus every wallet of a coordinated buy cluster in the window (`/rhc/tokens/{address}/bundles`), each wallet counted once, balanceOf from our node in one Multicall3 batch (at most 500 wallets). Null when not every wallet could be read. Cached 30 seconds per token, shared by every caller (`as_of`). Before hood rhc/039 is applied it counts the launch bundle only (`scope: launch_cohort_only`).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"window","in":"query","schema":{"type":"string","enum":["1h","6h","24h"],"default":"24h"},"description":"Which later clusters to include (the launch bundle is always included)."},{"name":"min_wallets","in":"query","schema":{"type":"integer","minimum":3,"maximum":20,"default":3}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"window":{"type":"string"},"min_wallets":{"type":"integer"},"bundled_pct_of_supply_now":{"type":"number","nullable":true,"description":"RATIO in [0, 1]: share of supply held now by every bundle wallet. Null unless the wallet set is known complete (clusters_complete true) AND every wallet was read (see held_now.incomplete_reason)."},"scope":{"type":"string","enum":["launch_and_clusters","launch_cohort_only"],"description":"launch_cohort_only = the cluster function was not available; only the launch bundle is counted."},"clusters_status":{"type":"string","enum":["ok","unavailable","timeout","error"]},"clusters_complete":{"type":"boolean","description":"True only when every coordinated buy cluster in the window was read: clusters_status ok AND fewer than clusters_limit clusters came back. False when the cluster list hit clusters_limit (older clusters in the window may be missing; held_now.incomplete_reason clusters_truncated) or the cluster function was not available (scope launch_cohort_only). bundled_pct_of_supply_now is null whenever this is false (2026-10-15)."},"clusters_limit":{"type":"integer","description":"Most clusters read per request (200). A response with this many clusters is treated as possibly truncated."},"wallets":{"type":"object","properties":{"total":{"type":"integer"},"launch_cohort_wallets":{"type":"integer"},"cluster_wallets":{"type":"integer"},"overlap":{"type":"integer"},"clusters_counted":{"type":"integer"},"verified":{"type":"integer"},"holding":{"type":"integer"},"max":{"type":"integer"}}},"held_now":{"type":"object","description":"Same shape as the bundle held_now of this chain. incomplete_reason adds clusters_truncated (the cluster list hit clusters_limit; balances are not read) next to cluster_wallets_truncated (a cluster has more wallets than the 50 listed)."},"as_of":{"type":"string","format":"date-time"},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid address or query parameters","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Tier gate - PRO required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Temporarily unavailable","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/bundles":{"get":{"tags":["Robinhood Chain"],"summary":"Every coordinated buy cluster on a Robinhood Chain token, launch and later (PRO+)","description":"Every block in the window where at least `min_wallets` distinct effective trading accounts (ERC-4337 senders resolved) bought the token, the launch bundle AND clusters that enter later (2026-10-15). `/rhc/tokens/{address}/bundle` remains the launch-cohort view. Per cluster: block, time, `minutes_after_launch` + `phase`, `wallet_count`, `new_wallets`, `same_tx_groups` (transactions carrying 3+ of them; weaker than on Solana because a 4337 bundler batches unrelated userOps into one tx), ETH volume, `token_volume_raw` (uint256 string), wallets. No size floor on Robinhood Chain. `include_balances=true` adds `held_now` (balanceOf from our node) to the 3 most recent clusters.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"window","in":"query","schema":{"type":"string","enum":["1h","6h","24h"],"default":"24h"}},{"name":"min_wallets","in":"query","schema":{"type":"integer","minimum":3,"maximum":20,"default":3},"description":"Minimum distinct buyers in one slot/block to count as a cluster."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"include_balances","in":"query","schema":{"type":"boolean","default":false},"description":"Add `held_now` (current balances from the chain) to the 3 most recent clusters."}],"responses":{"200":{"description":"OK. An empty clusters array means no slot/block in the window had min_wallets distinct buyers.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"window":{"type":"string"},"min_wallets":{"type":"integer"},"launch_at":{"type":"string","format":"date-time","nullable":true},"summary":{"type":"object","properties":{"cluster_count":{"type":"integer"},"launch_clusters":{"type":"integer"},"later_clusters":{"type":"integer"},"latest_cluster_at":{"type":"string","format":"date-time","nullable":true},"largest_cluster_wallets":{"type":"integer"},"baseline":{"type":"object","nullable":true,"description":"Window baseline (null when no cluster was found): active units, buys in window, buys per active unit. On busy tokens unrelated buyers share slots."}}},"clusters":{"type":"array","items":{"type":"object","properties":{"block_number":{"type":"integer"},"same_tx_groups":{"type":"integer"},"eth_volume":{"type":"number","nullable":true},"token_volume_raw":{"type":"string","nullable":true},"at":{"type":"string","format":"date-time"},"minutes_after_launch":{"type":"number","nullable":true},"phase":{"type":"string","enum":["launch","later","unknown"],"description":"launch = within 5 minutes of launch_at."},"wallet_count":{"type":"integer"},"new_wallets":{"type":"integer","description":"Buyers with no earlier buy of this token."},"wallets":{"type":"array","items":{"type":"string"},"description":"At most 50."},"held_now":{"type":"object","description":"Only with include_balances=true, on the 3 most recent clusters: same shape as the bundle held_now of this chain; totals only when every wallet was read."},"exit":{"type":"object","nullable":true,"description":"What this cluster's wallets have SOLD of the token since the cluster (bundle-watch sell ledger, migration 503). null = not followed (only clusters bundle-watch announced: >= 3 wallets new to the token; followed 7 days after detection; first 50 wallets).","properties":{"cluster_id":{"type":"integer"},"followed_until":{"type":"string","format":"date-time"},"wallets_tracked":{"type":"integer"},"wallets_sold":{"type":"integer"},"wallets_exited":{"type":"integer","description":"Sold >= 99 % of their cluster buy."},"bought_tokens_raw":{"type":"string","nullable":true},"sold_tokens_raw":{"type":"string"},"sold_pct":{"type":"number","nullable":true,"description":"Sum over wallets of min(sold, bought in the cluster) / bought in the cluster, 0..1."},"realized_eth":{"type":"number","description":"Known proceeds only (migration 511); see realized_status."},"realized_status":{"type":"string","nullable":true,"enum":["complete","incomplete"],"description":"Migration 511: incomplete when at least one recorded sell has unknown proceeds (Solana price_status proceeds_unattributed, or no quote amount); its tokens count in sold_pct, its proceeds are NOT in realized_eth (never booked as 0). null = not measured (ledger before migration 511)."},"unknown_proceeds_sells":{"type":"integer","nullable":true,"description":"Recorded sells with unknown proceeds (see realized_status)."},"last_sell_at":{"type":"string","format":"date-time","nullable":true}}}}}},"held_now_clusters":{"type":"integer","description":"Only with include_balances=true."},"exit_tracking":{"type":"string","enum":["ok","unavailable","error"],"description":"Whether the exit ledger could be read; the clusters are served either way (exit null when not ok)."},"exit_note":{"type":"string"},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid address or query parameters","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Tier gate - PRO required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"bundle_clusters_unavailable (SQL function not applied) or bundle_clusters_temporarily_unavailable (timeout).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/bundle":{"get":{"tags":["Robinhood Chain"],"summary":"Launch-bundle detection on a Robinhood Chain token (BASIC+)","description":"Detects a coordinated launch bundle in a token's earliest-buyer cohort and measures how much of what the bundle bought it still holds. Mirrors the Solana `/tokens/{mint}/bundle` detector: rank the first 20 distinct buyers by on-chain order, flag a bundle when 3+ of them make their first buy in the **same block**, then report the cohort's current-held %. Robinhood Chain is an Arbitrum Orbit L2 with no atomic multi-signer transaction, so there is no `atomic_tx` kind — a detected bundle is `same_block` (else `none`). Scores tokens ingested live (the near-launch window where bundling happens). Field-gated by tier: **BASIC** gets the scalar `bundle` signal only; **PRO** adds the top-10 wallets; **ULTRA** returns the full cohort enriched with alpha-wallet identity (win-rate, bot, KOL).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"include_balances","in":"query","schema":{"type":"boolean","default":false},"description":"PRO+ (2026-10-15): add `held_now`, the cohort's CURRENT balanceOf(token) from one Multicall3 batch on our own node, and `balance_now` per disclosed wallet. Totals only when every cohort wallet was read; never a partial sum."}],"responses":{"200":{"description":"OK. `wallet_count` 0 with `bundle_kind: none` when no same-block early-buyer cluster is present.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"bundle":{"type":"object","properties":{"wallet_count":{"type":"integer","description":"Bundle-cohort size (0 when none)."},"bundle_kind":{"type":"string","enum":["same_block","none"],"description":"`same_block` = 3+ early buyers first-bought in one block; `none` = no cluster. `atomic_tx` does not exist on EVM."},"held_ratio":{"type":"number","nullable":true,"description":"Net tokens still held ÷ tokens bought, [0,1]. The primary signal."},"held_pct_of_supply":{"type":"number","nullable":true,"description":"Net tokens held ÷ total supply, [0,1]; null when supply is unknown."},"fully_exited":{"type":"boolean","description":"True when the cohort holds ≤0.5% of what it bought."},"buy_volume":{"type":"number","description":"Cohort cumulative buy-side token volume (human-scaled)."},"tokens_held":{"type":"number","description":"Cohort net position (Σbuys − Σsells, human-scaled)."},"holdings_basis":{"type":"string","enum":["swap_only","swap_and_transfers"],"description":"swap_only = token transfers are not applied: a member that transferred tokens out and sold elsewhere still reads as holding."}}},"held_now":{"type":"object","description":"Only with include_balances=true (PRO+). Balance-based, next to the swap-derived bundle.* figures.","properties":{"source":{"type":"string","enum":["rhc_node_balanceOf_latest"]},"checked_at":{"type":"string","format":"date-time"},"wallets":{"type":"integer"},"verified_wallets":{"type":"integer"},"holding_wallets":{"type":"integer"},"complete":{"type":"boolean","description":"True only when every cohort wallet was read."},"incomplete_reason":{"type":"string","nullable":true},"tokens_held_raw":{"type":"string","nullable":true,"description":"Exact uint256 sum; null unless complete."},"tokens_held":{"type":"string","nullable":true,"description":"tokens_held_raw / 10^decimals, exact; null unless complete."},"held_pct_of_supply":{"type":"number","nullable":true,"description":"RATIO in [0, 1] of total_supply_raw (like bundle.held_pct_of_supply); null unless complete and supply known."},"supply_basis":{"type":"string","nullable":true,"enum":["total_supply_raw",null]}}},"wallets":{"type":"array","description":"Empty for BASIC; top-10 for PRO; full cohort for ULTRA.","items":{"type":"object","properties":{"rank":{"type":"integer","description":"Early-buyer rank (1 = first buyer)."},"wallet":{"type":"string","description":"Buyer wallet (lowercase 0x)."},"held_ratio":{"type":"number","nullable":true},"has_sold":{"type":"boolean"},"is_kol":{"type":"boolean","description":"Wallet is a tracked RHC KOL."},"balance_now":{"type":"object","nullable":true,"properties":{"status":{"type":"string","enum":["verified","unverified"]},"balance_raw":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"balance":{"type":"string","nullable":true},"holding":{"type":"boolean","nullable":true},"reason":{"type":"string","nullable":true}},"description":"Only with include_balances=true: this wallet's current balanceOf(token) from our node; unverified never means zero."},"win_rate":{"type":"number","nullable":true,"description":"ULTRA only — historical win-rate [0,1]."},"likely_bot":{"type":"boolean","description":"ULTRA only — bot heuristic from mv_rhc_alpha_wallets."},"tokens_held":{"type":"number","description":"ULTRA only — net position, human-scaled."}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}],"x-madeonsol-feature-tiers":[{"tier":"PRO","feature":"Robinhood Chain bundle balances (include_balances)"}]}},"/rhc/tokens/{address}/top-traders":{"get":{"tags":["Robinhood Chain"],"summary":"Top traders of a Robinhood Chain token, ranked by realized ETH (PRO+)","description":"Lifetime per-trader performance on one token, ranked by realized ETH flow, enriched with alpha-wallet reputation (win-rate, bot heuristic, KOL identity), dump-cluster membership and early-buyer rank.\n\n**`net_eth` is realized flow (sell − buy), not PnL.** It does not value a trader's remaining bag, so a wallet that bought and still holds ranks last. Each trader also carries **`fifo`**: FIFO realized PnL on this token, the same method as `/rhc/wallet/{address}/pnl` (sells match only earlier buys; tokens sold without an observed buy never count as profit). **PRO** returns up to 50 rows; **ULTRA/BUSINESS** up to 200.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Rows to return. Capped at 50 on PRO, 200 on ULTRA/BUSINESS."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0},"description":"Rows to skip."}],"responses":{"200":{"description":"OK. `traders` is empty for a token with no attributed traders yet — a 200, not an error.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"traders":{"type":"array","items":{"type":"object","properties":{"trader_eoa":{"type":"string","description":"Trader address (lowercase 0x)."},"buy_eth":{"type":"number","nullable":true},"sell_eth":{"type":"number","nullable":true},"net_eth":{"type":"number","nullable":true,"description":"sell_eth − buy_eth. Realized only."},"trades":{"type":"integer"},"last_trade_at":{"type":"string","format":"date-time","nullable":true},"avg_trade_mc":{"type":"number","nullable":true,"description":"Mean market cap at time of trade (USD)."},"win_rate":{"type":"number","nullable":true,"description":"Wallet-level historical win-rate [0,1]."},"likely_bot":{"type":"boolean","nullable":true},"is_known_kol":{"type":"boolean","nullable":true},"kol_name":{"type":"string","nullable":true,"description":"Null when the KOL is tracked but unnamed."},"wallet_net_eth":{"type":"number","nullable":true,"description":"Trader's net across ALL tokens, for context."},"wallet_tokens":{"type":"integer","nullable":true},"dump_cohorts":{"type":"integer","nullable":true,"description":"Dump-cluster cohort count; >0 means recycled dumper."},"early_buyer_rank":{"type":"integer","nullable":true,"description":"1–20 when this trader was an early buyer."},"fifo":{"type":"object","nullable":true,"description":"FIFO realized PnL on this token, computed the way `/rhc/wallet/{address}/pnl` computes it: sells match only earlier buys in chain order; tokens sold without an observed buy are `unmatched_sell_tokens` and never profit. Window: the token's whole stored history (`/pnl` reads the wallet's last 90 days). Open lots are not valued (a FIFO-open lot is not a verified balance). Null when `fifo_status` is not `ok`.","properties":{"realized_pnl_eth":{"type":"number"},"roi":{"type":"number","nullable":true,"description":"realized / matched cost basis. Null when nothing was matched."},"cost_basis_matched_eth":{"type":"number"},"bought_eth":{"type":"number","description":"ETH spent on the trades FIFO used (sized + priced)."},"sold_eth":{"type":"number"},"unmatched_sell_tokens":{"type":"number","description":"Tokens sold without an earlier observed buy (transfers in, pre-attribution buys). Excluded from realized PnL."},"cost_basis_complete":{"type":"boolean","description":"True when unmatched_sell_tokens is 0."},"fifo_open_tokens":{"type":"number","description":"FIFO-open quantity. NOT a verified balance."},"open_cost_basis_eth":{"type":"number"},"sized_trades":{"type":"integer"},"unpriced_trades":{"type":"integer","description":"Trades without an ETH leg or direction: excluded."},"unsized_trades":{"type":"integer","description":"Trades whose token quantity could not be reconstructed: excluded."}}}}}},"count":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"metric":{"type":"string","description":"States the net_eth semantics explicitly."},"cost_method":{"type":"string","enum":["fifo"],"description":"Method of the per-trader `fifo` block."},"fifo_status":{"type":"string","enum":["ok","unavailable","timeout","error"],"description":"`ok` = computed; `unavailable` = not deployed yet; `timeout` = too slow right now; `error` = failed. The ranking and the other fields never depend on it."},"fifo_note":{"type":"string"},"attribution":{"type":"object","description":"Interim attribution disclosure: the underlying rollup filters `trader_eoa IS NOT NULL`, and trader_eoa was only written reliably from 2026-07-18, so pre-floor history is not reflected. Removed once the trader_eoa backfill lands.","properties":{"attribution_complete_from":{"type":"string","format":"date-time"},"note":{"type":"string"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address, or bad limit/offset.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/flow":{"get":{"tags":["Robinhood Chain"],"summary":"Net buy/sell flow by trader cohort on a Robinhood Chain token (PRO+)","description":"Splits a token's trade flow into mutually-exclusive trader cohorts over a window, so you can see *who* is accumulating and *who* is distributing.\n\n**Sign convention: `net_eth = sell − buy`.** Positive means the cohort **distributed** (took ETH out); negative means it **accumulated**. Cohorts are assigned by a priority ladder and each trader lands in exactly one: `kol` → `bot` → `dump_cluster` → `early_buyer` → `unprofiled` → `smart_money` → `retail`.\n\n`smart_money` is derived (win-rate ≥ 0.5 and net positive across all tokens), not a stored label. `unprofiled` is a real answer, not a gap — the trader has not met the reputation matview's thresholds. There is deliberately no `fresh_wallet` cohort: Robinhood Chain has no wallet-level first-seen, so it cannot be computed honestly.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"window","in":"query","schema":{"type":"string","enum":["1h","6h","24h","7d"],"default":"24h"},"description":"Lookback window."}],"responses":{"200":{"description":"OK. `cohorts` is empty when the token had no trades in the window.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"window":{"type":"string","enum":["1h","6h","24h","7d"]},"cohorts":{"type":"array","items":{"type":"object","properties":{"cohort":{"type":"string","enum":["kol","bot","dump_cluster","early_buyer","unprofiled","smart_money","retail"]},"traders":{"type":"integer"},"trades":{"type":"integer"},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"net_eth":{"type":"number","description":"sell − buy. Positive = distributed."}}}},"totals":{"type":"object","description":"Sum across cohorts; always equals the parts."},"sign_convention":{"type":"string"},"attribution":{"type":"object","description":"Interim attribution disclosure: cohort figures are computed from attributed trades only (`trader_eoa IS NOT NULL`), and trader_eoa was only written reliably from 2026-07-18 — pre-floor history is not reflected. Removed once the trader_eoa backfill lands.","properties":{"attribution_complete_from":{"type":"string","format":"date-time"},"note":{"type":"string"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address, or window not in {1h,6h,24h,7d}.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/peak-history":{"get":{"tags":["Robinhood Chain"],"summary":"Peak market cap, drawdown and high-water curve for a Robinhood Chain token (PRO+)","description":"Peak market cap, current drawdown from peak, and a running high-water curve.\n\n**Two peaks are returned, and they can disagree.** `peak_mc_usd_recorded` is the stored high-water mark every other Robinhood Chain surface keys off (deployer runner-rate, the $40K graduation bar). `peak_mc_usd_observed` is the maximum of the 1-minute candle highs — trade-level truth, and always ≥ the recorded value. The recorded figure is sampled from write batches so it can undercount an intra-batch spike; both are surfaced rather than silently swapping one for the other, which would desync this endpoint from deployer tiering.\n\nCandle history begins 2026-07-15, so a token that peaked earlier cannot have its peak reconstructed — `observed_covers_full_history` tells you whether the observed figure spans the token's whole life. Curve binning is chosen server-side (1m→4h) to keep the series bounded.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"window","in":"query","schema":{"type":"string","enum":["24h","7d","30d","all"],"default":"7d"},"description":"Curve window."},{"name":"curve","in":"query","schema":{"type":"string","enum":["true","false"],"default":"true"},"description":"Set false to skip the series and return only the peak summary."}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"name":{"type":"string","nullable":true},"symbol":{"type":"string","nullable":true},"current":{"type":"object","description":"Live market cap, liquidity, price, FDV."},"peak":{"type":"object","properties":{"peak_mc_usd_recorded":{"type":"number","nullable":true},"peak_mc_at_recorded":{"type":"string","format":"date-time","nullable":true},"peak_mc_usd_observed":{"type":"number","nullable":true,"description":"Candle-derived max; ≥ recorded."},"peak_mc_at_observed":{"type":"string","format":"date-time","nullable":true},"observed_covers_full_history":{"type":"boolean","description":"False when candle history starts after the token did."},"pct_of_peak":{"type":"number","nullable":true,"description":"Current MC ÷ best-known peak, [0,1]."},"drawdown_from_peak":{"type":"number","nullable":true,"description":"1 − pct_of_peak."}}},"curve":{"type":"object","properties":{"window":{"type":"string"},"bucket":{"type":"string","description":"Server-chosen bin size (1m/5m/15m/1h/4h)."},"points":{"type":"array","items":{"type":"object","properties":{"bucket_start":{"type":"string","format":"date-time"},"high_mc_usd":{"type":"number","nullable":true},"close_mc_usd":{"type":"number","nullable":true},"running_peak_mc":{"type":"number","nullable":true,"description":"Monotonically non-decreasing high-water mark."}}}},"count":{"type":"integer"}}}}}}},"description":"OK.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address, or bad window.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Token not found on Robinhood Chain.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/risk":{"get":{"tags":["Robinhood Chain"],"summary":"EVM-native risk assessment for a Robinhood Chain token (PRO+)","description":"Risk assessment computed **live** against our own Robinhood Chain node at the chain head.\n\n**This is not the Solana risk model.** EVM has no mint or freeze authority. Measured across 300 random Robinhood Chain tokens, only 2.3% even expose an `owner()` function and 0% expose `mint` in their own bytecode — so an absent flag is the norm, not a safety signal. The axes that actually discriminate here are proxy upgradeability, LP custody, and sellability.\n\n**Sellability is the strongest signal.** A sell is simulated through the router at head using state overrides, which detects a token that can be bought but not sold. It is computed live, never cached — whether a token is sellable can change the moment an owner flips a setting.\n\nProxies are resolved before capability scanning: EIP-1167 minimal proxies (14% of tokens) carry zero selectors of their own, and the tokenized equities are beacon proxies whose *implementation* is what exposes `mint`/`pause`/`upgradeTo`. `lp_custody` is only read for uniswap-v2 pools; v3/v4 liquidity sits in an LP NFT whose custody needs a position-manager trace, and is reported `unknown` rather than guessed.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."}],"responses":{"200":{"description":"OK. Absent capability flags are the norm on this chain and are not a safety guarantee.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"checked_at":{"type":"string","format":"date-time","description":"Computed live; always current."},"code_size":{"type":"integer","description":"Runtime bytecode length in bytes."},"is_contract":{"type":"boolean"},"proxy":{"type":"object","properties":{"kind":{"type":"string","enum":["none","eip1167_minimal","eip1967","eip1967_beacon","legacy"]},"implementation":{"type":"string","nullable":true},"admin":{"type":"string","nullable":true},"upgradeable":{"type":"boolean","description":"False for eip1167_minimal — the target is baked into immutable code."}}},"owner":{"type":"object","properties":{"model":{"type":"string","enum":["none","renounced","eoa","contract"],"description":"`none` = no owner function at all, which is NOT the same as renounced."},"address":{"type":"string","nullable":true}}},"capabilities":{"type":"object","properties":{"can_mint":{"type":"boolean"},"can_pause":{"type":"boolean"},"has_access_control":{"type":"boolean"},"selectors_found":{"type":"array","items":{"type":"string"}}}},"liquidity":{"type":"object","properties":{"primary_pool":{"type":"string","nullable":true},"dex":{"type":"string","nullable":true},"lp_custody":{"type":"string","enum":["burned","locked","at_risk","unknown"]},"lp_burned_pct":{"type":"number","nullable":true},"last_removed_at":{"type":"string","format":"date-time","nullable":true,"description":"Most recent LP withdrawal observed on this token (uniswap-v2/v3 `Burn`, uniswap-v4 negative `ModifyLiquidity`). `null` means none seen since removal capture began on 2026-08-05 — not that none ever happened."}}},"sellability":{"type":"object","properties":{"sellable":{"type":"string","enum":["yes","no","unknown"]},"reason":{"type":"string","nullable":true}}},"flags":{"type":"array","items":{"type":"string"},"description":"Derived from the fields above. Includes `lp_removed_24h` when liquidity was withdrawn from this token in the last 24 hours."},"score":{"type":"integer","nullable":true,"description":"0–100, conservative. Absence of evidence is not evidence of safety."},"assessment":{"type":"object","description":"Whether every input was actually read (2026-09-21). A failed read is an UNKNOWN input, never a silent all-clear: e.g. lp_removal_history unknown ⇒ the absence of `lp_removed_24h` proves nothing; observed_sells unknown ⇒ a simulated sell revert is reported sellable=unknown, not a honeypot.","properties":{"status":{"type":"string","enum":["complete","incomplete"]},"unknown_inputs":{"type":"array","items":{"type":"string","enum":["lp_removal_history","pools","holder_probes","observed_sells"]}}}},"coverage":{"type":"object","description":"What this model does and does not read — see the endpoint description.","properties":{"model":{"type":"string","enum":["evm_native"]},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"Basis of any liquidity_usd figure quoted for this token: uniswap-v4 values are virtual reserves clamped to the PoolManager's total holdings — a provable ceiling, not measured per-pool TVL."},"liquidity_note":{"type":"string"},"note":{"type":"string"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/kol-trades":{"get":{"tags":["Robinhood Chain"],"summary":"Every KOL trade on one Robinhood Chain token, with optional current balances (BASIC+)","description":"Every stored KOL trade on one Robinhood Chain token, newest first, in one payload (2026-10-15): KOL name, EVM address, side, ETH and token amounts, price and market cap at the trade, DEX, tx hash, log index, block and time. Keyset paging with `next_cursor` / exact `has_more`. Same tier depth as `/rhc/kol/feed` (BASIC: 5-minute delay, 20 rows).\n\n**`include_balances=true` (PRO+)** adds `balances`: `balanceOf(token)` for every KOL address on the page, read in one Multicall3 batch from our own Robinhood Chain node at `checked_at`. A failed read is `status: unverified` with a `reason` and null balance, never a zero, and the balance is never reconstructed from trades (an open FIFO lot is not proof of a held balance).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":100},"description":"BASIC is clamped to 20."},{"name":"action","in":"query","schema":{"type":"string","enum":["buy","sell"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only trades strictly after this time."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"`next_cursor` from the previous page (keyset on traded_at DESC, id DESC)."},{"name":"kol","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Only this KOL address."},{"name":"include_balances","in":"query","schema":{"type":"boolean","default":false},"description":"PRO+: current balanceOf(token) per KOL address on the page, from our node."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"trades":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kol_name":{"type":"string","nullable":true},"kol_twitter":{"type":"string","nullable":true},"evm_address":{"type":"string"},"action":{"type":"string","enum":["buy","sell"]},"eth_amount":{"type":"number","nullable":true},"token_amount":{"type":"number","nullable":true},"price_usd_at_trade":{"type":"number","nullable":true},"market_cap_usd_at_trade":{"type":"number","nullable":true},"dex":{"type":"string","nullable":true},"tx_hash":{"type":"string"},"log_index":{"type":"integer","nullable":true},"block_number":{"type":"integer","nullable":true},"traded_at":{"type":"string","format":"date-time"}}}},"count":{"type":"integer"},"kols_on_page":{"type":"integer","description":"Distinct KOL addresses on this page."},"next_cursor":{"type":"string","nullable":true},"has_more":{"type":"boolean","description":"Exact (limit + 1 probe)."},"note":{"type":"string"},"balances":{"type":"object","description":"Only with include_balances=true.","properties":{"source":{"type":"string","enum":["rhc_node_balanceOf_latest"]},"checked_at":{"type":"string","format":"date-time","nullable":true},"by_wallet":{"type":"object","additionalProperties":{"type":"object","properties":{"status":{"type":"string","enum":["verified","unverified"]},"balance_raw":{"type":"string","nullable":true,"description":"uint256 as a decimal string."},"decimals":{"type":"integer","nullable":true},"balance":{"type":"string","nullable":true,"description":"balance_raw / 10^decimals, exact decimal string."},"holding":{"type":"boolean","nullable":true},"reason":{"type":"string","nullable":true,"enum":["rpc_unavailable","call_failed","decimals_failed","over_cap","not_read",null]}}}},"summary":{"type":"object","properties":{"wallets":{"type":"integer"},"verified":{"type":"integer"},"holding":{"type":"integer"},"zero":{"type":"integer"},"unverified":{"type":"integer"}}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid address or query parameters","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Tier gate - PRO required for include_balances.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited, or the heavy-query limiter refused the balance read.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Temporarily unavailable","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}],"x-madeonsol-feature-tiers":[{"tier":"PRO","feature":"Robinhood Chain KOL balances (include_balances)"}]}},"/rhc/tokens/{address}/early-buyers":{"get":{"tags":["Robinhood Chain"],"summary":"First buyers of a Robinhood Chain token, and whether they still hold (PRO+)","description":"The first buyers of a Robinhood Chain token, in order, joined to what happened next. `rhc_early_buyers` ranks the first 20 buyers of 437k tokens and is recomputed daily; until now it was read only as a per-wallet COUNT, never exposed as a per-token list. The Solana counterpart is `GET /kol/tokens/{mint}/entry-order`.\n\n**`realized_eth` is observed sell-minus-buy ETH cashflow, NOT validated FIFO realized PnL.** Missing earlier buys, transfers and source gaps affect cost basis; read `position` and holding evidence separately.\n\n**Default `still_holding`** requires a successful holder fold and a supply reconciliation. On failed/partial source it is null, not an invented exit. **Optional `verify_current_balances=true` (ULTRA+)** checks every ranked first buyer via `balanceOf` on the existing private Hood node at one pinned block with a matching block-hash recheck. If any RPC call, block check or the ranked cohort/statistics is unavailable, the **whole strict request fails (503)** rather than returning partially verified balances. Maximum 20 wallets; additional RPC is opt-in only. `holder_recon_block`/`holder_recon_checked_at` refer to the separate existing fold, not atomic chain-head balance proof.\n\n**Ranks are as of `computed_at`, not live.** A token that began trading after the last sweep returns an empty list with a stated reason - never an assertion that it had no early buyers. Wallets may be ERC-4337 smart accounts, so a wallet is an address, not a person.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":20,"default":20},"description":"Ranking depth is 20 by construction."},{"name":"verify_current_balances","in":"query","schema":{"type":"boolean","default":false},"description":"ULTRA+ opt-in: 1 existing Hood-node batch of ≤20 ERC-20 balanceOf calls at a pinned block; all verified or 503, never a partially verified panel. No new RPC traffic by default."},{"name":"include_scout_scores","in":"query","schema":{"type":"boolean","default":false},"description":"PRO+ opt-in (2026-10-15): adds `is_kol` and `scout_score` per buyer. A KOL buyer's scout score is computed as of its own `first_buy_at`, so it shows what was knowable when it bought, not hindsight. Method as `GET /rhc/kol/scouts/leaderboard`. A failed read sets `scout_scores_status` and leaves the fields null, never the rest of the response."}],"responses":{"200":{"description":"OK. An empty early_buyers array with a note means the token is not yet ranked.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"early_buyers":{"type":"array","items":{"type":"object","properties":{"rank":{"type":"integer","description":"1 = first buyer observed."},"wallet":{"type":"string"},"first_buy_at":{"type":"string","format":"date-time","nullable":true},"first_buy_block":{"type":"integer","nullable":true},"still_holding":{"type":"boolean","nullable":true,"description":"Null when the holder-table read, uint256 value, or supply reconciliation is unverified; never falsely infer exit."},"balance":{"type":"string","nullable":true,"description":"Raw uint256 as a decimal STRING, may be source-unverified."},"holding_status":{"type":"string","enum":["verified_nonzero","verified_zero","unverified"],"description":"Source-verified fold observation; not necessarily current chain-head proof."},"holding_reason":{"type":"string","enum":["holder_read_failed","supply_reconciliation_unverified","invalid_holder_balance","indexed_nonzero_balance","indexed_zero_balance","pinned_chain_nonzero_balance","pinned_chain_zero_balance","pinned_chain_balance_missing"]},"position":{"type":"string","enum":["closed","open","unknown"]},"bought_eth":{"type":"number","nullable":true},"sold_eth":{"type":"number","nullable":true},"realized_eth":{"type":"number","nullable":true,"description":"Legacy field name: observed sold_eth - bought_eth net ETH flow, NOT transfer-aware FIFO PnL."},"trades":{"type":"integer","nullable":true},"avg_entry_mc_usd":{"type":"number","nullable":true},"is_kol":{"type":"boolean","nullable":true,"description":"Only with include_scout_scores=true. False = not a known KOL address; null = unknown (scout read failed)."},"scout_score":{"nullable":true,"description":"Only with include_scout_scores=true: this KOL's scout score as of its own first_buy_at (no hindsight). Null for non-KOLs or when unknown.","type":"object","properties":{"as_of":{"type":"string","format":"date-time","description":"The moment the score describes; every input is at or before it."},"first_touches_30d":{"type":"integer","description":"First touches in [as_of - 30 d, as_of - 4 h]."},"avg_followers_4h":{"type":"number","nullable":true},"swarm_3plus_pct":{"type":"number","nullable":true,"description":"% of first touches that drew ≥3 other KOLs within 4 h."},"swarm_5plus_pct":{"type":"number","nullable":true,"description":"% of first touches that drew ≥5 other KOLs within 4 h."},"scout_tier":{"type":"string","nullable":true,"enum":["S","A","B","C"],"description":"Null below 30 first touches."}}}}}},"scout_scores_status":{"type":"string","enum":["ok","unavailable","timeout","error"],"description":"Only with include_scout_scores=true. unavailable = hood rhc/038 not applied."},"scout_scores_note":{"type":"string","description":"Only with include_scout_scores=true: the scout score method."},"count":{"type":"integer"},"computed_at":{"type":"string","format":"date-time","nullable":true},"holdings_verified":{"type":"boolean","nullable":true,"description":"True only when the holder read succeeded AND token supply reconciles at a previously checked block."},"holder_recon_block":{"type":"integer","nullable":true,"description":"Block of the latest supply reconciliation; no atomic snapshot guarantee for holder rows."},"holder_recon_checked_at":{"type":"string","format":"date-time","nullable":true},"onchain_balance_verification":{"type":"object","description":"Present only after ALL ULTRA+ verify_current_balances checks passed at one pinned block on our Hood node.","properties":{"source":{"type":"string","enum":["rhc_node_pinned_balanceOf"]},"block_number":{"type":"integer"},"block_hash":{"type":"string"},"checked_at":{"type":"string","format":"date-time"},"verified_wallets":{"type":"integer","minimum":1,"maximum":20},"complete":{"type":"boolean","enum":[true]}}},"summary":{"type":"object","nullable":true,"properties":{"ranked":{"type":"integer"},"with_holding_data":{"type":"integer"},"still_holding":{"type":"integer"},"exited":{"type":"integer","description":"Only source-verified zero balance wallets, including transfer-outs."},"unknown_holding":{"type":"integer","description":"Wallets missing a valid holder read / supply reconciliation / raw balance."},"closed_positions":{"type":"integer"},"realized_eth_closed_only":{"type":"number","nullable":true}}},"note":{"type":"string","description":"Present only when the list is empty."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid token address or query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Tier gate - PRO required, ULTRA for verify_current_balances.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Strict verification requested but some ranked buyers, trade stats, canonical block hash or ERC-20 balances could not be proved; no partial panel returned. Retry later.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}],"x-madeonsol-feature-tiers":[{"tier":"ULTRA","feature":"Pinned-block early-buyer balance verification"}]}},"/rhc/tokens/{address}/holders":{"get":{"tags":["Robinhood Chain"],"summary":"Holder set and concentration for a Robinhood Chain token (PRO+)","description":"Holder balances and concentration metrics. **Not trade-derived** — balances are folded from ERC-20 `Transfer` logs, which our node retains in full, so they are exact rather than estimated. The Solana counterpart is `GET /tokens/{mint}/holders` — a live on-chain census via mint-scoped getProgramAccounts (shipped 2026-08-16).\n\n**Every token carries a reconciliation.** `verified` is true only when the reconstructed `sum(balance)` equals on-chain `totalSupply()` at a pinned block. A token that fails, or has not been swept yet, returns `verified: false` with a stated `unverified_reason` — never as though it were exact.\n\n**Concentration excludes pools and burn addresses.** The largest holder of a token is normally its own liquidity pool, so counting it would make `top1_share` meaningless; pools and burns are reported separately as `pool_held_pct` / `burned_pct` and excluded from the circulating denominator. Balances are raw uint256 and are returned as **strings** to preserve precision. Holder addresses may be ERC-4337 smart accounts, so `holder_count` is not a headcount of people.\n\n**Holder growth (2026-08-17).** `holder_growth.{1h,24h,7d}` reports `entered` (first Transfer at-or-after the window's `cutoff_block`), `entered_still_holding`, `exited` (pre-existing holders whose last movement in the window left them at zero) and `net` ≈ Δ holder_count — possible because the fold keeps first_seen_block/last_block and retains zero-balance rows. The Solana census has no history and cannot answer this.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Token address (0x, 40 hex)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Capped at 50 on PRO, 200 on ULTRA/BUSINESS."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0},"description":"Position paging, capped at 10,000 (OFFSET is O(n)). For a full walk use `after`."},{"name":"after","in":"query","schema":{"type":"string"},"description":"Keyset cursor (2026-09-05): pass the previous page's `next_after` unchanged to continue past the offset cap. Same order (balance DESC, holder ASC); supersedes offset. `next_after` is null on the last page."},{"name":"include_wallet_flags","in":"query","schema":{"type":"boolean","default":false},"description":"Opt in (TR-07) to per-holder `wallet_flags` + top-level `wallet_flags_meta`. Robinhood Chain: current holder page only; holders may be contracts or ERC-4337 accounts. Flags come from MadeOnSol's indexed wallet populations: a `false`/`null` with `label_coverage.evaluated=false` means insufficient evidence, NOT a verified negative. Any value other than true/false is a 400 (`invalid_include_wallet_flags`)."}],"responses":{"200":{"description":"OK. Check `verified` before relying on the numbers.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"verified":{"type":"boolean","description":"True only when reconstructed supply matches on-chain totalSupply()."},"unverified_reason":{"type":"string","nullable":true},"share_basis":{"type":"object","description":"Plain-language denominator of each per-holder ratio (share, share_of_supply, share_of_circulating) and the burn addresses.","additionalProperties":true},"holders":{"type":"array","items":{"type":"object","properties":{"holder":{"type":"string"},"balance":{"type":"string","description":"Raw uint256 as a decimal STRING — not a number."},"share":{"type":"number","nullable":true,"description":"balance / non-burned supply (liquidity pools INCLUDED), [0,1]. null on burn rows (is_burn). Not the concentration basis: use share_of_circulating for that."},"share_of_supply":{"type":"number","nullable":true,"description":"balance / total folded supply (pools and burns included), [0,1]. Defined for every row, including burn and pool rows. null = unknown."},"share_of_circulating":{"type":"number","nullable":true,"description":"balance / circulating supply (pools and burns excluded), [0,1]: the same basis as concentration.top1_share. null on pool and burn rows, or when unknown."},"last_block":{"type":"integer","nullable":true},"is_pool":{"type":"boolean"},"is_burn":{"type":"boolean"},"is_deployer":{"type":"boolean"},"wallet_flags":{"type":"object","nullable":true,"description":"Only with include_wallet_flags=true; null for pools/burns, invalid addresses or unavailable sources. RHC has no sniper or wallet-level bundler classifier: those are always null.","properties":{"is_sniper":{"type":"boolean","nullable":true},"is_bundler":{"type":"boolean","nullable":true},"is_kol":{"type":"boolean"},"is_alpha_tracked":{"type":"boolean"},"likely_bot":{"type":"boolean","nullable":true},"is_dumper":{"type":"boolean"},"dump_cluster_as_of":{"type":"string","nullable":true},"label_coverage":{"type":"object","additionalProperties":{"type":"object","properties":{"evaluated":{"type":"boolean"},"reason":{"type":"string"}}},"description":"Per label: evaluated=false means no sufficient evidence (not a verified negative)."}}}}}},"count":{"type":"integer"},"wallet_flags_meta":{"type":"object","description":"Only with include_wallet_flags=true.","properties":{"status":{"type":"string","enum":["available","partial","unavailable"]},"rule_version":{"type":"string"},"note":{"type":"string"}},"additionalProperties":true},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"next_after":{"type":"string","nullable":true,"description":"Keyset cursor for the next page — pass it unchanged as `after`. null on the last page (or when the last row has no balance). Preferred over `offset` for full walks: offset is capped at 10,000, `after` is not."},"after":{"type":"string","nullable":true,"description":"Echo of the `after` cursor this page was read from (null on the first page)."},"concentration":{"type":"object","nullable":true,"properties":{"holder_count":{"type":"integer","nullable":true},"circulating":{"type":"string","nullable":true},"top1_share":{"type":"number","nullable":true},"top10_share":{"type":"number","nullable":true},"top50_share":{"type":"number","nullable":true},"hhi":{"type":"number","nullable":true,"description":"Herfindahl index over circulating shares."},"pool_held_pct":{"type":"number","nullable":true},"burned_pct":{"type":"number","nullable":true},"deployer_pct":{"type":"number","nullable":true}}},"holder_growth":{"type":"object","nullable":true,"description":"Entered / exited holders per window, read from first_seen_block + last_block of the Transfer-log fold (mig 325). null only if the growth read failed; a single window is null when the chain had no ingested trades in it (cutoff unresolvable).","properties":{"1h":{"$ref":"#/components/schemas/RhcHolderGrowthWindow"},"24h":{"$ref":"#/components/schemas/RhcHolderGrowthWindow"},"7d":{"$ref":"#/components/schemas/RhcHolderGrowthWindow"},"note":{"type":"string"}}},"history_coverage":{"type":"object","description":"Per-token history continuity of the Transfer-log fold (COV-24). Present only when the coverage read is enabled. `state`: `verified_interval` (fold proven continuous from the token's birth and reconciled), `recovery_pending` (a repair is rebuilding it), `partial_history` (folded only while tracked, a re-entry gap, failed/non-standard token, or the coverage read failed — `reason` says which). `recon_ok` alone is NOT proof of correct individual balances.","properties":{"state":{"type":"string","enum":["verified_interval","recovery_pending","partial_history"]},"history":{"type":"string"},"reason":{"type":"string","nullable":true},"fold_from_block":{"type":"integer","nullable":true},"compared_at_block":{"type":"integer","nullable":true},"verified_at_block":{"type":"integer","nullable":true}}},"reconciliation":{"type":"object","nullable":true,"description":"recon_supply vs chain_supply at recon_block."},"source":{"type":"object","description":"Method, sweep cursor and completeness."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/deployer-hunter/leaderboard":{"get":{"tags":["Robinhood Chain"],"summary":"Deployer reputation leaderboard on Robinhood Chain (BASIC+)","description":"Robinhood Chain deployers ranked by reputation, from a 5-min-refresh rollup over every launchpad token we've indexed (160K+ ranked deployers). Most RHC launchpads are direct-to-DEX (no bonding curve), so \"graduation\" is a market-cap milestone: `graduation_rate` = share of the deployer's tokens that reached a $40K+ peak MC; `runner_rate` = share that reached $100K+. **`tier` is earned on `runner_rate`, NOT `graduation_rate`:** elite = 5+ launches, 24h+ of deployer history and runner_rate >= 0.50; good = same but >= 0.25; spammer = 20+ launches with graduation_rate < 0.05 (the only tier still keyed on the $40K bar). The $40K bar is cheap enough to manufacture — operators mass-relaunch one ticker across rotating wallets — so it is reported but no longer sets the tier. Tier: **BASIC** (any valid key).","parameters":[{"name":"sort","in":"query","schema":{"type":"string","enum":["graduation_rate","runner_rate","tokens_deployed","best_peak_mc_usd","last_deploy_at"],"default":"graduation_rate"},"description":"Ordering (all descending, NULLs last)."},{"name":"tier","in":"query","schema":{"type":"string","enum":["elite","good","neutral","spammer"]},"description":"Filter to one reputation tier."},{"name":"min_tokens","in":"query","schema":{"type":"integer","minimum":1,"maximum":100000,"default":3},"description":"Minimum tokens deployed. Default 3 — the minimum sample for a graded tier; lower it to include one-shot deployers."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}}],"responses":{"200":{"description":"OK. `total` is the filtered deployer count; page with limit/offset until `has_more` is false.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"deployers":{"type":"array","items":{"type":"object","properties":{"deployer_address":{"type":"string","description":"Deployer wallet (lowercase 0x)."},"tokens_deployed":{"type":"integer"},"graduated":{"type":"integer","description":"Tokens that reached a $40K+ peak MC (the graduation milestone)."},"graduation_rate":{"type":"number","description":"graduated ÷ tokens_deployed — share of the deployer's tokens that reached $40K+ peak MC."},"runners":{"type":"integer","description":"Tokens that peaked ≥ $100K MC."},"runner_rate":{"type":"number","description":"runners ÷ tokens_deployed."},"best_peak_mc_usd":{"type":"number","nullable":true,"description":"All-time-high MC across all their tokens."},"launchpads":{"type":"array","items":{"type":"string"},"description":"Launchpads this deployer has used."},"first_deploy_at":{"type":"string","format":"date-time","nullable":true},"last_deploy_at":{"type":"string","format":"date-time","nullable":true},"tier":{"type":"string","enum":["elite","good","neutral","spammer"]}}}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/alerts":{"get":{"tags":["Robinhood Chain"],"summary":"Deployer signal alert feed on Robinhood Chain (BASIC+)","description":"The deployer alert feed on Robinhood Chain (from `rhc_deployer_alerts`) — new deploys and graduations from tracked deployers, newest first. RHC domain values differ from Solana: `tier` is elite | good | neutral | spammer, `priority` is high | medium, `alert_type` is new_deploy | graduated (RHC has no bonded/kol_buy alert types, and no KOL-buy enrichment).\n\n**Two behaviours changed 2026-07-25.** (1) A tradability filter is now applied **BY DEFAULT** (`liquidity_usd >= $100`; unknown liquidity fails it) — the feed was serving alerts on tokens that had pumped and drained, one at $45K MC against $68 of liquidity. Pass `include_untradeable=true` for the raw tape; the active filter is echoed as `tradability_filter`. (2) `tier` and the `message` explaining it are now resolved at **READ time** from the live deployer rollup instead of being frozen at insert, so a demoted deployer can no longer be advertised as good-tier indefinitely. The original snapshot is preserved as `tier_at_alert`, with `tier_is_stale` flagging disagreement. Rows also carry `liquidity_usd` and `current_mc_usd`.\n\n**Paging (2026-09-21, audit F09 follow-up):** the tradability and tier gates are served by a bounded SCAN over (event_at DESC, id DESC) — `has_more` is false only at the real end, `scan.scan_truncated` says the budget ran out first; page with `cursor=` (`next_cursor`). Alerts with a NULL event_at (none in production) are excluded.\n\nTier: **BASIC** (any valid key) — **ULTRA** gets the full requested `limit`, while BASIC/PRO share a 50-alert cap per request.","parameters":[{"name":"deployer_tier","in":"query","schema":{"type":"string","enum":["elite","good","neutral","spammer"]},"description":"Filter to one deployer reputation tier. Applied to the RESOLVED (read-time) tier, not the stored snapshot, so the filter and the reported `tier` always agree."},{"name":"include_untradeable","in":"query","schema":{"type":"boolean","default":false},"description":"Set true to disable the default liquidity_usd >= $100 tradability filter and receive the raw alert tape."},{"name":"priority","in":"query","schema":{"type":"string","enum":["high","medium"]},"description":"Filter by alert priority."},{"name":"alert_type","in":"query","schema":{"type":"string","enum":["new_deploy","graduated"]}},{"name":"launchpad","in":"query","schema":{"type":"string","minLength":1,"maxLength":32},"description":"Filter to one launchpad."},{"name":"min_mc","in":"query","schema":{"type":"number","minimum":0},"description":"Minimum market cap at alert time (USD)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"description":"Capped at 50 for BASIC/PRO; ULTRA gets the full requested value."},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Incremental polling: return only alerts with `event_at` strictly newer than this ISO timestamp. Pass back `next_event_at` from the previous response to receive just what is new."},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"Cursor: return only alerts with `event_at` strictly older than this ISO timestamp. Pass `next_before` from the previous response to page backwards. Takes precedence over `offset`."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0},"description":"Offset pagination (RAW rows, before the gates), used when no cursor is supplied. Prefer `cursor` for stable paging over a live feed."},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":200},"description":"PREFERRED pagination (audit F09 follow-up): the `next_cursor` from a previous page — an opaque strict (event_at, id) keyset, so paging never repeats or skips rows that share a sort value and progresses with limit=1 through runs of identical timestamps. Malformed or tampered → 400. Cannot be combined with `before=` or `offset=` (400)."}],"responses":{"200":{"description":"`next_event_at` is the newest event_at on the page (poll cursor); `data_age_seconds` is the age of the newest alert.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"alerts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"deployer_address":{"type":"string","description":"Deployer wallet (0x)."},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"alert_type":{"type":"string","enum":["new_deploy","graduated"]},"title":{"type":"string","nullable":true},"message":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"],"description":"Deployer reputation tier resolved at READ time from the live deployer rollup (falls back to the snapshot when the deployer is not in the rollup)."},"tier_at_alert":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"],"description":"Snapshot of the tier written when the alert fired."},"tier_is_stale":{"type":"boolean","description":"true when the read-time tier differs from tier_at_alert."},"mc_at_alert":{"type":"number","nullable":true,"description":"Market cap when the alert fired (USD)."},"liquidity_usd":{"type":"number","nullable":true,"description":"Token liquidity now (USD)."},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. A uniswap-v4 row passing the $100 tradability filter is a CEILING-pass: its figure is virtual reserves clamped to the PoolManager's total holdings, not measured per-pool TVL."},"current_mc_usd":{"type":"number","nullable":true,"description":"Token market cap now (USD)."},"risk":{"$ref":"#/components/schemas/RhcTokenRiskSummary"},"priority":{"type":"string","enum":["high","medium"]},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"event_at":{"type":"string","format":"date-time","nullable":true}}}},"limit":{"type":"integer"},"offset":{"type":"integer"},"tradability_filter":{"type":"string","description":"The active tradability gate, echoed: `liquidity_usd >= $100`, or `off (include_untradeable=true)`."},"liquidity_note":{"type":"string","description":"Constant statement of the uniswap-v4 ceiling semantics — a v4 row passing the tradability filter is a ceiling-pass; per-row `liquidity_basis` says which rows that applies to."},"next_event_at":{"type":"string","format":"date-time","nullable":true,"description":"Newest event_at on this page — pass as ?since= to poll forward."},"next_before":{"type":"string","format":"date-time","nullable":true,"description":"Legacy cursor — event_at of the last row consumed (returned or gated out); pass as ?before= to page backward. Strict: skips alerts sharing that event_at. Prefer next_cursor."},"next_cursor":{"type":"string","nullable":true,"description":"Opaque keyset cursor for the next (older) page — pass as `cursor=`. null = end of feed. PREFERRED over the strict-timestamp legacy cursor, which skips same-timestamp siblings of the boundary row."},"has_more":{"type":"boolean","description":"false only when the candidate feed is exhausted (not merely when the page is short)."},"scan":{"type":"object","description":"Present when a filter had to be applied after the candidate fetch (audit F09): has_more is then false only when the candidates ran out, and scan_truncated=true means the per-request scan budget ran out first — more matches MAY exist past next_cursor.","properties":{"post_filtered":{"type":"boolean"},"scanned":{"type":"integer","description":"Candidate rows examined"},"scan_truncated":{"type":"boolean","description":"The per-request scan budget ran out before `limit` matches — more matches MAY exist past the cursor/offset"},"scan_budget":{"type":"integer"}}},"data_age_seconds":{"type":"integer","nullable":true}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/recent-bonds":{"get":{"tags":["Robinhood Chain"],"summary":"Recent graduations on Robinhood Chain (BASIC+)","description":"Recently graduated tokens on Robinhood Chain, newest first. On RHC a \"graduation\" is the **$40K peak-MC milestone**, not a bonding-curve completion — most RHC launchpads are direct-to-DEX. The set is defined purely by `peak_mc_usd ≥ $40,000` (independent of the sometimes-unreliable `is_graduated` flag), then enriched with token metadata and the deployer's reputation tier. Ordered by (peak_mc_at DESC, token_address DESC); page with `cursor=` (`next_cursor`, added 2026-09-21). `deployer_tier` is served by a bounded scan — see `has_more` / `scan`. Tier: **BASIC** (any valid key).","parameters":[{"name":"deployer_tier","in":"query","schema":{"type":"string","enum":["elite","good","neutral","spammer"]},"description":"Filter to one deployer reputation tier (post-filter over the peak-MC-ordered set)."},{"name":"min_peak","in":"query","schema":{"type":"number","minimum":0},"description":"Raise the peak-MC floor above the $40K graduation milestone (USD). Never lowers it below $40K."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":200},"description":"PREFERRED pagination (audit F09 follow-up): the `next_cursor` from a previous page — an opaque strict (peak_mc_at, token_address) keyset, so paging never repeats or skips rows that share a sort value and progresses with limit=1 through runs of identical timestamps. Malformed or tampered → 400."}],"responses":{"200":{"description":"`graduation_mc` echoes the $40K milestone; `next_peak_mc_at` is the newest peak timestamp on the page.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"graduation_mc":{"type":"integer","description":"The $40K peak-MC graduation milestone (USD)."},"tokens":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"deployer_address":{"type":"string","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"]},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"market_cap_usd":{"type":"number","nullable":true,"description":"Live market cap."},"peak_mc_usd":{"type":"number","nullable":true,"description":"All-time-high MC observed since ingestion."},"peak_mc_at":{"type":"string","format":"date-time","nullable":true}}}},"limit":{"type":"integer"},"next_peak_mc_at":{"type":"string","format":"date-time","nullable":true},"next_cursor":{"type":"string","nullable":true,"description":"Opaque keyset cursor for the next (older) page — pass as `cursor=`. null = end of feed. PREFERRED over the strict-timestamp legacy cursor, which skips same-timestamp siblings of the boundary row."},"has_more":{"type":"boolean","description":"false only when the candidate feed is exhausted (not merely when the page is short)."},"scan":{"type":"object","description":"Present when a filter had to be applied after the candidate fetch (audit F09): has_more is then false only when the candidates ran out, and scan_truncated=true means the per-request scan budget ran out first — more matches MAY exist past next_cursor.","properties":{"post_filtered":{"type":"boolean"},"scanned":{"type":"integer","description":"Candidate rows examined"},"scan_truncated":{"type":"boolean","description":"The per-request scan budget ran out before `limit` matches — more matches MAY exist past the cursor/offset"},"scan_budget":{"type":"integer"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/{address}/activity":{"get":{"tags":["Robinhood Chain"],"summary":"A Robinhood Chain developer's launches and own-token buys/sells as one timeline (PRO+)","description":"The REST timeline behind the `rhc:dev_activity` WS channel (2026-10-15). Events: `launch` (a token whose recorded deployer is this address), `dev_buy` / `dev_sell` (a trade of one of those tokens by this address itself, the effective trading account with ERC-4337 senders resolved). Same developer definition as the WS producer, and `event_id` equals the WS event id, so REST and WS can be joined. `attribution` `creator` = seen at launch, `pool_creator` = only the first pool's creator is known (weaker).\n\nOne event per trade leg, newest first, keyset paged over both sources with `next_cursor`. The trade scan is bounded: `coverage.scan_truncated` + `next_cursor` say where it stopped, never a false end. Window: `since` (default 30 days, at most 90). `coverage.dev_trades_complete_from` is the later of the window start and the Postgres floor; older months are in the archive and not read (`archive_required_before`).\n\n**Not included (v1):** developer token transfers, trades from other wallets of the same person, history below `dev_trades_complete_from`. An empty timeline is not proof that nothing happened outside those bounds.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Developer (deployer) address."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Window start; default 30 days ago, clamped to 90 days."},{"name":"types","in":"query","schema":{"type":"string"},"description":"Comma list of launch, dev_buy, dev_sell (default all)."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"`next_cursor` from the previous page."}],"responses":{"200":{"description":"OK. An address with no attributed token returns an empty timeline with `coverage.tokens_attributed: 0`.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"address":{"type":"string"},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable timeline key: t:<trade row id> or l:<token>."},"type":{"type":"string","enum":["launch","dev_buy","dev_sell"]},"at":{"type":"string","format":"date-time","description":"Chain time (launch: first seen)."},"block_number":{"type":"integer","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"attribution":{"type":"string","enum":["creator","pool_creator"]},"token_name":{"type":"string","nullable":true,"description":"launch only"},"launchpad":{"type":"string","nullable":true,"description":"launch only"},"event_id":{"type":"string","description":"dev trades only: the rhc:dev_activity id dx1:<tx>:<token>:<type>:<actor>"},"tx_hash":{"type":"string"},"log_index":{"type":"integer","nullable":true},"dex":{"type":"string","nullable":true},"eth_amount":{"type":"number","nullable":true},"token_amount_raw":{"type":"string","nullable":true,"description":"Raw uint256 of the token leg."},"price_usd":{"type":"number","nullable":true}}}},"count":{"type":"integer"},"summary":{"type":"object","properties":{"launches":{"type":"integer"},"dev_buys":{"type":"integer"},"dev_sells":{"type":"integer"}}},"next_cursor":{"type":"string","nullable":true},"has_more":{"type":"boolean"},"window":{"type":"object","properties":{"since":{"type":"string","format":"date-time"},"max_days":{"type":"integer"}}},"coverage":{"type":"object","properties":{"tokens_attributed":{"type":"integer"},"tokens_truncated":{"type":"boolean"},"dev_trades_complete_from":{"type":"string","format":"date-time","nullable":true,"description":"Null when the archive floor is unknown."},"archive_required_before":{"type":"string","format":"date-time","nullable":true},"trades_scanned":{"type":"integer"},"scan_truncated":{"type":"boolean"},"transfers_included":{"type":"boolean","enum":[false]},"linked_wallets_included":{"type":"boolean","enum":[false]}}},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid address or query parameters","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Tier gate - PRO required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Temporarily unavailable","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/deployer-hunter/{address}":{"get":{"tags":["Robinhood Chain"],"summary":"Single deployer profile on Robinhood Chain (BASIC+)","description":"One deployer's full reputation row (tier, bonding_rate, runner_rate, best peak MC, launchpads, deploy timeline) plus their 50 most recent tokens enriched with live MC and peak MC. Unknown wallets return 200 with `is_deployer: false` (not a 404) so clients can branch cheaply. Tier: **BASIC** (any valid key).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Deployer EVM wallet address (0x, 40 hex)."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"is_deployer":{"type":"boolean","description":"False if this wallet has never deployed a tracked token (deployer is then null)."},"address":{"type":"string"},"deployer":{"type":"object","nullable":true,"properties":{"deployer_address":{"type":"string"},"tokens_deployed":{"type":"integer"},"curve_tokens":{"type":"integer"},"graduated":{"type":"integer"},"bonding_rate":{"type":"number","nullable":true},"runners":{"type":"integer"},"runner_rate":{"type":"number"},"best_peak_mc_usd":{"type":"number","nullable":true},"launchpads":{"type":"array","items":{"type":"string"}},"first_deploy_at":{"type":"string","format":"date-time","nullable":true},"last_deploy_at":{"type":"string","format":"date-time","nullable":true},"tier":{"type":"string","enum":["elite","good","neutral","spammer"]}}},"recent_tokens":{"type":"array","description":"Up to 50 most recent tokens by this deployer.","items":{"type":"object","properties":{"address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"graduated_at":{"type":"string","format":"date-time","nullable":true},"graduated_pool":{"type":"string","nullable":true},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"market_cap_usd":{"type":"number","nullable":true,"description":"Live market cap."},"peak_mc_usd":{"type":"number","nullable":true,"description":"All-time-high MC observed since ingestion."},"peak_mc_at":{"type":"string","format":"date-time","nullable":true}}}},"recent_tokens_count":{"type":"integer","description":"Rows returned (capped at 50) — the true total is deployer.tokens_deployed."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/{address}/history":{"get":{"tags":["Robinhood Chain"],"summary":"Deployer token-deploy history on Robinhood Chain (PRO+)","description":"A deployer's full **token-deploy history** on Robinhood Chain: their `mv_rhc_deployers` reputation row plus every token they've deployed (paginated, newest first) enriched with live and peak MC. Note: RHC has no per-day reputation snapshot table, so this is a token-deploy history, not a daily tier/rate time-series. Unknown addresses return 200 with `is_deployer: false`. Tier: **PRO+** (the point-in-time `/rhc/deployer-hunter/{address}` profile stays BASIC).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Deployer EVM wallet address (0x, 40 hex)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":100000,"default":0}}],"responses":{"200":{"description":"OK. `total` is the deployer's full token count; page with limit/offset until `has_more` is false.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"is_deployer":{"type":"boolean","description":"False if this wallet has never deployed a tracked token (deployer/tokens then empty)."},"address":{"type":"string","description":"Lowercased 0x deployer address."},"deployer":{"type":"object","nullable":true,"properties":{"deployer_address":{"type":"string"},"tokens_deployed":{"type":"integer"},"graduated":{"type":"integer"},"graduation_rate":{"type":"number","description":"Share of tokens that reached a $40K+ peak MC."},"runners":{"type":"integer"},"runner_rate":{"type":"number","description":"Share of tokens that reached $100K+ peak MC."},"best_peak_mc_usd":{"type":"number","nullable":true},"launchpads":{"type":"array","items":{"type":"string"}},"first_deploy_at":{"type":"string","format":"date-time","nullable":true},"last_deploy_at":{"type":"string","format":"date-time","nullable":true},"tier":{"type":"string","enum":["elite","good","neutral","spammer"]}}},"tokens":{"type":"array","description":"This page of the deployer's tokens, newest first.","items":{"type":"object","properties":{"address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"graduated_at":{"type":"string","format":"date-time","nullable":true},"graduated_pool":{"type":"string","nullable":true},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"market_cap_usd":{"type":"number","nullable":true,"description":"Live market cap."},"peak_mc_usd":{"type":"number","nullable":true,"description":"All-time-high MC observed since ingestion."},"peak_mc_at":{"type":"string","format":"date-time","nullable":true}}}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address or query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/deployer-hunter/{address}/trajectory":{"get":{"tags":["Robinhood Chain"],"summary":"Is this RHC deployer getting better or worse? (BASIC+)","description":"Streak, rolling-rate and trend shape for one Robinhood Chain deployer, so you can tell a deployer on the way up from one coasting on old hits. Field names keep the Solana `bond` wording for drop-in compatibility, but `success_metric` states what was actually counted: the **$40K graduation**, deliberately NOT the $100K tier bar — $100K is rare enough that most deployers would return an all-zero curve. Unknown wallets return 200 with `is_deployer: false` (never a 404). Tier: **BASIC**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"},"description":"Deployer wallet (0x, case-insensitive)."}],"responses":{"200":{"description":"OK. `truncated` is true when the deployer has more launches than the 500-token analysis cap.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"is_deployer":{"type":"boolean"},"address":{"type":"string"},"deployer":{"type":"object","nullable":true},"success_metric":{"type":"string","example":"graduated ($40K+ peak market cap)"},"trajectory":{"type":"object","nullable":true,"properties":{"current_streak":{"type":"object","properties":{"type":{"type":"string","enum":["bond","fail","none"]},"count":{"type":"integer"}}},"longest_bond_streak":{"type":"integer"},"longest_fail_streak":{"type":"integer"},"rolling_bond_rates":{"type":"array","items":{"type":"object","properties":{"window_end":{"type":"integer"},"bond_rate":{"type":"number"}}},"description":"10-launch rolling hit rate."},"trend":{"type":"string","enum":["improving","declining","stable"]},"avg_days_between_deploys":{"type":"number","nullable":true},"avg_recovery_tokens":{"type":"number","nullable":true,"description":"Launches burned between a miss and the next hit."},"best_stretch":{"type":"object","nullable":true},"worst_stretch":{"type":"object","nullable":true},"total_tokens_analyzed":{"type":"integer"}}},"truncated":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/{address}/tokens":{"get":{"tags":["Robinhood Chain"],"summary":"Full paginated launch history for one RHC deployer (BASIC+)","description":"Every token a Robinhood Chain deployer has launched, enriched with live MC, peak MC and liquidity. Each token carries `liquidity_basis` (`v4_virtual_ceiling` | `measured`) — uniswap-v4 liquidity_usd is a virtual-reserve ceiling, not measured per-pool TVL. Distinct from `/rhc/deployer-hunter/{address}`, which caps `recent_tokens` at 50 and is a profile read — this is the enumerable history. Unknown wallets return 200 with `is_deployer: false`. Tier: **BASIC**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}},{"name":"sort","in":"query","schema":{"type":"string","enum":["first_seen_at","peak_mc_usd"],"default":"first_seen_at"},"description":"`peak_mc_usd` sorts the RETURNED PAGE only (peak MC lives in another table) — the response echoes `sort_scope: \"page\"` so it cannot be mistaken for a global ranking."},{"name":"include_launches_24h","in":"query","schema":{"type":"boolean","default":false},"description":"Opt in (TR-03) to `launches_24h`: distinct launches observed in OUR index (rhc_tokens first_seen_at) over a UTC rolling 24 h window. Indexed observations only, not a chain-complete count; `count` is null (never 0) when the source is unavailable, incomplete or over budget. Any value other than true/false is a 400 (`invalid_include_launches_24h`)."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"is_deployer":{"type":"boolean"},"address":{"type":"string"},"deployer":{"type":"object","nullable":true},"tokens":{"type":"array","items":{"type":"object"}},"total":{"type":"integer","description":"Lifetime launch count (not the page size)."},"launches_24h":{"type":"object","description":"Present only with include_launches_24h=true. count is null unless status is observed.","properties":{"window_start":{"type":"string","format":"date-time"},"window_end":{"type":"string","format":"date-time"},"count":{"type":"integer","nullable":true},"status":{"type":"string","enum":["observed","source_unavailable","over_budget","source_incomplete","untracked_deployer"]},"completeness":{"type":"string","enum":["indexed_observations_only"]},"provenance":{"type":"string"},"row_cap_per_source":{"type":"integer"},"source_rows":{"type":"object","properties":{"bonded":{"type":"integer"},"pending":{"type":"integer"}}}}},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"sort":{"type":"string"},"sort_scope":{"type":"string","enum":["page"]}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address or query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/best-tokens":{"get":{"tags":["Robinhood Chain"],"summary":"Top launches from reputable RHC deployers (BASIC+)","description":"The highest-peaking tokens launched by good/elite Robinhood Chain deployers in a window — \"what did the deployers worth tracking actually produce\". Gated on tier by design; for an unfiltered ranking use `/rhc/tokens?sort=peak_mc_usd`. Each token carries `liquidity_basis` (`v4_virtual_ceiling` | `measured`) — uniswap-v4 liquidity_usd is a virtual-reserve ceiling, not measured per-pool TVL. `truncated: true` means the window exceeded the 1,000-candidate scan, so the top-N is drawn from the most RECENT launches rather than the whole period. Tier: **BASIC**.","parameters":[{"name":"period","in":"query","schema":{"type":"string","enum":["24h","7d","30d","all"],"default":"7d"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"tokens":{"type":"array","items":{"type":"object"}},"period":{"type":"string"},"limit":{"type":"integer"},"reputable_deployers":{"type":"integer"},"candidates_scanned":{"type":"integer"},"truncated":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/deployer-hunter/stats":{"get":{"tags":["Robinhood Chain"],"summary":"Chain-wide RHC deployer reputation census (BASIC+)","description":"Population and token count per reputation tier across Robinhood Chain, plus alert volume. `tier_rules` echoes the ACTIVE thresholds so a consumer can see what \"elite\" currently means instead of inferring it from the label. Tier: **BASIC**.","responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"total_deployers":{"type":"integer"},"total_tokens":{"type":"integer"},"reputable_deployers":{"type":"integer","description":"elite + good."},"by_tier":{"type":"object","additionalProperties":{"type":"object","properties":{"deployers":{"type":"integer"},"tokens":{"type":"integer"}}}},"spam_token_share":{"type":"number","nullable":true},"alerts_24h":{"type":"integer"},"alerts_7d":{"type":"integer"},"tier_rules":{"type":"object","description":"The live tier CASE, e.g. elite = \"tokens_deployed >= 5 AND runner_rate >= 0.50\"."},"graduation_definition":{"type":"string","example":"peak market cap >= $40,000"},"runner_definition":{"type":"string","example":"peak market cap >= $100,000"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/token/batch":{"post":{"tags":["Robinhood Chain"],"summary":"Up to 50 Robinhood Chain tokens in one call (BASIC+)","description":"Set-based batch read — three queries regardless of batch size, not a fan-out. Returns token metadata, price/MC/liquidity and deployer reputation. Deliberately does NOT compute buyer-quality (that is a per-token cohort computation; use `/rhc/tokens/batch/buyer-quality`) so a caller who only wants prices does not pay for it. Accepts `addresses` or `mints` so a ported Solana client works unchanged. **One entry is returned per REQUESTED address, in order** — unknown tokens come back as `found: false` rather than being silently omitted. Tier: **BASIC**.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"addresses":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":50,"description":"0x EVM token addresses."},"mints":{"type":"array","items":{"type":"string"},"description":"Alias for `addresses` (Solana-client compatibility)."}}}}}},"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"tokens":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"found":{"type":"boolean"},"status":{"type":"string","enum":["ok","no_price_yet","mc_unavailable","not_seen_yet"],"description":"Why a price field is null: no_price_yet (seen, no priced trade yet), mc_unavailable (priced, MC failed the plausibility gate or supply unknown), not_seen_yet (found:false)."},"hint":{"type":"string","description":"found:false only."},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"graduated_at":{"type":"string","format":"date-time","nullable":true},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"price_usd":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"liquidity_source":{"type":"string","enum":["pool_balances","v4_virtual_ceiling","bonding_curve_reserve","unknown_venue"],"description":"Where liquidity_usd comes from: pool_balances = uniswap-v2/v3 pool token balances; v4_virtual_ceiling = uniswap-v4 virtual reserves clamped to the PoolManager (a ceiling); bonding_curve_reserve = 2x a launchpad curve quote reserve from contract state (pons-v2, flap, hood.fun, bags); unknown_venue = no recognised primary venue."},"liquidity_status":{"type":"string","enum":["available","verified_zero","unavailable"],"description":"available = positive figure; verified_zero = explicit 0 from chain state; unavailable = liquidity_usd is null (unknown, not yet measured, unresolved quote asset, or graduated curve awaiting its pool figure). Null never means zero."},"peak_mc_at":{"type":"string","format":"date-time","nullable":true},"primary_dex":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true},"deployer":{"type":"object","nullable":true,"description":"address + source, plus the deployer's reputation row (tier, tokens_deployed, graduated, graduation_rate, runners, runner_rate) when known."}}}},"requested":{"type":"integer"},"found":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Body must be { addresses: string[] } with 1-50 valid 0x addresses.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/tokens/batch/buyer-quality":{"post":{"tags":["Robinhood Chain"],"summary":"Early-buyer quality for up to 20 RHC tokens (BASIC+)","description":"Scores several tokens' earliest-buyer cohorts in one call. **The cap is 20, not the Solana 50** — RHC buyer-quality is a per-token cohort computation (ordered early-buyer scan + bundle RPC + alpha/cluster joins) that cannot collapse into one set-based query, so 50 would mean ~200 round-trips behind a single request. A per-token failure degrades to an `error` entry rather than failing the batch. Scores are identical to the single-token endpoint (shared scorer). Tier: **BASIC**.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"addresses":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":20},"mints":{"type":"array","items":{"type":"string"},"description":"Alias for `addresses`."}}}}}},"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"tokens":{"type":"array","items":{"type":"object"},"description":"Either a scored result or `{ token_address, error }`."},"requested":{"type":"integer"},"scored":{"type":"integer"},"max_addresses":{"type":"integer","example":20},"coverage":{"type":"object"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Body must be { addresses: string[] } with 1-20 valid 0x addresses. Response echoes `max_addresses`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/token/{address}":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/tokens/{address} (BASIC+)","description":"Path alias so a Solana integration ported to Robinhood Chain does not 404 on a capability we ship. Solana exposes the single-token read at `/token/{mint}` (SINGULAR); the RHC tree uses `/rhc/tokens/{address}` (plural). Identical handler and response — not a redirect. Tier: **BASIC**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Identical to `/rhc/tokens/{address}`.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"graduated_pool":{"type":"string","nullable":true},"graduated_at":{"type":"string","format":"date-time","nullable":true},"deployer_address":{"type":"string","nullable":true},"first_seen_at":{"type":"string","format":"date-time","nullable":true},"token_age_minutes":{"type":"integer","nullable":true},"price_usd":{"type":"number","nullable":true},"price_native":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"fdv_usd":{"type":"number","nullable":true},"peak_mc_usd":{"type":"number","nullable":true},"peak_mc_at":{"type":"string","format":"date-time","nullable":true},"drawdown_from_peak_pct":{"type":"integer","nullable":true},"total_supply_raw":{"type":"string","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. uniswap-v4 has no per-pool balances, so its figure is virtual reserves clamped to the PoolManager's total holdings — a provable CEILING, not measured per-pool TVL."},"liquidity_note":{"type":"string","description":"Human-readable statement of the uniswap-v4 ceiling semantics; constant."},"liquidity_source":{"type":"string","enum":["pool_balances","v4_virtual_ceiling","bonding_curve_reserve","unknown_venue"],"description":"Where liquidity_usd comes from: pool_balances = uniswap-v2/v3 pool token balances; v4_virtual_ceiling = uniswap-v4 virtual reserves clamped to the PoolManager (a ceiling); bonding_curve_reserve = 2x a launchpad curve quote reserve from contract state (pons-v2, flap, hood.fun, bags); unknown_venue = no recognised primary venue."},"liquidity_status":{"type":"string","enum":["available","verified_zero","unavailable"],"description":"available = positive figure; verified_zero = explicit 0 from chain state; unavailable = liquidity_usd is null (unknown, not yet measured, unresolved quote asset, or graduated curve awaiting its pool figure). Null never means zero."},"primary_dex":{"type":"string","nullable":true},"primary_pool":{"type":"string","nullable":true},"last_trade_time":{"type":"string","format":"date-time","nullable":true},"deployer":{"type":"object","nullable":true,"description":"Deployer reputation.","properties":{"address":{"type":"string"},"tier":{"type":"string","enum":["elite","good","neutral","spammer"]},"tokens_deployed":{"type":"integer"},"graduation_rate":{"type":"number","nullable":true},"runner_rate":{"type":"number","nullable":true},"runners":{"type":"integer"},"best_peak_mc_usd":{"type":"number","nullable":true},"launchpads":{"type":"array","items":{"type":"string"}}}},"deployer_other_tokens":{"type":"array","items":{"type":"string"},"description":"Up to 10 other tokens by the same deployer (symbol or address)."},"kol_activity":{"type":"object","properties":{"distinct_kols":{"type":"integer"},"names":{"type":"array","items":{"type":"string"}},"buys":{"type":"integer"},"sells":{"type":"integer"},"net_eth":{"type":"number"}}},"pools":{"type":"array","description":"Up to 20 pools with reserves/liquidity/sqrt_price. Each entry carries `liquidity_basis` (`v4_virtual_ceiling` | `measured`) for its own `liquidity_usd`.","items":{"type":"object"}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/lp-events":{"get":{"tags":["Robinhood Chain"],"summary":"Liquidity REMOVALS feed — the rug signal (PRO+)","description":"Liquidity removals on Robinhood Chain from our own node's log subscription: Uniswap v2/v3 Burn and v4 ModifyLiquidity with a negative delta, for tracked pools. **By default removals only** — a request without `action` returns exactly what it always did, so an empty default page means 'no removals seen', never 'no liquidity activity'. Amounts are RAW on-chain integers as strings; token0/token1 say which side is which and token_amount_raw/quote_amount_raw pre-resolve the token side. v4 rows carry liquidity only (the pool manager emits no token amounts). provider_is_token_deployer is the classic rug tell. Cursor via next_before (same opaque (block_time,id) keyset as /rhc/trades). Data since 2026-08-05. **Adds, pool creations and depth fields (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 (kept 30 days like removals), persisted since the WS Phase 3 producer — earlier windows hold removals only. Every row also carries `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 % of reserves / active liquidity), null where the pool state was unknown and on older rows. `provider` is the log's sender/owner — usually the router or position manager on v3/v4, not the beneficial owner. The same events are pushed live on WS channel `rhc:lp_events` (ULTRA+). Tier: **PRO+**.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Rows per page (1-200, default 50)."},{"name":"token","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Filter to one token address."},{"name":"pool","in":"query","schema":{"type":"string"},"description":"Pool address (v2/v3) or bytes32 poolId (v4)."},{"name":"provider","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Filter to one liquidity provider (the wallet that pulled)."},{"name":"dex","in":"query","schema":{"type":"string","enum":["uniswap-v2","uniswap-v3","uniswap-v4"]}},{"name":"action","in":"query","schema":{"type":"string","enum":["remove","add","pool_created","all"],"default":"remove"},"description":"Which liquidity actions to return (2026-09-23). Default `remove` = the historical removals-only feed, unchanged. `add` (kept 7 days), `pool_created` or `all` opt into the rows persisted since the WS Phase 3 producer."},{"name":"before","in":"query","schema":{"type":"string"},"description":"Opaque cursor from next_before."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"events":{"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["remove","add","pool_created"],"description":"The row's action. Always `remove` on a request without `action`."},"pool":{"type":"string"},"dex":{"type":"string","enum":["uniswap-v2","uniswap-v3","uniswap-v4"]},"fee_tier":{"type":"integer","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"token_decimals":{"type":"integer","nullable":true},"launchpad":{"type":"string","nullable":true},"provider":{"type":"string","nullable":true,"description":"Wallet that removed liquidity."},"provider_is_token_deployer":{"type":"boolean","description":"True when the provider is the token's own deployer — the classic rug shape."},"provider_deployer_tier":{"type":"string","nullable":true},"provider_kol_name":{"type":"string","nullable":true},"liquidity":{"type":"string","nullable":true,"description":"Raw liquidity units removed (v3/v4). String — uint256."},"amount0":{"type":"string","nullable":true,"description":"Raw token0 amount (v2/v3 only). String."},"amount1":{"type":"string","nullable":true,"description":"Raw token1 amount (v2/v3 only). String."},"token0":{"type":"string","nullable":true},"token1":{"type":"string","nullable":true},"token_amount_raw":{"type":"string","nullable":true,"description":"amount0 or amount1, whichever is the token side."},"quote_token":{"type":"string","nullable":true},"quote_amount_raw":{"type":"string","nullable":true},"block_number":{"type":"integer"},"block_time":{"type":"string","format":"date-time","description":"Exact block header timestamp."},"tx_hash":{"type":"string"},"log_index":{"type":"integer"},"tick_lower":{"type":"integer","nullable":true,"description":"Position range lower tick (v3/v4); null on v2 (full range) and on rows written before 2026-09-23."},"tick_upper":{"type":"integer","nullable":true,"description":"Position range upper tick (v3/v4)."},"liquidity_delta":{"type":"string","nullable":true,"description":"Signed liquidity change (+ add, - remove), v3/v4. String — int256."},"in_range":{"type":"boolean","nullable":true,"description":"tick_lower <= current tick < tick_upper just before the event; null when the pool's tick was unknown."},"active_liquidity_delta":{"type":"string","nullable":true,"description":"Change to ACTIVE liquidity: liquidity_delta when in range, \"0\" out of range, null when unknown."},"active_share":{"type":"number","nullable":true,"description":"|active delta| / active liquidity before (v3/v4). 0 for an out-of-range change; adds can exceed 1; null when unknown."},"share_of_reserves":{"type":"number","nullable":true,"description":"v2 only: amount / reserve before, from the pair's Sync; null for a pair's first liquidity or when the Sync was not found."},"material":{"type":"boolean","nullable":true,"description":"true = a REMOVAL of at least 25 % of reserves (v2) or active liquidity (v3/v4); false = a removal with a known smaller share; null for adds, pool creations and unknown shares."}}}},"count":{"type":"integer"},"has_more":{"type":"boolean"},"next_before":{"type":"string","nullable":true},"coverage":{"type":"object","description":"Honesty block: events (the actions this response covers — [remove] by default), adds_persisted (true since 2026-09-23), adds_retention_days (7), note, since."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters (code invalid_query).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/locks":{"get":{"tags":["Robinhood Chain"],"summary":"Token locks & vesting feed — newest lock contracts across all tokens (PRO+)","description":"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 (services/rhc-lock-tracker, chain-wide topic0 probe with no address filter — a new deployment of a known locker shape is caught on first sight): PinkLock-compatible, HoodLock (+ vesting), Team Finance-compatible (+ LP NFT), Titan Locker (token / LP / position), UNCX v2/v3-compatible LP lockers, Sablier Lockup v4 (linear / tranched / dynamic). Every 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` is the depositor/creator (compare with the token's deployer for a dev lock), `recipient` the beneficiary when different; `cancelable` / `cancelable_by_sender` from Sablier's flag (null where the family does not say). Amounts are RAW base units as strings; ui/usd/pct are null when decimals/price are unknown. **Create-only tape**: withdrawals / cancels are NOT tracked (no RHC locker publishes a verified release event shape) — `withdrawn` is null (unknown), never 0, and the `coverage` block says `withdrawals_tracked: false`. LP locks (subject=lp — RHC launchpads auto-lock LP on every launch) are stored but excluded unless `subject=lp|all`, carry pair/liquidity units and never claim usd/pct. Cursor: `cursor=` (`pagination.next_cursor`, strict (created_at, id) — preferred), `since=` (`pagination.next_since`) / legacy `before=`. The status / min_usd / min_pct_of_supply post-filters are served by a bounded scan (`pagination.scan`). Pushed live as `rhc:token_lock` on WS channel `rhc:token_locks`. Tier: **PRO+**.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only locks created after this instant (poll cursor = pagination.next_since)."},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"Legacy: only locks created strictly before this instant (page back = pagination.next_before; skips locks sharing that created_at — prefer cursor)."},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":200},"description":"PREFERRED pagination (audit F09 follow-up): the `next_cursor` from a previous page — an opaque strict (created_at, id) keyset, so paging never repeats or skips rows that share a sort value and progresses with limit=1 through runs of identical timestamps. Malformed or tampered → 400. Cannot be combined with `before=` (400)."},{"name":"token","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"sender","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Depositor / creator wallet."},{"name":"recipient","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Beneficiary wallet."},{"name":"locker","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Locker contract address."},{"name":"family","in":"query","schema":{"type":"string","enum":["pinklock","teamfinance","teamfinance-nft","uncx-v2-lp","uncx-v3-lp","uncx-vesting","vesting-fork","goplus","titan","titan-position","titan-vesting","hoodlock","hoodlock-vesting","sablier","stonkbrokers-vesting"]}},{"name":"kind","in":"query","schema":{"type":"string","enum":["lock","vesting"]}},{"name":"subject","in":"query","schema":{"type":"string","enum":["token","lp","all"],"default":"token"},"description":"token (default) excludes LP locks; lp = only LP locks; all = both."},{"name":"status","in":"query","schema":{"type":"string","enum":["active","completed"]}},{"name":"min_usd","in":"query","schema":{"type":"number","minimum":0},"description":"Post-filter on the deposited amount in USD (bounded scan — see pagination.scan)."},{"name":"min_pct_of_supply","in":"query","schema":{"type":"number","minimum":0,"maximum":100},"description":"Post-filter on the deposited amount as % of supply."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"locks":{"type":"array","items":{"type":"object","properties":{"lock_id":{"type":"string","description":"`<tx_hash>:<log_index>` — the row identity."},"locker":{"type":"string"},"locker_name":{"type":"string","nullable":true},"provider":{"type":"object","description":"Who runs the lock contract, and how sure we are. identity: verified = a known provider deployment (by contract address); compatible = only the event shape (ABI) matches a known provider, the operator is NOT identified; unverified = unknown. id/website_url are null unless verified. lock_url is a per-lock page on the provider's site, emitted ONLY where the URL format is proven (HoodLock vault: /proof/lock/{locker_lock_id}); otherwise null (never guessed).","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"identity":{"type":"string","enum":["verified","compatible","unverified"]},"compatible_with":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"lock_url":{"type":"string","nullable":true}}},"explorer":{"type":"object","description":"Independent evidence on Blockscout.","properties":{"locker_url":{"type":"string","nullable":true},"creation_tx_url":{"type":"string","nullable":true}}},"price_usd":{"type":"number","nullable":true,"description":"Token price used for the *_usd fields (null when unknown or guarded as phantom)."},"seconds_until_end":{"type":"integer","nullable":true,"description":"Seconds until fully unlocked (>= 0). 0 once completed; null when there is no end date (perpetual) or the lock was cancelled/closed."},"seconds_until_next_unlock":{"type":"integer","nullable":true,"description":"Seconds until next_unlock.at (>= 0); null when there is no next unlock."},"family":{"type":"string"},"family_name":{"type":"string"},"locker_lock_id":{"type":"string","nullable":true},"kind":{"type":"string","enum":["lock","vesting"]},"subject":{"type":"string","enum":["token","lp"]},"status":{"type":"string","enum":["active","completed"]},"token_address":{"type":"string"},"lp":{"type":"object","nullable":true,"description":"Only on subject=lp: kind (v2_pair | v3_position | v4_position), pool, token0, token1, token_id."},"sender":{"type":"string","description":"Depositor / creator — the dev-lock comparison key."},"recipient":{"type":"string","nullable":true},"tx_sender":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"amount_raw":{"type":"string","nullable":true},"amount":{"type":"number","nullable":true},"amount_usd":{"type":"number","nullable":true},"amount_pct_of_supply":{"type":"number","nullable":true},"amount_unit":{"type":"string","nullable":true,"description":"token | lp_token | liquidity (uncx-v3) — LP rows never claim usd/pct."},"locked_raw":{"type":"string","nullable":true},"locked":{"type":"number","nullable":true},"locked_usd":{"type":"number","nullable":true},"locked_pct_of_supply":{"type":"number","nullable":true},"unlocked_raw":{"type":"string","nullable":true},"unlocked":{"type":"number","nullable":true},"withdrawn_raw":{"type":"string","nullable":true,"description":"Always null — withdrawals are not tracked on RHC."},"withdrawn":{"type":"number","nullable":true},"start_at":{"type":"string","nullable":true},"cliff_at":{"type":"string","nullable":true},"end_at":{"type":"string","nullable":true},"cliff_amount_raw":{"type":"string","nullable":true},"cliff_amount":{"type":"number","nullable":true},"continuous":{"type":"boolean","description":"Linear per-second release between cliff and end."},"perpetual":{"type":"boolean"},"schedule":{"type":"array","nullable":true,"description":"Tranches (Sablier tranched/dynamic): release_at, amount_raw, amount.","items":{"type":"object"}},"next_unlock":{"type":"object","nullable":true,"description":"at, kind (cliff | final | tranche), amount_raw, amount, amount_usd."},"cancelable":{"type":"boolean","nullable":true},"cancelable_by_sender":{"type":"boolean","nullable":true},"transferable":{"type":"boolean","nullable":true},"created_at":{"type":"string","format":"date-time","description":"= block_time of the creation event."},"created_at_estimated":{"type":"boolean","description":"Always false on RHC."},"block_number":{"type":"integer"},"block_time":{"type":"string","format":"date-time"},"tx_hash":{"type":"string"},"log_index":{"type":"integer"},"layout_verified":{"type":"boolean","description":"false only for families decoded from published source without a live log yet (titan-vesting)."},"token":{"type":"object","properties":{"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"price_usd":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"liquidity_usd":{"type":"number","nullable":true}}}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"count":{"type":"integer"},"has_more":{"type":"boolean","description":"false only when the candidate feed is exhausted (not merely when the page is short)."},"next_cursor":{"type":"string","nullable":true,"description":"Opaque keyset cursor for the next (older) page — pass as `cursor=`. null = end of feed. PREFERRED over the strict-timestamp legacy cursor, which skips same-timestamp siblings of the boundary row."},"next_since":{"type":"string","nullable":true},"next_before":{"type":"string","nullable":true,"description":"Legacy: created_at of the last row consumed (strict bound — skips ties)."},"scan":{"type":"object","description":"Present when a filter had to be applied after the candidate fetch (audit F09): has_more is then false only when the candidates ran out, and scan_truncated=true means the per-request scan budget ran out first — more matches MAY exist past next_cursor.","properties":{"post_filtered":{"type":"boolean"},"scanned":{"type":"integer","description":"Candidate rows examined"},"scan_truncated":{"type":"boolean","description":"The per-request scan budget ran out before `limit` matches — more matches MAY exist past the cursor/offset"},"scan_budget":{"type":"integer"}}}}},"stream":{"type":"object","description":"WS pointer: channel rhc:token_locks, event rhc:token_lock."},"coverage":{"type":"object","description":"Honesty block: families, withdrawals_tracked false, cancels_tracked false, lp_locks, note."},"meta":{"type":"object"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters (code invalid_query).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/locks":{"get":{"tags":["Robinhood Chain"],"summary":"Token locks & vesting on one token — live locked / next unlock / 7d & 30d schedule (PRO+)","description":"Every lock / vesting contract on one Robinhood Chain token with a live derived view: what is still locked right now (deposited − unlocked-so-far by the schedule), what unlocks next, the 7d / 30d unlock schedule and whether the locker can cancel — 'did the team lock, how much, until when'. `summary` covers the token-subject rows (counts by family / kind, distinct depositing wallets and locker contracts, locked / deposited raw + ui + usd + % of supply, `unlocking_7d_*` / `unlocking_30d_*`, nearest `next_unlock`, `active_cancelable_by_sender`); LP locks on the token's pools are listed under subject=lp and counted apart (`lp_lock_count`, `lp_lock_active_count`) because their amounts are pair / liquidity units. Rows are active-first, largest locked first. `token.facts_resolved` is false when decimals are unknown — every ui / usd / pct field is then null. Same create-only caveat as the feed (`coverage.withdrawals_tracked: false`): an unlocked-but-unclaimed balance counts as unlocked. Tier: **PRO+**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"status","in":"query","schema":{"type":"string","enum":["active","completed"]}},{"name":"family","in":"query","schema":{"type":"string"}},{"name":"subject","in":"query","schema":{"type":"string","enum":["token","lp","all"],"default":"all"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":200},"description":"Rows returned; the summary always covers every row on the token (up to 5000)."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"token_address":{"type":"string"},"token":{"type":"object","properties":{"symbol":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"price_usd":{"type":"number","nullable":true},"supply":{"type":"number","nullable":true},"market_cap_usd":{"type":"number","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"facts_resolved":{"type":"boolean"}}},"summary":{"type":"object","properties":{"lock_count":{"type":"integer"},"complete":{"type":"boolean"},"rows_considered":{"type":"integer"},"token_lock_count":{"type":"integer"},"lp_lock_count":{"type":"integer"},"lp_lock_active_count":{"type":"integer"},"active_count":{"type":"integer"},"by_family":{"type":"object"},"by_kind":{"type":"object"},"distinct_lockers":{"type":"integer"},"distinct_locker_contracts":{"type":"integer"},"locked_raw":{"type":"string"},"locked":{"type":"number","nullable":true},"locked_usd":{"type":"number","nullable":true},"locked_pct_of_supply":{"type":"number","nullable":true},"deposited_raw":{"type":"string"},"deposited":{"type":"number","nullable":true},"deposited_usd":{"type":"number","nullable":true},"unlocking_7d_raw":{"type":"string"},"unlocking_7d":{"type":"number","nullable":true},"unlocking_7d_usd":{"type":"number","nullable":true},"unlocking_7d_pct_of_supply":{"type":"number","nullable":true},"unlocking_30d_raw":{"type":"string"},"unlocking_30d":{"type":"number","nullable":true},"unlocking_30d_usd":{"type":"number","nullable":true},"unlocking_30d_pct_of_supply":{"type":"number","nullable":true},"next_unlock":{"type":"object","nullable":true},"active_cancelable_by_sender":{"type":"integer"}}},"locks":{"type":"array","items":{"type":"object","description":"Same row shape as /rhc/tokens/locks (without the token embed)."}},"coverage":{"type":"object"},"meta":{"type":"object"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid address (code invalid_address) or query (code invalid_query).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/unlocks":{"get":{"tags":["Robinhood Chain"],"summary":"Upcoming unlock events across all active RHC lock / vesting contracts (PRO+)","description":"Upcoming unlock EVENTS on Robinhood Chain — each active token lock / vesting contract's NEXT cliff, tranche or final unlock inside the window: which tokens have supply hitting the market this week, how much, from whose lock. `amount_*` is the next event, `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 (LP locks excluded). Candidates come off the writer-maintained `next_unlock_at` column (rolled forward every 2 min) so every active contract is considered per call; 60 s in-process cache with the window quantised to the same bucket. Prices with an implied market cap above $100B are treated as phantom → usd null. Tier: **PRO+**.","parameters":[{"name":"within","in":"query","schema":{"type":"string","enum":["1h","6h","24h","3d","7d","14d","30d","90d"],"default":"7d"}},{"name":"token","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"family","in":"query","schema":{"type":"string"}},{"name":"kind","in":"query","schema":{"type":"string","enum":["lock","vesting"]}},{"name":"min_usd","in":"query","schema":{"type":"number","minimum":0},"description":"On the next-event amount."},{"name":"min_pct_of_supply","in":"query","schema":{"type":"number","minimum":0,"maximum":100},"description":"On the next-event amount."},{"name":"sort","in":"query","schema":{"type":"string","enum":["soonest","largest_usd","largest_pct"],"default":"soonest"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"window":{"type":"object","properties":{"within":{"type":"string"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"unlocks":{"type":"array","items":{"type":"object","properties":{"unlock_at":{"type":"string","format":"date-time"},"in_seconds":{"type":"integer"},"event":{"type":"string","enum":["cliff","final","tranche"]},"amount_raw":{"type":"string"},"amount":{"type":"number","nullable":true},"amount_usd":{"type":"number","nullable":true},"amount_pct_of_supply":{"type":"number","nullable":true},"window_amount_raw":{"type":"string"},"window_amount":{"type":"number","nullable":true},"window_amount_usd":{"type":"number","nullable":true},"window_amount_pct_of_supply":{"type":"number","nullable":true},"token_address":{"type":"string"},"token":{"type":"object"},"lock":{"type":"object","description":"lock_id, locker, locker_name, family, kind, name, sender, recipient, amount_*, locked_*, cliff_at, end_at, cancelable_by_sender, tx_hash."}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"count":{"type":"integer"},"total_in_window":{"type":"integer"},"has_more":{"type":"boolean"},"candidates_capped":{"type":"boolean"}}},"coverage":{"type":"object"},"meta":{"type":"object"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters (code invalid_query).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/lp-events":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/lp-events?token= (PRO+)","description":"Path alias: liquidity removals for one token. Delegates to /rhc/lp-events with token pinned to the path segment; pagination, enrichment and the removals-only honesty block are identical. Tier: **PRO+**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"before","in":"query","schema":{"type":"string"}},{"name":"dex","in":"query","schema":{"type":"string","enum":["uniswap-v2","uniswap-v3","uniswap-v4"]}},{"name":"action","in":"query","schema":{"type":"string","enum":["remove","add","pool_created","all"],"default":"remove"},"description":"Same as on /rhc/lp-events: default `remove` (unchanged), or opt into adds / pool creations (2026-09-23)."}],"responses":{"200":{"description":"Identical to /rhc/lp-events?token={address}.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"events":{"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["remove","add","pool_created"],"description":"The row's action. Always `remove` on a request without `action`."},"pool":{"type":"string"},"dex":{"type":"string","enum":["uniswap-v2","uniswap-v3","uniswap-v4"]},"fee_tier":{"type":"integer","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"token_decimals":{"type":"integer","nullable":true},"launchpad":{"type":"string","nullable":true},"provider":{"type":"string","nullable":true,"description":"Wallet that removed liquidity."},"provider_is_token_deployer":{"type":"boolean","description":"True when the provider is the token's own deployer — the classic rug shape."},"provider_deployer_tier":{"type":"string","nullable":true},"provider_kol_name":{"type":"string","nullable":true},"liquidity":{"type":"string","nullable":true,"description":"Raw liquidity units removed (v3/v4). String — uint256."},"amount0":{"type":"string","nullable":true,"description":"Raw token0 amount (v2/v3 only). String."},"amount1":{"type":"string","nullable":true,"description":"Raw token1 amount (v2/v3 only). String."},"token0":{"type":"string","nullable":true},"token1":{"type":"string","nullable":true},"token_amount_raw":{"type":"string","nullable":true,"description":"amount0 or amount1, whichever is the token side."},"quote_token":{"type":"string","nullable":true},"quote_amount_raw":{"type":"string","nullable":true},"block_number":{"type":"integer"},"block_time":{"type":"string","format":"date-time","description":"Exact block header timestamp."},"tx_hash":{"type":"string"},"log_index":{"type":"integer"},"tick_lower":{"type":"integer","nullable":true,"description":"Position range lower tick (v3/v4); null on v2 (full range) and on rows written before 2026-09-23."},"tick_upper":{"type":"integer","nullable":true,"description":"Position range upper tick (v3/v4)."},"liquidity_delta":{"type":"string","nullable":true,"description":"Signed liquidity change (+ add, - remove), v3/v4. String — int256."},"in_range":{"type":"boolean","nullable":true,"description":"tick_lower <= current tick < tick_upper just before the event; null when the pool's tick was unknown."},"active_liquidity_delta":{"type":"string","nullable":true,"description":"Change to ACTIVE liquidity: liquidity_delta when in range, \"0\" out of range, null when unknown."},"active_share":{"type":"number","nullable":true,"description":"|active delta| / active liquidity before (v3/v4). 0 for an out-of-range change; adds can exceed 1; null when unknown."},"share_of_reserves":{"type":"number","nullable":true,"description":"v2 only: amount / reserve before, from the pair's Sync; null for a pair's first liquidity or when the Sync was not found."},"material":{"type":"boolean","nullable":true,"description":"true = a REMOVAL of at least 25 % of reserves (v2) or active liquidity (v3/v4); false = a removal with a known smaller share; null for adds, pool creations and unknown shares."}}}},"count":{"type":"integer"},"has_more":{"type":"boolean"},"next_before":{"type":"string","nullable":true},"coverage":{"type":"object","description":"Honesty block: events (the actions this response covers — [remove] by default), adds_persisted (true since 2026-09-23), adds_retention_days (7), note, since."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/trades":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/trades?token= (PRO+)","description":"Path alias: Solana exposes per-token trades as a SUBPATH (`/tokens/{mint}/trades`) while RHC exposes it as a FILTER on the trade tape. Delegates to `/rhc/trades` with `token` pinned to the path segment, so pagination, enrichment and gating stay identical. A caller-supplied `token` query param is overridden by the path. Tier: **PRO+** (inherits the /rhc/trades gate — BASIC gets 403).","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"before","in":"query","schema":{"type":"string"},"description":"Opaque cursor from next_before; a bare ISO block_time is also accepted for backward compatibility."},{"name":"action","in":"query","schema":{"type":"string","enum":["buy","sell"]}}],"responses":{"200":{"description":"Identical to `/rhc/trades?token={address}`.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"trades":{"type":"array","items":{"type":"object","properties":{"block_number":{"type":"integer"},"block_time":{"type":"string","format":"date-time"},"tx_hash":{"type":"string"},"log_index":{"type":"integer"},"dex":{"type":"string"},"pool":{"type":"string"},"trader":{"type":"string","nullable":true,"description":"Swap-log recipient — the ROUTER for aggregated swaps. Use trader_eoa for wallet analytics."},"trader_eoa":{"type":"string","nullable":true,"description":"Authoritative trader wallet. Normally tx.from; on ERC-4337 transactions this is the userOp sender (the account that actually traded) and tx.from — the bundler — is not returned."},"router":{"type":"string","nullable":true,"description":"Router/aggregator contract (tx.to)."},"token_address":{"type":"string","nullable":true},"action":{"type":"string","enum":["buy","sell"],"nullable":true},"eth_amount":{"type":"number","nullable":true},"price_native":{"type":"number","nullable":true},"price_usd":{"type":"number","nullable":true},"mc_usd_at_trade":{"type":"number","nullable":true},"gas_price":{"type":"number","nullable":true,"description":"Effective gas price, gwei."},"tx_index":{"type":"integer","nullable":true,"description":"Transaction position within the block (ordering / sandwich detection)."},"method_selector":{"type":"string","nullable":true,"description":"4-byte calldata selector."},"liquidity":{"type":"number","nullable":true,"description":"v3/v4 in-range liquidity at the trade."},"launchpad":{"type":"string","nullable":true},"is_kol":{"type":"boolean","description":"True if trader_eoa is a tracked KOL wallet."},"kol_name":{"type":"string","nullable":true},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"],"description":"Set if trader_eoa is a known deployer."}}}},"count":{"type":"integer"},"has_more":{"type":"boolean","description":"True when another page exists beyond this one."},"next_before":{"type":"string","nullable":true,"description":"Opaque (block_time, id) keyset cursor for the next page; null when has_more is false."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM token address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/kol/tokens/hot":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/kol/hot-tokens (BASIC+)","description":"Path alias matching Solana's `/kol/tokens/hot`. Identical handler — note it takes `window`, not `limit`. Tier: **BASIC**.","parameters":[{"name":"window","in":"query","schema":{"type":"string","default":"1h"}}],"responses":{"200":{"description":"Identical to `/rhc/kol/hot-tokens`.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"window":{"type":"string","enum":["5m","15m","1h","6h","24h"]},"tokens":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true,"description":"noxa | flap | pons | hood.fun | clanker | null."},"is_graduated":{"type":"boolean","nullable":true},"deployer_tier":{"type":"string","nullable":true,"description":"elite | good | neutral | spammer | null."},"kols_buying":{"type":"integer","description":"Distinct KOL buyers in the window (>= 2)."},"buys":{"type":"integer"},"sells":{"type":"integer"},"buy_eth":{"type":"number"},"net_eth":{"type":"number","description":"buy_eth − sell_eth."},"market_cap_usd":{"type":"number","nullable":true,"description":"Current market cap."},"last_trade_at":{"type":"string","format":"date-time"}}}},"count":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"FREE","x-badges":[{"name":"FREE","position":"after","color":"#64748b"}]}},"/rhc/alpha/leaderboard":{"get":{"tags":["Robinhood Chain"],"summary":"Alias of /rhc/alpha-wallets (PRO+)","description":"Path alias matching Solana's `/alpha/leaderboard`. Identical handler, including the PRO+ gate. Tier: **PRO**.","responses":{"200":{"description":"Identical to `/rhc/alpha-wallets`.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"wallets":{"type":"array","items":{"type":"object","properties":{"wallet":{"type":"string","description":"Trader EOA (lowercase 0x)."},"classification":{"type":"string","enum":["bot","smart_money","trader"]},"is_known_kol":{"type":"boolean"},"trades":{"type":"integer"},"tokens":{"type":"integer"},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"net_eth":{"type":"number","description":"Realized net flow (sell − buy)."},"win_rate":{"type":"number","nullable":true},"memecoin_share":{"type":"number","nullable":true,"description":"Share of trades in launchpad memecoins (vs tokenized stocks/stables)."},"avg_trade_mc_usd":{"type":"number","nullable":true},"last_trade_at":{"type":"string","format":"date-time","nullable":true},"zero_cost_share":{"type":"number","nullable":true,"description":"Share of gross ETH extracted from tokens with no recorded buy (deployer/insider dumps). Null = never sold. ≥0.5 wallets are excluded unless include_zero_cost_dumps=true."}}}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"attribution":{"type":"object","description":"Interim attribution disclosure: mv_rhc_alpha_wallets is built from attributed trades only (`trader_eoa IS NOT NULL`), and trader_eoa was only written reliably from 2026-07-18 — pre-floor history is not reflected in win_rate/net_eth/classification. Removed once the trader_eoa backfill lands.","properties":{"attribution_complete_from":{"type":"string","format":"date-time"},"note":{"type":"string"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"PRO+ tier required.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/alpha-wallets":{"get":{"tags":["Robinhood Chain"],"summary":"Smart-money wallet ranking on Robinhood Chain (PRO+)","description":"Robinhood Chain trader wallets ranked by realized on-chain performance — the reverse of KOL discovery: instead of tracing Solana wallets onto RHC, we rank the wallets we already watch trade. `net_eth` is realized net flow (sell − buy, honest about ignoring unrealized holdings); `win_rate` is the share of traded tokens taken out profitably; `likely_bot` flags atomic-arb/MM fleets (near-perfect win rate across many tokens). Because RHC is dual-natured (launchpad memecoins vs tokenized stocks/stables), `memecoin_share` = launchpad-token trade share — filter with `min_memecoin_share` to isolate memecoin traders, or `max_avg_mc_usd` for low-caps. Derived from our self-hosted node, refreshed every 15 min.\n\n**Zero-cost-basis dumps, filtered by default** (*added 2026-08-29*): `net_eth` is `sell_eth − buy_eth` per wallet, and for a token a wallet never bought (its own on-chain buy leg unattributed — almost always a deployer/insider allocation sold with no purchase), the whole sale counts as \"profit\" even though it isn't trading skill. `zero_cost_share` is the fraction of a wallet's gross ETH extracted (sell-side) that came from such tokens; wallets at or above 0.5 are excluded from this listing by default (~23% of tracked wallets, concentrated at the very top of a raw net_eth sort) since their ranking and win_rate are inflated by dumps, not performance. The row still exists in the underlying dataset — pass `include_zero_cost_dumps=true` for the unfiltered ranking, and read `zero_cost_share` on each row either way; do not treat a high `net_eth` from this endpoint as trading profit without checking it. Tier: **PRO+**.","parameters":[{"name":"classification","in":"query","schema":{"type":"string","enum":["all","human","bot","smart_money"],"default":"all"},"description":"human = not likely_bot; smart_money = human + net_eth ≥ 2 + win_rate ≥ 0.45."},{"name":"identity","in":"query","schema":{"type":"string","enum":["all","known_kol","unknown"],"default":"all"},"description":"known_kol = already mapped to a tracked Solana KOL; unknown = net-new RHC smart money."},{"name":"min_memecoin_share","in":"query","schema":{"type":"number","minimum":0,"maximum":1},"description":"Minimum share of trades in launchpad memecoins (0.7 ≈ mostly-memecoin traders). Excludes tokenized-stock/stablecoin traders."},{"name":"max_avg_mc_usd","in":"query","schema":{"type":"number"},"description":"Maximum average market cap traded — filter to low-cap degens."},{"name":"min_net_eth","in":"query","schema":{"type":"number"}},{"name":"min_win_rate","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"max_win_rate","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"min_trades","in":"query","schema":{"type":"integer","minimum":0}},{"name":"min_tokens","in":"query","schema":{"type":"integer","minimum":0}},{"name":"min_buy_eth","in":"query","schema":{"type":"number"},"description":"Minimum ETH deployed (whale/size filter)."},{"name":"active_hours","in":"query","schema":{"type":"integer","minimum":1,"maximum":720},"description":"Only wallets that traded within the last N hours."},{"name":"sort","in":"query","schema":{"type":"string","enum":["net_eth","win_rate","trades","tokens","buy_eth","memecoin_share","last_trade_at"],"default":"net_eth"}},{"name":"order","in":"query","schema":{"type":"string","enum":["desc","asc"],"default":"desc"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}},{"name":"include_zero_cost_dumps","in":"query","schema":{"type":"boolean","default":false},"description":"Include wallets whose net_eth/win_rate are ≥50% inflated by zero-cost-basis dumps (excluded by default — see zero_cost_share)."}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"wallets":{"type":"array","items":{"type":"object","properties":{"wallet":{"type":"string","description":"Trader EOA (lowercase 0x)."},"classification":{"type":"string","enum":["bot","smart_money","trader"]},"is_known_kol":{"type":"boolean"},"trades":{"type":"integer"},"tokens":{"type":"integer"},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"net_eth":{"type":"number","description":"Realized net flow (sell − buy)."},"win_rate":{"type":"number","nullable":true},"memecoin_share":{"type":"number","nullable":true,"description":"Share of trades in launchpad memecoins (vs tokenized stocks/stables)."},"avg_trade_mc_usd":{"type":"number","nullable":true},"last_trade_at":{"type":"string","format":"date-time","nullable":true},"zero_cost_share":{"type":"number","nullable":true,"description":"Share of gross ETH extracted from tokens with no recorded buy (deployer/insider dumps). Null = never sold. ≥0.5 wallets are excluded unless include_zero_cost_dumps=true."}}}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"attribution":{"type":"object","description":"Interim attribution disclosure: mv_rhc_alpha_wallets is built from attributed trades only (`trader_eoa IS NOT NULL`), and trader_eoa was only written reliably from 2026-07-18 — pre-floor history is not reflected in win_rate/net_eth/classification. Removed once the trader_eoa backfill lands.","properties":{"attribution_complete_from":{"type":"string","format":"date-time"},"note":{"type":"string"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet/{address}":{"get":{"tags":["Robinhood Chain"],"summary":"Wallet profile on Robinhood Chain (PRO+)","description":"Any Robinhood Chain wallet's 90-day trading profile: FIFO cost-basis PnL, per-token breakdown, recent trades, and a reputation block (tracked KOL, known deployer + tier, alpha-ranked, dump-cluster membership, early-buyer count).\n\n**Denomination is ETH**, matching the rest of the RHC tree (`eth_amount`, `net_eth`) — not USD. A USD cost basis would silently mix in the tokenized-stock quote assets some flap bonding curves price in.\n\n**Sourced from `trader_eoa` — the effective trading account, never the swap-log `trader`**, which is the router address on any aggregated swap.\n\n`stats.analyzed_trades + stats.unattributed_trades + stats.unsized_trades === stats.total_trades` always holds — no trade silently vanishes from the accounting. The two exclusions mean different things: **`unattributed_trades`** is swaps with no token side at all (token↔token exotic pools, unclassified pools) and is routine, often large for MM bots; **`unsized_trades`** is a token-side trade whose quantity could not be reconstructed from `rhc_trades`' raw uint256 leg amounts, which is the actual quality signal and should be ~0.\n\n**Attribution floor:** analysis starts at `notes.attribution_complete_from` (2026-07-18) rather than the full 90 days — `trader_eoa` was written for under half of earlier trades, and a partial view produces positions the wallet no longer holds.\n\nA wallet exceeding the 50,000-trade analysis cap returns `stats.partial: true`. Heavy wallets that blow the query budget return the reputation block with `stats_unavailable: true` rather than a 500. Responses are cached 60s per address. Tier: **PRO+**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"EVM wallet address (0x, 40 hex). Case-insensitive; echoed lowercase."}],"responses":{"200":{"description":"OK. `stats` is null only when the wallet is known solely through a reputation table (e.g. a deployer that has never traded).","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"address":{"type":"string"},"stats":{"type":"object","nullable":true,"properties":{"first_seen":{"type":"string","format":"date-time","nullable":true},"last_seen":{"type":"string","format":"date-time","nullable":true},"total_trades":{"type":"integer"},"analyzed_trades":{"type":"integer","description":"Trades that entered the FIFO computation."},"unattributed_trades":{"type":"integer","description":"Swaps with no token side or direction — token↔token exotic pools and pools our resolver has not classified. Routine, and a large share for MM bots (47% on one 512k-trade fleet wallet). NOT a data-quality signal."},"unsized_trades":{"type":"integer","description":"Token-side trades whose QUANTITY could not be reconstructed — excluded from PnL entirely. This IS the quality signal and should be ~0 (measured 0 across a 512k-trade wallet)."},"buys":{"type":"integer"},"sells":{"type":"integer"},"bought_eth":{"type":"number"},"sold_eth":{"type":"number"},"realized_pnl_eth":{"type":"number"},"unrealized_pnl_eth":{"type":"number","description":"Mark-to-market on FIFO-open positions using rhc_token_prices.last_price_native. Unpriced positions contribute 0. **FIFO figure, not a holding**: it includes lots transferred out since the buy. For PnL on what is actually held use `holdings.unrealized_known_eth`."},"total_pnl_eth":{"type":"number","description":"realized_pnl_eth + unrealized_pnl_eth (FIFO)."},"held_value_eth":{"type":"number","description":"FIFO-unmatched DEX buys x current price. **Not an on-chain balance**: a token sent out by transfer still counts here. The proven current value is `holdings.verified_value_eth`."},"unique_tokens":{"type":"integer"},"open_positions":{"type":"integer","description":"FIFO-open positions (unmatched DEX buys). How many are actually still held is in `holdings`."},"window_days":{"type":"integer","example":90},"partial":{"type":"boolean","description":"Present only when the 50,000-trade cap was hit."}}},"flags":{"type":"object","properties":{"is_kol":{"type":"boolean"},"kol_name":{"type":"string","nullable":true},"is_deployer":{"type":"boolean"},"deployer_tier":{"type":"string","nullable":true,"enum":["elite","good","neutral","spammer"]},"deployer_tokens":{"type":"integer","nullable":true},"deployer_runner_rate":{"type":"number","nullable":true},"is_alpha_tracked":{"type":"boolean"},"alpha_win_rate":{"type":"number","nullable":true},"alpha_net_eth":{"type":"number","nullable":true},"alpha_tokens_traded":{"type":"integer","nullable":true},"likely_bot":{"type":"boolean","nullable":true,"description":"Atomic-arb / MM signature from mv_rhc_alpha_wallets."},"is_dumper":{"type":"boolean","description":"≥5 dump cohorts AND 0 runner cohorts, rolling 42d. Rebuilt daily — up to ~48h stale. Absence means NOT OBSERVED, not verified clean."},"dump_cluster":{"type":"object","nullable":true},"early_buyer_tokens":{"type":"integer","description":"Tokens where this wallet was in the first-20 buyer cohort."}}},"top_tokens":{"type":"array","maxItems":10,"items":{"type":"object","properties":{"still_holding":{"type":"boolean","description":"FIFO meaning: an unmatched DEX buy exists. NOT an on-chain balance; see holding_status."},"holding_status":{"type":"string","nullable":true,"enum":["HELD","PARTIALLY_REDUCED","TRANSFERRED_OR_DISPOSED","EXTERNAL_INFLOW","BALANCE_UNVERIFIED"],"description":"On-chain status of a FIFO-open token; null when the token is FIFO-closed."}}}},"holdings":{"type":"object","nullable":true,"description":"On-chain verification of every FIFO-open position: balanceOf + decimals read from our own Robinhood Chain node in one Multicall3 batch (cached 30 s). `complete: false` means at least one position is BALANCE_UNVERIFIED (node unreachable, call reverted, non-standard token, decimals mismatch) and contributes NO value.","properties":{"balance_source":{"type":"string","enum":["rhc_node_multicall3"]},"checked_at":{"type":"string","format":"date-time"},"complete":{"type":"boolean"},"fifo_open_positions":{"type":"integer"},"held":{"type":"integer"},"partially_reduced":{"type":"integer"},"transferred_or_disposed":{"type":"integer"},"external_inflow":{"type":"integer"},"unverified":{"type":"integer"},"verified_value_eth":{"type":"number","description":"PROVEN balances x current price: the current value of the tokens this wallet bought on a DEX and still holds. Unverified and unpriced positions contribute nothing."},"unpriced_held":{"type":"integer"},"cost_basis_held_eth":{"type":"number","description":"Cost basis of the FIFO-known portion still in the wallet."},"unrealized_known_eth":{"type":"number","description":"Unrealized PnL on the portion whose cost basis is known AND still held. External inflows never add trading profit."},"cost_basis_not_held_eth":{"type":"number","description":"Cost basis of FIFO lots no longer in the wallet (transferred out or disposed outside indexed swaps). Outcome unknown: neither realized nor unrealized."}}},"recent_trades":{"type":"array","maxItems":20,"items":{"type":"object"}},"derived":{"type":"object","nullable":true,"properties":{"win_rate":{"type":"number","nullable":true},"wins":{"type":"integer"},"losses":{"type":"integer"},"avg_trade_size_eth":{"type":"number","nullable":true},"is_active":{"type":"boolean"}}},"stats_unavailable":{"type":"boolean","description":"Present when the trade aggregation was skipped on a timeout. Absence of stats is then UNPROVEN — do not read it as an inactive wallet."},"cache_hit":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No recorded Robinhood Chain activity for this address as a trading account (`trader_eoa`). The body carries `address_type` (`eoa` / `eoa_7702` / `contract` / `unknown`, from eth_getCode); for a contract also `contract_trader_swaps_last_hour` (swaps where it is the swap-log trader; null = not measured) and a `note`. A contract cannot sign transactions, so its own swaps are never attributed to a wallet here; identities are not merged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet/{address}/funding":{"get":{"tags":["Robinhood Chain"],"summary":"Robinhood Chain shared-funder evidence for a tracked wallet (PRO+)","description":"Robinhood Chain (eip155:4663). Addresses that sent a qualifying native ETH or ERC-20 transfer to this wallet AND to other tracked wallets (KOL EVM wallets, elite/good deployers), with the supporting transactions. Evidence of a funding connection — not proof of common ownership. Internal (contract → wallet) ETH transfers are not observed. Forward-looking coverage from monitoring start; no historical backfill.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"},"description":"EVM address (0x…, case-insensitive)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":20,"default":10},"description":"Shared funders per page."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":100,"default":0}}],"responses":{"200":{"description":"OK. `status`: ok | partial_coverage | not_tracked | collection_disabled | collection_stale | not_started. `collection_stale` = the collector has not reported within the staleness window, so evidence after `coverage.heartbeat_at` may be missing. An empty `shared_funders` with status ok means no shared funder was OBSERVED within coverage — never that wallets are independent.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["solana","robinhood"]},"chain_id":{"type":"string"},"native_asset":{"type":"string"},"address":{"type":"string"},"status":{"type":"string","enum":["ok","partial_coverage","not_tracked","collection_disabled","collection_stale","not_started"]},"summary":{"type":"string"},"shared_funders":{"type":"array","items":{"type":"object","properties":{"funder":{"type":"string"},"funder_explorer_url":{"type":"string"},"funder_label":{"type":"object","nullable":true,"properties":{"label":{"type":"string"},"category":{"type":"string"},"verified":{"type":"boolean"}}},"service_funder":{"type":"boolean","description":"Known exchange/service: a common funding source, not a connection signal"},"to_this_wallet":{"type":"array","items":{"type":"object","properties":{"asset":{"type":"string","description":"'native' or the token contract"},"symbol":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"amount_raw":{"type":"string","description":"Exact integer (raw units)"},"amount":{"type":"string","nullable":true,"description":"Exact decimal string when decimals are known"},"transfer_count":{"type":"integer"},"first_seen":{"type":"string","format":"date-time","description":"Chain block time of the earliest transfer when resolved; otherwise the collector's observation time (Solana block times are resolved asynchronously and can stay unknown after bounded retries). Not a guaranteed on-chain timestamp."},"last_seen":{"type":"string","format":"date-time","description":"Same basis as first_seen, for the latest transfer."},"transactions":{"type":"array","items":{"type":"object","properties":{"tx":{"type":"string"},"explorer_url":{"type":"string"}}}}}}},"connected_wallets":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"explorer_url":{"type":"string"},"tracked_as":{"type":"array","items":{"type":"string"}},"transfers":{"type":"array","items":{"type":"object","properties":{"asset":{"type":"string","description":"'native' or the token contract"},"symbol":{"type":"string","nullable":true},"decimals":{"type":"integer","nullable":true},"amount_raw":{"type":"string","description":"Exact integer (raw units)"},"amount":{"type":"string","nullable":true,"description":"Exact decimal string when decimals are known"},"transfer_count":{"type":"integer"},"first_seen":{"type":"string","format":"date-time","description":"Chain block time of the earliest transfer when resolved; otherwise the collector's observation time (Solana block times are resolved asynchronously and can stay unknown after bounded retries). Not a guaranteed on-chain timestamp."},"last_seen":{"type":"string","format":"date-time","description":"Same basis as first_seen, for the latest transfer."},"transactions":{"type":"array","items":{"type":"object","properties":{"tx":{"type":"string"},"explorer_url":{"type":"string"}}}}}}}}}}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"total":{"type":"integer"},"has_more":{"type":"boolean"}}},"coverage":{"type":"object","additionalProperties":true,"description":"collection_enabled, mode (off|shadow|on), heartbeat_at, collector_current, monitoring_started_at, last_committed_position, last_committed_at, tracked_intervals, known_gaps, supported/unsupported transfer types, recovery, history note"},"disclaimer":{"type":"string"},"direct_funding":{"type":"object","additionalProperties":true,"description":"Optional, additive: where THIS wallet was funded from (the same block as `funding` on the wallet/deployer profiles). Absent when the direct read fails — the shared-funder answer above still stands. `observed: false` carries `coverage`, `coverage_explanation`, `observation_started_at` and `note` (no funding observed within coverage is not evidence the wallet was never funded). `observed: true` adds the coverage fields, `asset_scope`, `native_funding`, `token_funding`, `sources[]` and `source_count` (PRO); cross-wallet `relationships` counts are ULTRA+ and removed below ULTRA.","properties":{"observed":{"type":"boolean"},"coverage":{"type":"string","description":"Coverage level of the funding evidence, e.g. forward_only."},"coverage_explanation":{"type":"string"},"observation_started_at":{"type":"string","format":"date-time","nullable":true},"note":{"type":"string"}}},"wallet_coverage":{"type":"object","description":"What the funding collector can see for THIS address. not_tracked: no evidence is collected for it at all; internal_transfers_not_visible (RHC): tracked, but the address is a contract / EIP-7702 smart account whose native funding typically arrives as internal value the node cannot show.","properties":{"state":{"type":"string","enum":["tracked","not_tracked","internal_transfers_not_visible"]},"currently_tracked":{"type":"boolean"},"ever_tracked":{"type":"boolean"},"address_kind":{"type":"string","nullable":true,"enum":["eoa","eoa_7702","contract","unknown"]},"limitations":{"type":"array","items":{"type":"string","enum":["spl_token_transfers_not_visible","internal_eth_transfers_not_visible","erc20_only_eth_weth_usdg_classified_as_funding"]}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid address or query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Tier below PRO.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"`code: feature_disabled` (feature switched off by the operator; on in production since 2026-09-20) or `code: funding_data_unavailable` (data error — NOT an empty result; retry).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet/{address}/pnl":{"get":{"tags":["Robinhood Chain"],"summary":"FIFO cost-basis PnL on Robinhood Chain (PRO+)","description":"Full FIFO cost-basis PnL for one RHC wallet over 90 days: realized and unrealized split, a daily realized curve, every closed position with ROI and token-weighted hold time, and every open position marked to the current price.\n\nThis runs the **same FIFO implementation as the Solana `/wallet/{address}/pnl`** — the algorithm is imported, not reimplemented — with ETH substituted for SOL. Field names keep the Solana convention with the denomination swapped (`realized_eth`, `pnl_eth`), so porting a Solana integration is a mechanical rename.\n\nIt also shares its loader with `/rhc/wallet/{address}`, so the two endpoints cannot report different PnL for the same wallet.\n\n**Cost basis is only observable inside the window** (`notes.cost_basis_observable_from`). Tokens sold that were bought before it contribute no realized PnL rather than a fabricated one — figures read low, never invented.\n\n**Attribution floor (`notes.attribution_complete_from`, 2026-07-18):** the window is clamped forward to this date because `trader_eoa` — the column every wallet endpoint filters on — was written for under half of earlier trades. The gap is ASYMMETRIC per wallet: a token's buys can carry it while its sell does not, which leaves FIFO holding a position that was actually closed. Analysing only the attributed era is narrower but honest. `notes.window_clamped` flags it. Cached 120s per address. Tier: **PRO+**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"address":{"type":"string"},"window_days":{"type":"integer","example":90},"summary":{"type":"object","properties":{"realized_eth":{"type":"number"},"unrealized_eth":{"type":"number"},"total_pnl_eth":{"type":"number"},"total_bought_eth":{"type":"number"},"total_sold_eth":{"type":"number"},"wins":{"type":"integer"},"losses":{"type":"integer"},"win_rate":{"type":"number","nullable":true,"description":"Fraction in [0,1] across CLOSED positions."},"profit_factor":{"type":"number","nullable":true,"description":"Gross wins / gross losses. null when there are no losses (undefined math), 0 when there are no wins."},"avg_hold_minutes":{"type":"integer","nullable":true},"median_hold_minutes":{"type":"integer","nullable":true},"max_drawdown_eth":{"type":"number","description":"Magnitude — always ≥ 0."},"open_positions_count":{"type":"integer"},"closed_positions_count":{"type":"integer"},"total_tokens_traded":{"type":"integer"},"best_realized":{"type":"object","nullable":true},"worst_realized":{"type":"object","nullable":true}}},"pnl_curve":{"type":"array","description":"Sparse daily UTC buckets of REALIZED PnL. `cumulative_pnl` is the running sum of `day_pnl`; days with no realized events are omitted.","items":{"type":"object","properties":{"date":{"type":"string","example":"2026-07-24"},"day_pnl":{"type":"number"},"cumulative_pnl":{"type":"number"},"trades":{"type":"integer"}}}},"closed_positions":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"buy_count":{"type":"integer"},"sell_count":{"type":"integer"},"bought_eth":{"type":"number"},"sold_eth":{"type":"number"},"pnl_eth":{"type":"number"},"roi_pct":{"type":"number","nullable":true},"hold_minutes":{"type":"integer","nullable":true,"description":"Token-weighted across matched FIFO lots — correct for re-entered tokens."},"result":{"type":"string","enum":["win","loss","breakeven"]},"first_trade":{"type":"string","format":"date-time","nullable":true},"last_trade":{"type":"string","format":"date-time","nullable":true}}}},"open_positions":{"type":"array","description":"Unsold FIFO tail marked to the current price. Each entry carries `liquidity_basis` (`v4_virtual_ceiling` | `measured`) — uniswap-v4 liquidity_usd is a virtual-reserve ceiling, not measured per-pool TVL.","items":{"type":"object"}},"notes":{"type":"object","properties":{"denomination":{"type":"string","enum":["ETH"]},"cost_basis_observable_from":{"type":"string","format":"date-time"},"data_through":{"type":"string","format":"date-time","nullable":true,"description":"Newest trade this answer was computed from — the response's vintage. Equals `stats.last_seen` on /rhc/wallet/{address} when both ran over the same data. Use this, not a trade count, to tell whether two responses are comparable: the count saturates at the analysis cap."},"trades_seen":{"type":"integer"},"trades_analyzed":{"type":"integer"},"trades_unattributed":{"type":"integer","description":"No token side / direction (exotic or unresolved pool). Routine."},"trades_unsized":{"type":"integer","description":"Token-side trades with no reconstructable quantity. Should be ~0."},"partial":{"type":"boolean"},"partial_reason":{"type":"string"}}},"cache_hit":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Wallet has no Robinhood Chain trades in the data window.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Trades exist but none carry a reconstructable token amount, so no PnL can be computed. Returning zeroes would assert the wallet is flat, which is a different claim.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet/{address}/positions":{"get":{"tags":["Robinhood Chain"],"summary":"Open positions on Robinhood Chain (PRO+)","description":"Only what the wallet is still holding, marked to the current price — the same FIFO pass as `/pnl` without the curve and closed-position payload, for clients polling \"what is this wallet in right now\".\n\n**\"Open\" means FIFO-unmatched buys inside the window: a TRADING position, NOT an on-chain balance.** This cuts both ways and the second direction is the dangerous one: a token acquired by transfer or bridge does not appear, and a token **disposed of by plain ERC-20 transfer rather than sold on a DEX still appears as held**, because only swaps are indexed. Since 2026-10-02 every position is **checked against the chain**: `current_onchain_balance` (balanceOf from our own node, Multicall3, cached 30 s) sits next to `fifo_unmatched_amount`, and `holding_status` says which applies: `HELD` (balance within 0.5 % of FIFO), `PARTIALLY_REDUCED` (0 < balance < FIFO), `TRANSFERRED_OR_DISPOSED` (balance 0), `EXTERNAL_INFLOW` (balance > FIFO; the excess has no cost basis), `BALANCE_UNVERIFIED` (read failed, non-standard token, or our decimals differ from on-chain decimals: fail closed, no value). The pre-existing fields (`token_amount`, `current_value_eth`, `unrealized_eth`, the `summary` totals) keep their FIFO meaning; `summary.holdings` and the `current_holding_value_eth` / `unrealized_known_eth` fields are the proven-holdings view.\n\n**Attribution floor:** analysis starts at `notes.attribution_complete_from` (2026-07-18), not the full 90 days — `trader_eoa` was written for under half of earlier trades, and a partial view yields positions the wallet no longer holds. `notes.window_clamped` flags when this is what bounds the result. `total_unrealized_eth` is computed against the cost basis of the PRICED subset only — `unpriced_positions` counts what is missing from the totals, so a zero is never mistaken for worthless. Tier: **PRO+**.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"responses":{"200":{"description":"OK. Sorted by current value, then cost basis.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"address":{"type":"string"},"window_days":{"type":"integer"},"summary":{"type":"object","properties":{"open_positions":{"type":"integer"},"total_cost_basis_eth":{"type":"number"},"total_current_value_eth":{"type":"number","description":"Priced positions only."},"total_unrealized_eth":{"type":"number","description":"Against the cost basis of the priced subset only."},"unpriced_positions":{"type":"integer"},"holdings":{"type":"object","nullable":true,"description":"On-chain verification of every FIFO-open position: balanceOf + decimals read from our own Robinhood Chain node in one Multicall3 batch (cached 30 s). `complete: false` means at least one position is BALANCE_UNVERIFIED (node unreachable, call reverted, non-standard token, decimals mismatch) and contributes NO value.","properties":{"balance_source":{"type":"string","enum":["rhc_node_multicall3"]},"checked_at":{"type":"string","format":"date-time"},"complete":{"type":"boolean"},"fifo_open_positions":{"type":"integer"},"held":{"type":"integer"},"partially_reduced":{"type":"integer"},"transferred_or_disposed":{"type":"integer"},"external_inflow":{"type":"integer"},"unverified":{"type":"integer"},"verified_value_eth":{"type":"number","description":"PROVEN balances x current price: the current value of the tokens this wallet bought on a DEX and still holds. Unverified and unpriced positions contribute nothing."},"unpriced_held":{"type":"integer"},"cost_basis_held_eth":{"type":"number","description":"Cost basis of the FIFO-known portion still in the wallet."},"unrealized_known_eth":{"type":"number","description":"Unrealized PnL on the portion whose cost basis is known AND still held. External inflows never add trading profit."},"cost_basis_not_held_eth":{"type":"number","description":"Cost basis of FIFO lots no longer in the wallet (transferred out or disposed outside indexed swaps). Outcome unknown: neither realized nor unrealized."}}}}},"positions":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"is_graduated":{"type":"boolean","nullable":true},"token_amount":{"type":"number"},"cost_basis_eth":{"type":"number"},"avg_entry_price_eth":{"type":"number"},"current_price_eth":{"type":"number","nullable":true},"current_value_eth":{"type":"number","nullable":true},"unrealized_eth":{"type":"number","nullable":true},"unrealized_pct":{"type":"number","nullable":true},"current_mc_usd":{"type":"number","nullable":true},"liquidity_usd":{"type":"number","nullable":true},"liquidity_basis":{"type":"string","enum":["v4_virtual_ceiling","measured"],"description":"How liquidity_usd was derived. uniswap-v4 figures are virtual reserves clamped to the PoolManager's total holdings — a provable ceiling, not measured per-pool TVL."},"buys_in_position":{"type":"integer"},"realized_so_far_eth":{"type":"number","description":"Partial exits already taken on this token."},"first_buy_at":{"type":"string","format":"date-time","nullable":true},"last_buy_at":{"type":"string","format":"date-time","nullable":true},"fifo_unmatched_amount":{"type":"number","nullable":true,"description":"DEX buys not matched by a DEX sell (same as token_amount). A trading position, not a balance."},"current_onchain_balance":{"type":"number","nullable":true,"description":"balanceOf(wallet) / 10^decimals from our node. null = not proven (BALANCE_UNVERIFIED)."},"holding_status":{"type":"string","enum":["HELD","PARTIALLY_REDUCED","TRANSFERRED_OR_DISPOSED","EXTERNAL_INFLOW","BALANCE_UNVERIFIED"]},"holding_unverified_reason":{"type":"string","nullable":true,"enum":["rpc_unavailable","call_failed","decimals_failed","over_cap","decimals_mismatch","decimals_unknown"]},"held_known_amount":{"type":"number","nullable":true,"description":"min(balance, FIFO): the held part whose cost basis is known."},"external_inflow_amount":{"type":"number","nullable":true},"current_holding_value_eth":{"type":"number","nullable":true,"description":"current_onchain_balance x current price. 0 when transferred out; null when unverified or unpriced."},"cost_basis_held_eth":{"type":"number","nullable":true},"unrealized_known_eth":{"type":"number","nullable":true,"description":"Unrealized on the known-cost, still-held portion only."},"cost_basis_not_held_eth":{"type":"number","nullable":true,"description":"Cost basis of the FIFO portion no longer in the wallet. Outcome unknown."}}}},"notes":{"type":"object"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Wallet has no Robinhood Chain trades in the data window.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet/{address}/trades":{"get":{"tags":["Robinhood Chain"],"summary":"One wallet's Robinhood Chain trade tape (PRO+)","description":"A single wallet's swaps, newest first, cursor-paginated (opaque `next_before` keyset). Distinct from `/rhc/trades?token=` — that filters the global tape by TOKEN, this filters by WALLET, which is a different index path (`idx_rhc_trades_trader_eoa_bt`).\n\n`token_amount` is reconstructed from raw uint256 leg amounts and is **null when it cannot be** — never zero, and never a guess. Tier: **PRO+**.\n\n**Where the rows come from** (*added 2026-08-29*): closed months older than the newest three move from Postgres to a Parquet archive; pages are split at `history.postgres_from` (ISO) — rows at/after it from Postgres, older rows from the archive reader, same ordering and `before` cursor. `history.archive_used`, `archive_months`, `archive_available` (`null` = not configured) and `truncated` (older history requested but the archive did not answer — retry rather than treating `has_more:false` as the end) mirror `/tokens/{mint}/trades`. Header `X-Read-Source`: `core`, `core+archive` or `archive`.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"before","in":"query","schema":{"type":"string"},"description":"Opaque cursor from next_before; a bare ISO block_time is also accepted for backward compatibility (loses intra-second position)."},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"action","in":"query","schema":{"type":"string","enum":["buy","sell"]}},{"name":"token","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Restrict to one token."}],"responses":{"200":{"description":"OK. `next_before` is the opaque pagination cursor — pass it back as `before`; `has_more` says whether another page exists.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"address":{"type":"string"},"trades":{"type":"array","items":{"type":"object","properties":{"token_address":{"type":"string","nullable":true},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"launchpad":{"type":"string","nullable":true},"action":{"type":"string","enum":["buy","sell"],"nullable":true},"eth_amount":{"type":"number","nullable":true},"token_amount":{"type":"number","nullable":true,"description":"null when no decimals row and no execution price exist for the token."},"price_native":{"type":"number","nullable":true},"price_usd":{"type":"number","nullable":true},"mc_usd_at_trade":{"type":"number","nullable":true},"dex":{"type":"string","nullable":true},"pool":{"type":"string","nullable":true},"router":{"type":"string","nullable":true},"method_selector":{"type":"string","nullable":true},"tx_hash":{"type":"string"},"log_index":{"type":"integer"},"block_number":{"type":"integer"},"block_time":{"type":"string","format":"date-time"}}}},"count":{"type":"integer"},"has_more":{"type":"boolean","description":"True when another page exists beyond this one."},"next_before":{"type":"string","nullable":true,"description":"Opaque (block_time, id) keyset cursor for the next page; null when has_more is false."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address or query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet-tracker/watchlist":{"get":{"tags":["Robinhood Chain"],"summary":"List tracked Robinhood Chain wallets (PRO+)","description":"Your Robinhood Chain watchlist. **Quotas are per chain** — PRO 50 / ULTRA 250 / BUSINESS 1,000 RHC wallets, independent of your Solana watchlist, so adopting RHC never shrinks an existing Solana list. Tier: **PRO+**.","responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"wallets":{"type":"array","items":{"type":"object","properties":{"wallet_address":{"type":"string"},"label":{"type":"string","nullable":true},"added_at":{"type":"string","format":"date-time"}}}},"count":{"type":"integer"},"limit":{"type":"integer"},"remaining":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"post":{"tags":["Robinhood Chain"],"summary":"Add a Robinhood Chain wallet to your watchlist (PRO+)","description":"Addresses are stored lowercase so they match `rhc_trades.trader_eoa`; a checksummed `0xAbC…` would otherwise join to nothing and look like a permanently silent wallet. Tier: **PRO+**.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wallet_address"],"properties":{"wallet_address":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"label":{"type":"string","maxLength":64}}}}}},"responses":{"201":{"description":"Added.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address or JSON body.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Wallet already in watchlist, or the per-tier RHC limit is reached.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet-tracker/watchlist/{address}":{"delete":{"tags":["Robinhood Chain"],"summary":"Remove a Robinhood Chain wallet from your watchlist (PRO+)","description":"Remove a wallet from your Robinhood Chain tracker watchlist, addressed by the `address` path param (0x + 40 hex; matched and returned lowercase). The watchlist quota is per chain and separate from Solana: PRO 50, ULTRA 250, BUSINESS 1,000 wallets. 400 for an invalid EVM address, 404 if the wallet isn't on your watchlist.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"responses":{"200":{"description":"Removed.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"removed":{"type":"string","description":"The lowercased EVM address that was removed."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not in watchlist.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"patch":{"tags":["Robinhood Chain"],"summary":"Relabel a tracked Robinhood Chain wallet (PRO+)","description":"Set or clear the label on a wallet in your Robinhood Chain tracker watchlist, addressed by the `address` path param (0x + 40 hex). Send `{ label }` in the JSON body: 1-64 characters, or null to clear it. 400 for an invalid address or body, 404 if the wallet isn't on your watchlist.","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["label"],"properties":{"label":{"type":"string","maxLength":64,"nullable":true}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"wallet":{"type":"object","properties":{"wallet_address":{"type":"string"},"label":{"type":"string","nullable":true},"added_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid EVM address or body.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not in watchlist.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/copytrade/subscriptions":{"get":{"tags":["Robinhood Chain"],"summary":"List RHC copy-trade rules (PRO+)","description":"Your Robinhood Chain copy-trade rules. Quotas are per chain — PRO 3 rules × 5 wallets / ULTRA 20 × 50 / BUSINESS 100 × 250, independent of your Solana copy-trade rules. Tier: **PRO+**.","responses":{"200":{"description":"OK — { chain, subscriptions[] }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscriptions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Numeric rule id (used in /rhc/copytrade/subscriptions/{id})"},"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"},"description":"Lowercase 0x EVM wallets being mirrored (1-250). Any valid address once source_admission is any_wallet; under the legacy kol_only engine only tracked KOL wallets (kol_evm_wallets) can fire — see source_admission and operational_state."},"min_trade_eth":{"type":"number"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"source_wallets_tracked":{"$ref":"#/components/schemas/RhcCopytradeTrackedWallets"},"source_wallets_untracked":{"$ref":"#/components/schemas/RhcCopytradeUntrackedWallets"},"operational_state":{"$ref":"#/components/schemas/RhcCopytradeOperationalState"},"source_admission":{"$ref":"#/components/schemas/RhcCopytradeSourceAdmission"},"monitoring_reasons":{"$ref":"#/components/schemas/RhcCopytradeMonitoringReasons"},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"post":{"tags":["Robinhood Chain"],"summary":"Create an RHC copy-trade rule (PRO+)","description":"Mirror chosen Robinhood Chain wallets to a webhook or the `rhc:copytrade:signals` WebSocket channel. Any valid 0x source wallet fires, KOL or not (`source_admission: any_wallet`, production since 2026-10-04; KOL membership is enrichment only and copy-trade sources do not use Wallet Tracker quota); `operational_state` says whether the rule can fire right now. A source trade must be at most 5 s old by chain time. Addresses are **lowercased on write** — the evaluator matches the lowercased event address, so a checksummed rule would never fire. Amounts are ETH. Idempotency is `(subscription_id, tx_hash)`, so a replayed event can never double-fire.\n\n**No `min_mc_usd`/`max_mc_usd`**: the RHC trade event carries no market cap, so an MC band could only be a per-event database lookup on a ~3.3M trades/day chain or a filter that silently never matches. Returns `webhook_secret` once, never again.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source_wallets","sizing_amount"],"properties":{"name":{"type":"string","maxLength":64},"source_wallets":{"type":"array","minItems":1,"maxItems":250,"items":{"type":"string","description":"Lowercase 0x EVM address"}},"min_trade_eth":{"type":"number","minimum":0,"default":0},"only_action":{"type":"string","enum":["buy","sell","both"],"default":"buy"},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"],"default":"fixed"},"sizing_amount":{"type":"number","exclusiveMinimum":0,"description":"ETH when sizing_mode=fixed, else a multiplier of the source trade"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"],"default":"webhook"},"webhook_url":{"type":"string","format":"uri","description":"HTTPS only. Required unless delivery_mode is websocket."}}}}}},"responses":{"200":{"description":"Created — includes one-time webhook_secret.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscription":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"}},"min_trade_eth":{"type":"number"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"source_wallets_tracked":{"$ref":"#/components/schemas/RhcCopytradeTrackedWallets"},"source_wallets_untracked":{"$ref":"#/components/schemas/RhcCopytradeUntrackedWallets"},"operational_state":{"$ref":"#/components/schemas/RhcCopytradeOperationalState"},"source_admission":{"$ref":"#/components/schemas/RhcCopytradeSourceAdmission"},"monitoring_reasons":{"$ref":"#/components/schemas/RhcCopytradeMonitoringReasons"},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"},"webhook_secret":{"type":"string","nullable":true,"description":"One-time HMAC secret — only present when webhook delivery is configured."},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body, EVM address, webhook URL, or wallet count above the tier cap.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"409":{"description":"RHC copy-trade rule limit reached for the tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/copytrade/subscriptions/{id}":{"get":{"tags":["Robinhood Chain"],"summary":"Get one RHC copy-trade rule (PRO+)","description":"Fetch one Robinhood Chain copy-trade rule you own, addressed by the numeric `id` path param. Returns its source wallets, minimum trade size in ETH, buy / sell filter, sizing mode and amount, delivery config (webhook, websocket or both) and `is_active` state. 400 for a non-numeric id, 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscription":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"}},"min_trade_eth":{"type":"number"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"source_wallets_tracked":{"$ref":"#/components/schemas/RhcCopytradeTrackedWallets"},"source_wallets_untracked":{"$ref":"#/components/schemas/RhcCopytradeUntrackedWallets"},"operational_state":{"$ref":"#/components/schemas/RhcCopytradeOperationalState"},"source_admission":{"$ref":"#/components/schemas/RhcCopytradeSourceAdmission"},"monitoring_reasons":{"$ref":"#/components/schemas/RhcCopytradeMonitoringReasons"},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"patch":{"tags":["Robinhood Chain"],"summary":"Update an RHC copy-trade rule (PRO+)","description":"Partial update. The wallet cap is re-checked, so a PRO rule cannot be PATCHed past its tier limit.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"}},"min_trade_eth":{"type":"number"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscription":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"source_wallets":{"type":"array","items":{"type":"string"}},"min_trade_eth":{"type":"number"},"only_action":{"type":"string","enum":["buy","sell","both"]},"sizing_mode":{"type":"string","enum":["fixed","proportional","percent_source"]},"sizing_amount":{"type":"number"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"source_wallets_tracked":{"$ref":"#/components/schemas/RhcCopytradeTrackedWallets"},"source_wallets_untracked":{"$ref":"#/components/schemas/RhcCopytradeUntrackedWallets"},"operational_state":{"$ref":"#/components/schemas/RhcCopytradeOperationalState"},"source_admission":{"$ref":"#/components/schemas/RhcCopytradeSourceAdmission"},"monitoring_reasons":{"$ref":"#/components/schemas/RhcCopytradeMonitoringReasons"},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}},"warnings":{"$ref":"#/components/schemas/RhcCopytradeRuleWarnings"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body or id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"delete":{"tags":["Robinhood Chain"],"summary":"Delete an RHC copy-trade rule (PRO+)","description":"Permanently delete a Robinhood Chain copy-trade rule you own, addressed by the numeric `id` path param. Its stored signal history is deleted with it and no further `rhc:copytrade:signal` events fire for it. To stop it temporarily instead, PATCH `is_active: false`. 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted — { chain, deleted: true }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"deleted":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/copytrade/signals":{"get":{"tags":["Robinhood Chain"],"summary":"RHC copy-trade fire history (PRO+)","description":"Catch-up path for a consumer that missed a webhook or was disconnected from the WebSocket channel. Retained 7 days.","parameters":[{"name":"subscription_id","in":"query","schema":{"type":"integer"},"description":"Scope to one of your rules. 404 if you do not own it."},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":50}}],"responses":{"200":{"description":"OK — { chain, signals[], count }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"signals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"subscription_id":{"type":"integer"},"fired_at":{"type":"string","format":"date-time"},"source_wallet":{"type":"string","description":"Lowercase 0x wallet whose trade matched the rule."},"action":{"type":"string","enum":["buy","sell"]},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"token_name":{"type":"string","nullable":true},"source_eth_amount":{"type":"number","description":"Size of the source wallet's trade, in ETH."},"suggested_eth_amount":{"type":"number","nullable":true,"description":"Sized amount per the rule's sizing_mode/sizing_amount."},"price_usd":{"type":"number","nullable":true},"dex":{"type":"string","nullable":true},"tx_hash":{"type":"string"},"delivered":{"type":"boolean","description":"True once the signal was actually written to one of your live sockets or accepted by your webhook. A frame that was only queued for a socket still running a replay and then dropped (queue overflow or a 4008 close) is NOT delivered and records delivery_error 'ws_replay_dropped'."},"delivered_at":{"type":"string","format":"date-time","nullable":true}}}},"count":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid limit, since, or subscription_id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"subscription_id not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/price-alerts":{"get":{"tags":["Robinhood Chain"],"summary":"List RHC price alerts (PRO+)","description":"List every Robinhood Chain market-cap price alert you own, active and paused, newest first. Each alert carries its token, the baseline market cap captured at creation, the `drop_pct` / `recovery_pct` thresholds, its current `status` (watching, then dipped, then recovered), the dip low, delivery config and expiry. Alerts are evaluated as trades land (event-driven off the chain trade feed, a few seconds of latency), with periodic table polls as a safety net. The quota counts active alerts only and is separate from Solana: PRO 5, ULTRA 50, BUSINESS 150.","responses":{"200":{"description":"OK — { chain, alerts[] }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"alerts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"baseline_mc_usd":{"type":"number","description":"Market cap captured at rule creation — the baseline drop_pct is measured against."},"drop_pct":{"type":"number"},"recovery_pct":{"type":"number","nullable":true},"status":{"type":"string","enum":["watching","dipped","recovered","expired"],"description":"`expired` = the rule outlived its window and was deactivated (terminal, like `recovered`)."},"dip_low_mc_usd":{"type":"number","nullable":true,"description":"Lowest MC seen while dipped; ratchets down."},"dip_fired_at":{"type":"string","format":"date-time","nullable":true},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"post":{"tags":["Robinhood Chain"],"summary":"Create an RHC price alert (PRO+)","description":"Market-cap drop alert with an optional recovery leg, baselined against the token's market cap **at creation**. One-shot state machine: `watching → dipped → recovered`; `dip_low` ratchets down while dipped; terminal on the dip when no `recovery_pct` is set.\n\n⚠️ **Latency differs from the Solana price alerts.** Solana alerts are evaluated inside a live in-memory price loop every 250 ms. RHC alerts are **event-driven**: each trade on the chain's trade feed (`rhc:dex_trade`) is checked against the alerted token set, with price-table polls (every 5 s while the feed is degraded or a trade carried no market cap, 60 s otherwise) and a trade-tape replay after a feed outage as safety nets. Latency is a few seconds (the chain trade flush is about 2 s), not sub-second. Every create response carries an `evaluation` block restating this. Do not size a strategy on the Solana figure. `token_address`, `drop_pct` and `recovery_pct` are immutable after creation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token_address","drop_pct"],"properties":{"name":{"type":"string","maxLength":64},"token_address":{"type":"string","description":"Lowercase 0x token address, must be tracked with a market cap"},"drop_pct":{"type":"number","minimum":0.01,"maximum":99.99},"recovery_pct":{"type":"number","minimum":0.01,"maximum":1000,"description":"Omit for a dip-only, terminal alert"},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"],"default":"webhook"},"webhook_url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Created — includes one-time webhook_secret and an `evaluation` block describing how the alert is evaluated.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"alert":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"baseline_mc_usd":{"type":"number"},"drop_pct":{"type":"number"},"recovery_pct":{"type":"number","nullable":true},"status":{"type":"string","enum":["watching","dipped","recovered","expired"],"description":"`expired` = the rule outlived its window and was deactivated (terminal, like `recovered`)."},"dip_low_mc_usd":{"type":"number","nullable":true},"dip_fired_at":{"type":"string","format":"date-time","nullable":true},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"webhook_secret":{"type":"string","nullable":true,"description":"One-time HMAC secret — only present when webhook delivery is configured."},"evaluation":{"type":"object","properties":{"mode":{"type":"string","enum":["event_driven","polled"],"description":"`event_driven` since 2026-09-15 (`polled` before)."},"trigger":{"type":"string","example":"rhc:dex_trade"},"interval_seconds":{"type":"integer","example":5,"description":"Kept for compatibility: the fast fallback table-poll interval."},"fallback_poll_seconds":{"type":"object","properties":{"fast":{"type":"integer","example":5},"slow":{"type":"integer","example":60}}},"note":{"type":"string"}}},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body, or token not tracked / has no market cap to baseline against.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"409":{"description":"RHC price alert limit reached for the tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/price-alerts/{id}":{"get":{"tags":["Robinhood Chain"],"summary":"Get one RHC price alert (PRO+)","description":"Fetch one Robinhood Chain price alert you own, addressed by the numeric `id` path param. Returns its thresholds, current `status`, the dip low and when the dip fired, delivery config, `is_active` and expiry. The fired dip / recovery events are listed at /rhc/price-alerts/events. 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"alert":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"baseline_mc_usd":{"type":"number"},"drop_pct":{"type":"number"},"recovery_pct":{"type":"number","nullable":true},"status":{"type":"string","enum":["watching","dipped","recovered","expired"],"description":"`expired` = the rule outlived its window and was deactivated (terminal, like `recovered`)."},"dip_low_mc_usd":{"type":"number","nullable":true},"dip_fired_at":{"type":"string","format":"date-time","nullable":true},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"patch":{"tags":["Robinhood Chain"],"summary":"Update an RHC price alert (PRO+)","description":"Only `name`, `delivery_mode`, `webhook_url` and `is_active` are mutable — changing a threshold mid-flight would make the alert's recorded events uninterpretable.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"alert":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true},"token_address":{"type":"string"},"token_symbol":{"type":"string","nullable":true},"baseline_mc_usd":{"type":"number"},"drop_pct":{"type":"number"},"recovery_pct":{"type":"number","nullable":true},"status":{"type":"string","enum":["watching","dipped","recovered","expired"],"description":"`expired` = the rule outlived its window and was deactivated (terminal, like `recovered`)."},"dip_low_mc_usd":{"type":"number","nullable":true},"dip_fired_at":{"type":"string","format":"date-time","nullable":true},"delivery_mode":{"type":"string","enum":["webhook","websocket","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body or id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"delete":{"tags":["Robinhood Chain"],"summary":"Delete an RHC price alert (PRO+)","description":"Permanently delete a Robinhood Chain price alert you own, addressed by the numeric `id` path param, together with its dip and recovery event history. To stop it temporarily instead, PATCH `is_active: false`. Deleting an active alert frees one slot of your active-alert quota. 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"deleted":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/price-alerts/events":{"get":{"tags":["Robinhood Chain"],"summary":"RHC price-alert fire history (PRO+)","description":"Dip and recovery events for your RHC alerts. Retained 30 days.","parameters":[{"name":"alert_id","in":"query","schema":{"type":"integer"}},{"name":"event_type","in":"query","schema":{"type":"string","enum":["dip","recovery"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":50}}],"responses":{"200":{"description":"OK — { chain, events[], count }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"alert_id":{"type":"integer"},"event_type":{"type":"string","enum":["dip","recovery"]},"fired_at":{"type":"string","format":"date-time"},"token_address":{"type":"string"},"baseline_mc_usd":{"type":"number","nullable":true},"current_mc_usd":{"type":"number","nullable":true},"drop_pct_actual":{"type":"number","nullable":true},"dip_low_mc_usd":{"type":"number","nullable":true},"recovery_pct_actual":{"type":"number","nullable":true},"delivered":{"type":"boolean","description":"True once the signal was actually written to one of your live sockets or accepted by your webhook. A frame that was only queued for a socket still running a replay and then dropped (queue overflow or a 4008 close) is NOT delivered and records delivery_error 'ws_replay_dropped'."},"delivered_at":{"type":"string","format":"date-time","nullable":true}}}},"count":{"type":"integer"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid parameter.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"alert_id not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/kol/coordination/alerts":{"get":{"tags":["Robinhood Chain"],"summary":"List RHC coordination rules (PRO+)","description":"List every Robinhood Chain KOL coordination rule you own, active and paused, newest first. A rule fires when at least `min_kols` tracked KOLs buy the same token within `window_minutes` and the coordination score reaches `min_score`, optionally bounded by a market-cap range; `cooldown_min` and `score_jump_break` decide when the same token may fire again. The quota counts every rule, paused ones included, and is separate from Solana: PRO 5, ULTRA 20, BUSINESS 100.","responses":{"200":{"description":"OK — { chain, rules[] }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"min_kols":{"type":"integer"},"window_minutes":{"type":"integer"},"min_score":{"type":"integer"},"cooldown_min":{"type":"integer"},"score_jump_break":{"type":"integer"},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"post":{"tags":["Robinhood Chain"],"summary":"Create an RHC coordination rule (PRO+)","description":"Fires when `min_kols` distinct tracked KOLs buy the same Robinhood Chain token inside `window_minutes` and the cluster scores at least `min_score`. `cooldown_min` suppresses repeats per (rule, token); `score_jump_break` is an **early exit from that cooldown** when the score climbs by at least that many points (the re-fire is flagged `is_rearm`). An unknown market cap is **dropped** by the MC band, never treated as inside it.\n\n**Scoring** uses the same v1 scorer as the Solana coordination alerts, so the number is comparable — with two differences recorded per-signal in `score_inputs`: `quality` is real (from the RHC KOL win-rate matview) while `earliness` is **defaulted**, because RHC has no early-entry measure. `density` is 1.0 by construction inside a rule's own window, so live scores start at 30.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":64},"min_kols":{"type":"integer","minimum":2,"maximum":50,"default":3},"window_minutes":{"type":"integer","minimum":1,"maximum":60,"default":15},"min_score":{"type":"integer","minimum":0,"maximum":100,"default":0},"cooldown_min":{"type":"integer","minimum":1,"maximum":1440,"default":30},"score_jump_break":{"type":"integer","minimum":0,"maximum":100,"default":20},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"],"default":"websocket"},"webhook_url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Created — includes one-time webhook_secret and a `scoring` block.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"rule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"min_kols":{"type":"integer"},"window_minutes":{"type":"integer"},"min_score":{"type":"integer"},"cooldown_min":{"type":"integer"},"score_jump_break":{"type":"integer"},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"webhook_secret":{"type":"string","nullable":true,"description":"One-time HMAC secret — only present when webhook delivery is configured."},"scoring":{"type":"object","properties":{"score_version":{"type":"string","example":"v1"},"quality":{"type":"string","description":"Real component, from mv_rhc_kol_scores winrate_7d."},"earliness":{"type":"string","description":"Defaulted — RHC has no early-entry equivalent."},"note":{"type":"string"}}},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body or MC band.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"409":{"description":"RHC coordination rule limit reached for the tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/kol/coordination/alerts/{id}":{"get":{"tags":["Robinhood Chain"],"summary":"Get one RHC coordination rule (PRO+)","description":"Fetch one Robinhood Chain KOL coordination rule you own, addressed by the `id` path param (UUID). Returns its KOL count, time window, score, cooldown and market-cap thresholds, delivery config (webhook, websocket or both) and `is_active` state. 400 for a malformed UUID, 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"rule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"min_kols":{"type":"integer"},"window_minutes":{"type":"integer"},"min_score":{"type":"integer"},"cooldown_min":{"type":"integer"},"score_jump_break":{"type":"integer"},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"patch":{"tags":["Robinhood Chain"],"summary":"Update an RHC coordination rule (PRO+)","description":"Partial update of a Robinhood Chain KOL coordination rule you own, addressed by the `id` path param (UUID). Every field accepted by POST is patchable, plus `is_active` to pause or resume the rule. A paused rule still counts toward your rule quota. 400 for a malformed UUID or an invalid body, 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true},"min_kols":{"type":"integer"},"window_minutes":{"type":"integer"},"min_score":{"type":"integer"},"cooldown_min":{"type":"integer"},"score_jump_break":{"type":"integer"},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"rule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"min_kols":{"type":"integer"},"window_minutes":{"type":"integer"},"min_score":{"type":"integer"},"cooldown_min":{"type":"integer"},"score_jump_break":{"type":"integer"},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body or id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]},"delete":{"tags":["Robinhood Chain"],"summary":"Delete an RHC coordination rule (PRO+)","description":"Permanently delete a Robinhood Chain KOL coordination rule you own, addressed by the `id` path param (UUID). Its fire history and cooldown state are deleted with it and its per-rule pushes stop. Deleting frees a quota slot; pausing does not. 400 for a malformed UUID, 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"deleted":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/kol/first-touches/subscriptions":{"get":{"tags":["Robinhood Chain"],"summary":"List RHC first-touch subscriptions (ULTRA+)","description":"List every Robinhood Chain first-touch subscription you own, active and paused, newest first. A subscription fires when a tracked KOL is the first to buy a token, filtered by KOL, minimum first-buy size in ETH, KOL win rate, trading strategy and market-cap range, and delivers per rule to a webhook, the WebSocket or both. ULTRA and BUSINESS only; the unfiltered broadcast is on WS channel `rhc:kol:first_touches` for PRO+. The quota counts every subscription, paused ones included, and is separate from Solana: ULTRA 10, BUSINESS 50.","responses":{"200":{"description":"OK — { chain, subscriptions[] }.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscriptions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"filters":{"type":"object","properties":{"kol":{"type":"string","nullable":true,"description":"Lowercase 0x EVM address"},"min_first_buy_eth":{"type":"number","nullable":true},"min_kol_winrate":{"type":"number","nullable":true},"strategy":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing","inactive","unscored"]},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true}}},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"ULTRA","x-badges":[{"name":"ULTRA","position":"after","color":"#b45309"}]},"post":{"tags":["Robinhood Chain"],"summary":"Create an RHC first-touch subscription (ULTRA+)","description":"Push the moment a token receives its **first** buy from a tracked KOL — the earliest signal available. A second KOL buying the same token produces nothing; dedup is structural (one first-touch row per token, ever).\n\n**Filters are `.strict()`** — an unknown key is a 400, not a silently ignored filter. ⚠️ There is deliberately **no `min_scout_tier` / `min_n_touches`** as on Solana: RHC has no scout scoring, and a filter that silently matched nothing would be worse than its absence. `min_kol_winrate` and `strategy` are the quality gates instead. An unknown market cap is dropped by the MC band, never passed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":64},"filters":{"type":"object","additionalProperties":false,"properties":{"kol":{"type":"string","description":"Lowercase 0x EVM address"},"min_first_buy_eth":{"type":"number","minimum":0},"min_kol_winrate":{"type":"number","minimum":0,"maximum":1,"description":"Win-rate on CLOSED positions. A KOL who has never sold is unscored and is dropped, not treated as a loser."},"strategy":{"type":"string","enum":["scalper","day_trader","swing","inactive","unscored"]},"min_mc_usd":{"type":"number"},"max_mc_usd":{"type":"number"}}},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"],"default":"websocket"},"webhook_url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Created — includes one-time webhook_secret.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscription":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"filters":{"type":"object","properties":{"kol":{"type":"string","nullable":true},"min_first_buy_eth":{"type":"number","nullable":true},"min_kol_winrate":{"type":"number","nullable":true},"strategy":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing","inactive","unscored"]},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true}}},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"webhook_secret":{"type":"string","nullable":true,"description":"One-time HMAC secret — only present when webhook delivery is configured."},"note":{"type":"string"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body, unknown filter key, or MC band inverted.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"409":{"description":"RHC first-touch subscription limit reached for the tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"ULTRA","x-badges":[{"name":"ULTRA","position":"after","color":"#b45309"}]}},"/rhc/kol/first-touches/subscriptions/{id}":{"get":{"tags":["Robinhood Chain"],"summary":"Get one RHC first-touch subscription (ULTRA+)","description":"Fetch one Robinhood Chain first-touch subscription you own, addressed by the `id` path param (UUID). Returns its filters (KOL, minimum first-buy ETH, KOL win rate, strategy, market-cap range), delivery config and `is_active` state. ULTRA and BUSINESS only. 400 for a malformed UUID, 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscription":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"filters":{"type":"object","properties":{"kol":{"type":"string","nullable":true},"min_first_buy_eth":{"type":"number","nullable":true},"min_kol_winrate":{"type":"number","nullable":true},"strategy":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing","inactive","unscored"]},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true}}},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"ULTRA","x-badges":[{"name":"ULTRA","position":"after","color":"#b45309"}]},"patch":{"tags":["Robinhood Chain"],"summary":"Update an RHC first-touch subscription (ULTRA+)","description":"`filters` is a whole-object replace, not a merge — merging would make removing a filter impossible to express.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true},"filters":{"type":"object"},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"subscription":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"filters":{"type":"object","properties":{"kol":{"type":"string","nullable":true},"min_first_buy_eth":{"type":"number","nullable":true},"min_kol_winrate":{"type":"number","nullable":true},"strategy":{"type":"string","nullable":true,"enum":["scalper","day_trader","swing","inactive","unscored"]},"min_mc_usd":{"type":"number","nullable":true},"max_mc_usd":{"type":"number","nullable":true}}},"delivery_mode":{"type":"string","enum":["websocket","webhook","both"]},"webhook_url":{"type":"string","format":"uri","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid body or id.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"ULTRA","x-badges":[{"name":"ULTRA","position":"after","color":"#b45309"}]},"delete":{"tags":["Robinhood Chain"],"summary":"Delete an RHC first-touch subscription (ULTRA+)","description":"Permanently delete a Robinhood Chain first-touch subscription you own, addressed by the `id` path param (UUID). Its delivery history is deleted with it and its per-rule pushes stop. Deleting frees a quota slot; pausing does not. ULTRA and BUSINESS only. 400 for a malformed UUID, 404 if the id doesn't exist or isn't yours.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"deleted":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/TierForbidden"},"404":{"description":"Not found.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"ULTRA","x-badges":[{"name":"ULTRA","position":"after","color":"#b45309"}]}},"/rhc/wallet-tracker/summary":{"get":{"tags":["Robinhood Chain"],"summary":"Activity summary across your tracked Robinhood Chain wallets (PRO+)","description":"Per-wallet buy/sell/volume rollup over the chosen period.\n\n**Sourced from `rhc_trades` directly, not from a capture log.** The Solana tracker needs a per-subscriber event log because Solana trades are only recorded for wallets somebody asked for; on RHC every swap is already persisted with its trader. Two consequences: a wallet added today reports its **full history** in the period rather than only what happens after you subscribe, and these numbers agree with `/rhc/wallet/{address}` by construction. Tier: **PRO+**.","parameters":[{"name":"period","in":"query","schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"wallet","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Restrict to one watched wallet."}],"responses":{"200":{"description":"OK. `stats_unavailable: true` means the rollup failed and the zeroes are not measurements.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"period":{"type":"string"},"interval":{"type":"string"},"stats_unavailable":{"type":"boolean"},"wallets":{"type":"array","items":{"type":"object","properties":{"wallet_address":{"type":"string"},"label":{"type":"string","nullable":true},"added_at":{"type":"string","format":"date-time"},"stats":{"type":"object","properties":{"trades":{"type":"integer"},"buys":{"type":"integer"},"sells":{"type":"integer"},"buy_eth":{"type":"number"},"sell_eth":{"type":"number"},"net_eth":{"type":"number"},"tokens_traded":{"type":"integer"},"last_trade_at":{"type":"string","format":"date-time","nullable":true}}}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/wallet-tracker/trades":{"get":{"tags":["Robinhood Chain"],"summary":"Merged trade feed across your tracked Robinhood Chain wallets (PRO+)","description":"Every trade by every wallet on your RHC watchlist, newest first, each row labelled with the watchlist label. The cursor (`next_before`) is an opaque keyset matching the rest of the RHC tree rather than the Solana tracker's integer epoch. A `wallet` filter must name a wallet already on your watchlist — otherwise this would be an unmetered alias for arbitrary wallet lookup. Tier: **PRO+**.\n\n**Where the rows come from** (*added 2026-08-29*): closed months older than the newest three move from Postgres to a Parquet archive; pages are split at `history.postgres_from` (ISO) — rows at/after it from Postgres, older rows from the archive reader, same ordering and `before` cursor. `history.archive_used`, `archive_months`, `archive_available` (`null` = not configured) and `truncated` (older history requested but the archive did not answer — retry rather than treating `has_more:false` as the end) mirror `/tokens/{mint}/trades`. Header `X-Read-Source`: `core`, `core+archive` or `archive`.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"before","in":"query","schema":{"type":"string"},"description":"Opaque cursor from next_before; a bare ISO block_time is also accepted for backward compatibility (loses intra-second position)."},{"name":"wallet","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"description":"Must be on your watchlist; otherwise 404."},{"name":"action","in":"query","schema":{"type":"string","enum":["buy","sell"]}},{"name":"token","in":"query","schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}}],"responses":{"200":{"description":"OK. `next_before` is the opaque pagination cursor — pass it back as `before`; `has_more` says whether another page exists.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","enum":["robinhood"]},"trades":{"type":"array","items":{"type":"object"}},"count":{"type":"integer"},"has_more":{"type":"boolean","description":"True when another page exists beyond this one."},"next_before":{"type":"string","nullable":true,"description":"Opaque (block_time, id) keyset cursor for the next page; null when has_more is false."}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"Invalid query parameters.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires Pro or Ultra tier.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The `wallet` filter names an address that is not on your watchlist.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}},"/rhc/tokens/{address}/intelligence":{"get":{"tags":["Robinhood Chain"],"operationId":"getRhcTokenIntelligence","summary":"Include-scoped token intelligence (PRO+)","description":"Include-scoped token intelligence for terminals: name the panels you need with `include` (comma-separated, no default). Each module is the existing keyed endpoint run in process with your plan, returned with its own `status` (ready | partial_history | unverified | unavailable | timeout), `as_of`, `provenance` and history coverage. One module failing never fails or zeroes another. Trade-derived modules are `partial_history` unless the source proves a complete interval. There is no global readiness claim. Budget: at most 5 modules and total cost 8. Modules: `snapshot` (cost 2, point_in_time, source /api/v1/rhc/tokens/{address}); `risk` (cost 2, point_in_time, source /api/v1/rhc/tokens/{address}/risk); `buyer_quality` (cost 2, trade_derived, source /api/v1/rhc/tokens/{address}/buyer-quality); `holders` (cost 3, point_in_time, source /api/v1/rhc/tokens/{address}/holders); `holder_count` (cost 1, point_in_time, source rhc_token_concentration() + rhc_token_holder_recon (same count as /api/v1/rhc/tokens/{address}/holders concentration.holder_count)); `flow` (cost 3, trade_derived, source /api/v1/rhc/tokens/{address}/flow); `kol` (cost 1, trade_derived, source /api/v1/rhc/tokens/{address}/kol-consensus); `locks` (cost 1, point_in_time, source /api/v1/rhc/tokens/{address}/locks); `top_traders` (cost 2, trade_derived, source /api/v1/rhc/tokens/{address}/top-traders).","security":[{"BearerAuth":[]}],"parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"}},{"name":"include","in":"query","required":true,"schema":{"type":"string","example":"snapshot,risk,kol"},"description":"Comma-separated modules: snapshot, risk, buyer_quality, holders, holder_count, flow, kol, locks, top_traders. Required; no default."}],"responses":{"200":{"description":"Per-module results.","content":{"application/json":{"schema":{"type":"object","required":["contract_version","chain","chain_id","address","address_format","native_asset","requested","generated_at","budget","summary","modules"],"properties":{"contract_version":{"type":"integer","const":1},"chain":{"type":"string","const":"robinhood-chain"},"chain_id":{"type":"integer","const":4663},"address":{"type":"string"},"address_format":{"type":"string","const":"evm_hex"},"native_asset":{"type":"string","const":"ETH"},"requested":{"type":"array","items":{"type":"string","enum":["snapshot","risk","buyer_quality","holders","holder_count","flow","kol","locks","top_traders"]}},"generated_at":{"type":"string","format":"date-time","description":"Response assembly time, not an observation time."},"budget":{"type":"object","additionalProperties":true},"summary":{"type":"object","additionalProperties":{"type":"integer"}},"modules":{"type":"object","additionalProperties":{"type":"object","required":["status","reason","as_of","provenance","coverage","limitations"],"properties":{"status":{"type":"string","enum":["ready","partial_history","unverified","unavailable","timeout"]},"reason":{"type":["string","null"],"description":"Machine reason for any non-ready status (tier_required, not_found, module_timeout, request_deadline, history_not_verified, not_captured, not_reconciled, stale_measurement, not_measured, source_error, ...)."},"as_of":{"type":["string","null"],"format":"date-time","description":"The source's own timestamp; null when the source gives none. Never the request time."},"provenance":{"type":"object","properties":{"source":{"type":"string"},"chain":{"type":"string"},"upstream_status":{"type":["integer","null"]},"cache":{"type":"string","enum":["hit","miss","none"]}}},"coverage":{"type":"object","properties":{"kind":{"type":"string","enum":["point_in_time","trade_derived"]},"historical_completeness":{"type":["object","null"],"properties":{"threshold":{"type":"string","const":"verified_interval"},"observed":{"type":"string","enum":["verified","not_verified","unknown"]},"threshold_met":{"type":"boolean"}}}}},"limitations":{"type":"array","items":{"type":"string"}},"data":{"type":"object","additionalProperties":true,"description":"The source endpoint's own response body. Absent when the module is unavailable or timed out; never a synthesized zero."}}}}}}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"X-Data-Delay":{"$ref":"#/components/headers/XDataDelay"},"X-MadeOnSol-Quota-Warning":{"$ref":"#/components/headers/XMadeOnSolQuotaWarning"}}},"400":{"description":"invalid_address, include_required, unknown_include or include_budget_exceeded.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Plan below PRO.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not enabled (TOKEN_INTELLIGENCE_API off).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate or daily limit reached (the composite counts as one call).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Used":{"$ref":"#/components/headers/XRateLimitUsed"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/AuthBackendUnavailable"}},"x-madeonsol-tier":"PRO","x-badges":[{"name":"PRO","position":"after","color":"#1d4ed8"}]}}},"x-madeonsol-tiers":[{"tier":"FREE","plan":"BASIC","name":"Free","price_eur_monthly":0,"price_eur_annual":0,"price_usd_monthly":0,"daily_limit":200,"burst_limit":60,"url":"https://madeonsol.com/developer"},{"tier":"PRO","plan":"PRO","name":"Pro","price_eur_monthly":43,"price_eur_annual":430,"price_usd_monthly":49,"daily_limit":10000,"burst_limit":300,"url":"https://madeonsol.com/checkout?tier=PRO"},{"tier":"ULTRA","plan":"ULTRA","name":"Ultra","price_eur_monthly":131,"price_eur_annual":1310,"price_usd_monthly":149,"daily_limit":100000,"burst_limit":1200,"url":"https://madeonsol.com/checkout?tier=ULTRA"},{"tier":"BUSINESS","plan":"BUSINESS","name":"Business","price_eur_monthly":400,"price_eur_annual":4000,"price_usd_monthly":456,"daily_limit":500000,"burst_limit":3000,"url":"https://madeonsol.com/checkout?tier=BUSINESS"},{"tier":"ENTERPRISE","plan":"ENTERPRISE","name":"Enterprise","price_eur_monthly":null,"price_eur_annual":null,"price_usd_monthly":null,"daily_limit":null,"burst_limit":null,"url":"https://madeonsol.com/pricing#enterprise"}]}