Endpoint Reference
Structured endpoint data for programmatic consumption. See /openapi.yaml for the machine-readable spec (refresh in progress — see OpenAPI Spec for the current operation set).
Live Stream Mapping
Every major REST endpoint has a WebSocket stream counterpart. Use REST for backfill, WebSocket for real-time. Sub-second latency on all streams.
| REST Endpoint | WebSocket Channel | Description |
|---|---|---|
| GET /v1/wallet/{addr}/trades | wallet:{addr}:pnl | Real-time realized PnL on every trade close |
| GET /v1/wallet/{addr}/positions | wallet:{addr}:positions | Position open/update/close events |
| GET /v1/wallet/{addr}/labels | wallet:{addr}:labels | Label and badge state changes |
| GET /v1/wallet/{addr}/follows | wallet:{addr}:follow | Follow-edge activations and updates |
| GET /v1/wallet/{addr}/entity | wallet:{addr}:entity | Entity-membership changes |
| GET /v1/token/{mint}/campaigns | token:{mint}:campaign | Coordinated campaign activations |
| GET /v1/token/{mint}/trades | token:{mint}:trades | Live trade tape |
| GET /v1/token/{mint}/ohlcv | token:{mint}:ohlcv:{view}:{tf} | Candle updates (full or filtered) |
| GET /v1/token/{mint}/suspicious-activity | token:{mint}:security | Token security events |
| — | token:{mint}:ticks | Chart tick events (stream-only) |
| — | wallet:{addr}:security | Wallet security events (stream-only) |
Route casing. The wallet and token resource roots are singular —
/v1/wallet/{address}/...and/v1/token/{mint}/.... The only plural wallet-collection endpoints are the Enterprise bulk routes (/v1/bulk/wallets/...). This reference matches the live registration exactly.
Wallets
GET /v1/wallet/{address}/performance — Layer 2
| Parameter | In | Type | Required | Default | Enum |
|---|---|---|---|---|---|
| address | path | string | yes | — | — |
| window | query | string | no | 7d | 1d, 7d, 30d |
Response schema: WalletPerformance
Cache TTL: 30s
Note: sharpe_ratio, profit_factor, and disposition_index are present on the schema but are always 0.0 here — they are not computed by the /performance SQL. The populated versions live on /labels and /quality.
GET /v1/wallet/{address}/trades — Layer 2
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| address | path | string | yes | — | — |
| limit | query | integer | no | 50 | max 200 |
| offset | query | integer | no | 0 | — |
| token | query | string | no | — | token mint filter |
Response: {"trades": WalletTrade[], "limit": int, "offset": int}
Live stream: wallet:{address}:pnl — fires on every trade close with realized PnL, hold time, entry/exit prices, fee attribution, trade-tool fingerprint
GET /v1/wallet/{address}/unrealized-pnl — coming soon
Coming soon. Not yet live. Until it ships, derive unrealized PnL by combining GET /v1/wallet/{addr}/positions?status=open with the latest tick from GET /v1/token/{mint}/ohlcv?timeframe=1s&limit=1. The companion WebSocket channel wallet:{addr}:unrealized-pnl ships at the same time.
GET /v1/wallet/{address}/positions — Layer 2
| Parameter | In | Type | Required | Default | Enum |
|---|---|---|---|---|---|
| address | path | string | yes | — | — |
| status | query | string | no | all | open, closed, all |
Response: {"positions": WalletPosition[]}
Live stream: wallet:{address}:positions — fires on position open, partial close, full close
GET /v1/wallet/{address}/labels — Layer 2
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
Response: WalletLabel | null
Live stream: wallet:{address}:labels — fires on label state change
Cache TTL: 60s
Includes: trader_type, performance_level, size_class, exit_style, automation_label, primary_terminal, primary_tool, primary_tool_pct, is_fresh_6h, is_fresh_24h, funded_by_farm, trade_badges[], identity_badges[], special_labels[], description, label_hash
GET /v1/wallet/{address}/quality — Layer 2
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
The position-correct skill signal. Reports a full-exit (position-correct) win rate alongside the commodity per-exit rate so the inflation between them is legible. Returns the object below, or literal null when the wallet has no snapshot row. 400 on a malformed address.
Response: {"wallet": string, "rated": bool, "skill_score": number, "performance_level": string, "trader_type": string, "exit_style": string, "size_class": string, "closed_positions": int, "position_win_rate_pct": number, "raw_exit_win_rate_pct": number, "win_rate_inflation_pts": number, "disposition_index": number|null, "conviction_sizing": number|null, "profit_factor": number, "sharpe_ratio": number|null, "runner_score": number, "avg_loss_roi_pct": number, "loss_consistency_stddev": number, "roi_p10_pct": number, "roi_p50_pct": number, "roi_p90_pct": number, "big_wins": int, "big_losses": int, "realized_pnl_usd": number, "trade_badges": string[]}
Field notes: rated is true when closed_positions >= 10. skill_score (0–100) = 0.40*position_win_rate + 0.30*profit_factor + 0.15*disposition + 0.15*runner, each normalized and clamped. position_win_rate_pct is the differentiated metric; raw_exit_win_rate_pct is the commodity per-exit rate for contrast; win_rate_inflation_pts = raw_exit - position, floored at 0.
Source: ClickHouse analytics.wallet_labels_emit_snapshot
Cache TTL: 60s
GET /v1/wallet/{address}/profile — Layer 2
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
Response: 30-dimensional behavior vector with raw + normalized values across six feature groups (hold timing, exit discipline, performance, velocity & sizing, infrastructure, provenance). Returns has_vector: false for wallets below the activity gating threshold.
Cache TTL: 60s
GET /v1/wallet/{address}/similar — Layer 2
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| address | path | string | yes | — | — |
| limit | query | integer | no | 20 | max 100 |
| min_trades | query | integer | no | — | minimum trade count filter |
| performance_level | query | string | no | — | PROFITABLE, BREAK_EVEN, etc. |
Response: {"query_wallet": string, "results": SimilarWallet[], "count": int} — k-NN cosine similarity over the 30-dim vector with shared traits and key differences.
GET /v1/wallet/{address}/provenance — Layer 2
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
Response: {"wallet": string, "root_entity": string|null, "root_source": string|null, "hops": int, "direct_funder": string, "last_funded_ts": string}
Cache TTL: 300s
GET /v1/wallet/{address}/entanglement — Layer 3
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
Response: {"wallet": string, "clusters": EntanglementCluster[], "cluster_count": int} — bundle-graph clusters this wallet participates in.
GET /v1/wallet/{address}/follows — Layer 3
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
Response (camelCase): {"address": string, "followsOut": FollowEdge[], "followsIn": FollowEdge[], "degraded": boolean}
Live stream: wallet:{address}:follow
Cache TTL: 30s
GET /v1/wallet/{address}/entity — Layer 3
| Parameter | In | Type | Required |
|---|---|---|---|
| address | path | string | yes |
Response (camelCase): {"address": string, "membership": EntityMembership|null, "siblingsSample": string[], "degraded": boolean} — entity kinds: shared_funder, shared_execution.
Live stream: wallet:{address}:entity
Cache TTL: 60s
Leaderboard
GET /v1/leaderboard — Layer 2
| Parameter | In | Type | Required | Default | Enum/Constraints |
|---|---|---|---|---|---|
| window | query | string | no | 7d | 1d, 7d, 30d |
| sort | query | string | no | pnl_usd | pnl_usd, roi, win_rate |
| limit | query | integer | no | 100 | max 500 |
| offset | query | integer | no | 0 | — |
| include_hft | query | boolean | no | false | include HFT/MEV bots |
Response: {"leaderboard": LeaderboardEntry[], "window": string, "sort": string, "limit": int, "offset": int}
Cache TTL: 60s
Note: Minimum 5 trades required for inclusion. By default the board excludes HFT/MEV bots (wallets with a median hold time under 60s) so it reflects real traders, not tick-scalpers — pass include_hft=true to include them. Malicious wallets are always excluded.
Tokens
GET /v1/token/{mint}/info — Layer 1
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
Response schema: TokenInfo
Cache TTL: 300s
Includes: token_mint, is_validated, is_suspicious, validation_reason
GET /v1/token/{mint}/ohlcv — Layer 1
| Parameter | In | Type | Required | Default | Enum/Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| timeframe | query | string | no | 1m | 1s, 1m, 5m, 15m, 1h |
| view | query | string | no | full | full, filtered |
| from | query | integer | no | — | unix ms |
| to | query | integer | no | — | unix ms |
| limit | query | integer | no | 500 | max 2000 |
Response: {"candles": OhlcvCandle[], "token_mint": string, "timeframe": string, "view": string}
Cache TTL: 5s
Live stream: token:{mint}:ohlcv:{view}:{tf}
GET /v1/token/{mint}/trades — Layer 1
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| limit | query | integer | no | 50 | max 200 |
Response: {"trades": TokenTrade[], "token_mint": string, "limit": int}
Live stream: token:{mint}:trades
Also available: token:{mint}:ticks (stream-only)
GET /v1/token/{mint}/price — coming soon
Coming soon. Not yet live. Until it ships, derive the current price from GET /v1/token/{mint}/ohlcv?timeframe=1s&limit=1 or subscribe to token:{mint}:ticks.
GET /v1/token/{mint}/buyer-quality — Free
| Parameter | In | Type | Required | Default |
|---|---|---|---|---|
| mint | path | string | yes | — |
| window_hours | query | integer | no | 1 |
Response: tiered breakdown — elite_smart_money, consistent_organic, developing_organic, bot_operated, farm_funded, unrated_new — plus smart_money_signal and volume_decomposition.
Cache TTL: 30s
Holders
GET /v1/token/{mint}/holders/summary — Layer 1
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
Response (camelCase): {"mint": string, "distinctCount": int, "totalBalanceRaw": string, "supplyRaw": string|null, "top10Pct": float|null, "top50Pct": float|null, "top100Pct": float|null, "hydrationStatus": "hydrating"|"hydrated"|"born_forward"|"partial_forward", "lastUpdatedSlot": int|null, "lastUpdatedTsMs": int|null, "asOfTsMs": int}
Cache TTL: 15s
GET /v1/token/{mint}/holders/top — Layer 1
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| n | query | integer | no | 10 | 1–500 |
Response (camelCase): {"mint": string, "distinctCount": int, "totalBalanceRaw": string, "hydrationStatus": string, "holders": HolderEntry[], "asOfTsMs": int} where HolderEntry = {rank, wallet, balanceRaw, pctOfTotal, firstSeenSlot}.
GET /v1/token/{mint}/holders — Layer 1
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| limit | query | integer | no | 100 | 1–1000 |
| offset | query | integer | no | 0 | — |
Response (camelCase): same as /holders/top plus limit, offset, nextOffset for cursor-style pagination.
Bundles
GET /v1/token/{mint}/bundles/summary — Free
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
Response: {"token_mint": string, "bundle_count": int, "open_bundle_count": int, "bundled_supply_pct": float, "bundled_value_usd": float, "bundled_realized_pnl_usd": float, "dominant_bundle_type": string}
Cache TTL: 15s
GET /v1/token/{mint}/bundles — Layer 3
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
Response: {"bundles": Bundle[], "token_mint": string} — bundle types: SybilPoisoning, CexCoordinated, SyntheticSwarm, Hybrid, JitoSequential. Status lifecycle: active → dormant / dumping / derisked / exited / rugged / merged.
GET /v1/token/{mint}/bundles/{bundle_id} — Layer 3
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
| bundle_id | path | string | yes |
Response: {"bundle": Bundle, "members": BundleMember[]} — per-wallet balance, realized PnL, entry/exit timing, leader flag.
Coordination
GET /v1/token/{mint}/campaigns — Layer 3
Response (camelCase): {"mint": string, "active": TokenCampaign[], "recent": TokenCampaign[], "degraded": boolean} — campaign status: active, closed.
Live stream: token:{mint}:campaign
Cache TTL: 15s
GET /v1/token/{mint}/crowd — Layer 3
Response (camelCase): {"mint": string, "current": CrowdMinute|null, "minutes": CrowdMinute[]} — crowd regime: quiet, trending_crowd, crowded_launch.
Cache TTL: 15s
GET /v1/entity/{entity_id} — Layer 3
Response (camelCase): {"entityId": string, "entityKind": string, "rootWallet": string, "memberCount": int, "confidence": float, "firstSeenTsMs": int, "lastSeenTsMs": int, "degraded": boolean, "members": EntityMember[]}
Cache TTL: 60s
GET /v1/entity/{entity_id}/members — Layer 3
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| entity_id | path | string | yes | — | — |
| page | query | integer | no | 0 | — |
| page_size | query | integer | no | 100 | 1–500 |
Response (camelCase): {"entityId": string, "page": int, "pageSize": int, "total": int, "members": EntityMember[], "degraded": boolean}
GET /v1/coordination/health — Layer 3
Response (camelCase): {"healthy": boolean, "degradedWindowMs": int, "droppedMessagesLastMinute": int, "observedAtMs": int}
Cache TTL: 30s
Intel
Layer 3. All intel endpoints return a uniform {"error": string, "code": string} envelope on failure; any upstream error surfaces as a 500.
GET /v1/intel/coordinated-pushes/forming
Coordinated pushes currently forming across tokens.
| Parameter | In | Type | Required |
|---|---|---|---|
| — | — | — | — |
Response (camelCase): array of {"tokenMint": string, "latestRegime": string, "priorRegime": string, "campaignId": string, "campaignStatus": string, "participantWallets": int, "participantEntities": int, "confidence": float, "tokenAgeMinutes": number}
GET /v1/intel/wallet/{leader}/cascade
Follower cascade behind a leader wallet on a given mint.
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| leader | path | string | yes | — | — |
| mint | query | string | yes | — | — |
| window_s | query | integer | no | 300 | 1–3600 |
400 conditions: Invalid leader wallet, Invalid token mint, and 400 when ?mint is missing.
Response (camelCase): array of {"follower": string, "confidence": float, "lagSeconds": number}
GET /v1/intel/entities/emerging
Entities that emerged within the lookback window.
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| hours | query | integer | no | 24 | 1–168 |
Response (camelCase): array of {"entityId": string, "entityKind": string, "rootWallet": string, "memberCount": int, "confidence": float, "firstSeenTsMs": int, "lastSeenTsMs": int}
GET /v1/intel/token/{mint}/early-buyers
Entities that participated in the token’s early-buy window.
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| window_s | query | integer | no | 300 | 1–3600 |
400 conditions: Invalid token mint.
Response (camelCase): array of {"entityId": string, "entityKind": string, "rootWallet": string, "confidence": float, "membersInEarlyBuy": int, "memberWallets": string[]}
GET /v1/intel/token/{mint}/copy-originator
Candidate copy-trade originators inside a buy cluster window.
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
| start_ts_ms | query | integer | yes |
| end_ts_ms | query | integer | yes |
400 conditions: Invalid token mint, end_ts_ms must be > start_ts_ms, window too wide (max 60 minutes).
Response (camelCase): array of {"candidateLeader": string, "followerBuysInCluster": int, "meanConfidence": float}
GET /v1/intel/token/{mint}/entity-concentration
Entity-level volume concentration over the lookback window.
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| hours | query | integer | no | 24 | 1–168 |
400 conditions: Invalid token mint.
Response (camelCase): {"totalWallets": int, "distinctActors": int, "totalVolumeUsd": number, "entityVolumeUsd": number, "entityVolumeShare": float, "topActors": string[]}
GET /v1/intel/token/{mint}/late-retail
Late retail entering after elite sells.
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| hours | query | integer | no | 24 | 1–72 |
400 conditions: Invalid token mint.
Response (camelCase): {"eliteSells": int, "lateBuyers": int, "lateBuyerVolumeUsd": number, "avgLagSeconds": number, "shareUnprofitable": float}
Security
GET /v1/token/{mint}/wash-trades — Layer 3
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| limit | query | integer | no | 50 | max 200 |
Response: {"wash_trades": WashTradeAlert[], "token_mint": string, "count": int}
Cache TTL: 15s
GET /v1/token/{mint}/funding-abuse — Layer 3
| Parameter | In | Type | Required | Default | Constraints |
|---|---|---|---|---|---|
| mint | path | string | yes | — | — |
| early_window_minutes | query | integer | no | 60 | 10–240 |
| limit | query | integer | no | 50 | max 200 |
Response: {"token_mint": string, "summary": FundingAbuseSummary, "wallets": FundingAbuseWallet[]}. The summary.reasons field holds reason codes: SEED_WAVE_HEAVY, SEED_WAVE_MODERATE, SEED_WAVE_LIGHT, FARM_FUNDED_FRESH_WALLETS, CEX_DISPERSED_ROOTS, CEX_ROOT_CONVERGENCE, FAST_FUND_TO_BUY, SAME_DAY_FUND_TO_BUY, SHARED_TERMINAL_<terminal>. Treat summary.suspicious and summary.reasons as the stable surface — summary.score is calibrated proprietarily.
GET /v1/token/{mint}/suspicious-activity — Layer 3
| Parameter | In | Type | Required |
|---|---|---|---|
| mint | path | string | yes |
Response: {"token_mint": string, "status": "clean"|"suspicious"|"rugged", "flagged_reasons": string[], "flagged_time": string|null, "rugged_time": string|null, "live_activity_flags": string[], "funding_abuse": FundingAbuseSummary|null}. live_activity_flags mirrors funding_abuse.reasons when funding_abuse.suspicious is true.
Live stream: token:{mint}:security
POST /v1/webhooks — coming soon
Coming soon. Webhook delivery is on the Layer 3 roadmap. Until it ships, use the WebSocket security streams (token:{mint}:security, wallet:{addr}:security) for the same event coverage.
Bulk (Enterprise)
POST /v1/bulk/wallets/profile, POST /v1/bulk/wallets/coordination — Enterprise, coming soon
Coming soon. Bulk endpoints are on the Enterprise roadmap. Reach out via your Enterprise contact for a preview window.
Operations (No Auth)
| Endpoint | Response |
|---|---|
| GET /health | {"status": "ok"} |
| GET /ready | {"status": "ready"|"not ready"} |
| GET /metrics | Prometheus text format |