# 0xinsider Developer API — Full Reference > The data and intelligence layer for Polymarket and Kalshi, exposed to AI agents, trading bots, and research tools. > Every wallet graded, every large trade scored, every outlier flagged — trader grades, whale trades, smart money signals, insider detection. Base URL: https://api.0xinsider.com OpenAPI spec: https://0xinsider.com/api/v1/openapi.json Public weekly wallet discovery page: https://0xinsider.com/trending/wallets --- ## Authentication All endpoints require an API key via Bearer token (except /api/v1/health). Authenticated internal POST endpoints that mutate state also accept an optional Idempotency-Key header for safe retries. Authorization: Bearer oxi_sk_live_... Get your key: https://0xinsider.com/developers Requires active Insider subscription ($89/mo). Key format: oxi_sk_live_{64 hex chars} Keys are HMAC-SHA256 hashed server-side. Shown once on creation — copy immediately. --- ## Rate Limits 100 requests/minute per user (sliding window) on authenticated endpoints. Batch read endpoints additionally reserve 100 batch item units/minute per user before execution. A batch with N requested items costs N item units, including duplicate and invalid items; over-quota batches return 429 before partial execution. /api/v1/health is limited to 60 requests/minute per IP. Response headers on authenticated requests: X-RateLimit-Limit: 100 X-RateLimit-Remaining: 84 X-RateLimit-Reset: 1710772860 (unix timestamp) X-Request-Id: req_550e8400 Additional response headers on successful batch reads: X-Request-Cost: 25 X-Batch-RateLimit-Limit: 100 X-Batch-RateLimit-Remaining: 75 X-Batch-RateLimit-Reset: 1710772860 (unix timestamp) 429 Too Many Requests includes Retry-After plus X-RateLimit-Limit / Remaining / Reset headers. 503 rate_limit_unavailable includes Retry-After plus X-Request-Id when the Redis-backed authenticated rate limiter is temporarily unavailable. Transport behavior: Normal API requests use a 30-second server timeout. Timed-out requests return HTTP 408 Request Timeout with an empty body (transport-layer timeout, not the standard JSON error envelope). Successful browser CORS preflight responses include Access-Control-Max-Age: 86400 (24h). --- ## Response Format ### Single object { "object": "trader", "data": { ... }, "meta": { "request_id": "req_...", "cached": true, "cache_age_s": 42 } } ### List { "object": "list", "data": [...], "has_more": true, "next_cursor": "...", "meta": { ... } } ### Batch { "object": "trader_batch", "data": [{ "index": 0, "input": "swisstony", "status": "ok", "data": { ... } }], "meta": { "request_id": "req_...", "cached": false, "total_items": 1, "successful_items": 1, "failed_items": 0, "request_cost": 1, "rate_limit": { "basis": "batch_items_per_minute", "limit": 100, "remaining": 99, "reset": 1710772860 } } } ### Error (RFC 7807-inspired) { "object": "error", "error": { "code": "...", "message": "...", "doc_url": "...", "param": null }, "meta": { "request_id": "req_..." } } ### Trust metadata vocabulary Trust-critical public API values use shared source/freshness/reconciliation/completeness semantics when a value can be cached, stale, partial, computed, or provider-unavailable. source.kind — provider | database | cache | computed | client_input | unavailable freshness.status — fresh | refreshing | stale | not_live | unknown | unavailable reconciliation.status — provider_backed | db_mirror | computed | partial | not_applicable | unavailable completeness.status — complete | partial | not_computed | not_applicable | unavailable Do not infer provider facts from missing fields, zeros, titles, slugs, or empty arrays. If a provider-owned value is unavailable, treat explicit unavailable/partial metadata as part of the result. ## TypeScript Client Repo-owned client source: web/src/lib/api-client. The client operation table is drift-tested against this OpenAPI spec, including method, path, and operationId. Supported runtime behavior: Authorization bearer headers, path parameter interpolation, repeated query parameters, JSON bodies, and typed V1 error exceptions. Example: docs/examples/api-client/typescript.ts. Release checklist: docs/api-client-release-process.md. This is not a published npm package yet; package name, semver, changelog ownership, and npm access require a follow-up release issue. ### Error codes 400 bad_request — Invalid parameters (check error.param) 401 invalid_api_key — Missing or invalid API key 402 subscription_required — Key valid but no active Insider subscription 403 forbidden — Account access denied 404 not_found — Trader or market not found 408 request_timeout — Request exceeded the 30-second server timeout (empty body, transport-layer timeout) 423 account_locked — Account is locked 429 rate_limited — Too many requests (check Retry-After plus X-RateLimit-* headers) 503 rate_limit_unavailable — Authenticated rate limiter temporarily unavailable (check Retry-After header) 500 internal_error — Server error ### Number precision Money (P&L, volume, size_usd) and scores: 2 decimal places, truncated Rates (win_rate, daily_win_rate) and prices: 4 decimal places, truncated ### Prefixed IDs Trader: trd_0x... | Market: mkt_0x... | Whale trade: wt_... | Radar flag: rf_... | Request: req_... --- ## Endpoints Public page: /trending/wallets ranks Polymarket wallets by 7-day realized P&L from local resolved-market data. It is a website discovery surface, not a public /api/v1/* contract. ### 1. GET /api/v1/trader/{address} Question: "Should I trust this trader?" Parameters: address (path, required) — Ethereum wallet address (0x...) or known trader username expand (query, optional, repeatable) — Include heavy fields: strategy, categories, quant_metrics expand[] (query, optional, repeatable) — Backward-compatible alias for expand Response fields (object: trader): id — Prefixed trader ID (trd_...) address — Wallet address username — Polymarket username (nullable) grade — S, A, B, C, D, or F (nullable for ungraded) score — Numeric grade score (nullable) rank — Global leaderboard rank (nullable) pnl.total — Total P&L in USD pnl.realized — Realized P&L pnl.unrealized — Mark-to-market unrealized P&L pnl.last_7d — Last 7 days P&L pnl.last_30d — Last 30 days P&L stats.markets_traded — Number of markets stats.win_rate — Overall win rate (0.0-1.0) stats.daily_win_rate — Daily win rate stats.total_volume — Total volume in USD strategy — null unless expanded via expand or expand[]. Object: { strategy_type, description, confidence } category_strengths — null unless expanded via expand or expand[]. Array of { category, grade, markets, pnl } quant_metrics — null unless expanded via expand or expand[]. Object: Sharpe, Sortino, max drawdown, Kelly fraction last_active — Last activity timestamp (ISO 8601) synced_at — Last sync timestamp sync_status — "synced", "unknown", or "pending" Notes: - Known trader usernames resolve to the same profile as their wallet address. - Unknown traders return sync_status: unknown (not 404). Poll again later. - Strategy expand adds ~200ms (16 parallel queries). Use only when needed. - Cache: 60s Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/trader/swisstony?expand=strategy&expand=categories&expand=quant_metrics' ### 1b. POST /api/v1/traders/batch Question: "Which of these wallets are worth following?" Request JSON: traders (array, required) — 1-25 wallet addresses or known trader usernames expand (array, optional) — Shared heavy fields: strategy, categories, quant_metrics Response fields (object: trader_batch): data[] preserves request order and duplicate inputs data[].index — Zero-based input index data[].input — Original requested trader lookup data[].status — ok or error data[].data — Trader object when status is ok data[].error — { code, message, doc_url, param } when status is error meta.request_cost — Number of batch item units reserved before execution meta.rate_limit.basis — "batch_items_per_minute" meta.rate_limit.remaining/reset — Batch item quota state after reservation Notes: - Maximum 25 items per request. - Empty input arrays and over-25 arrays return 400 for the whole request. - Blank trader items become per-item bad_request errors; unknown traders return sync_status: unknown like the single endpoint. - Quota is reserved for all requested items before execution; over-quota batches return 429 and do not partially execute. Example: curl -X POST -H 'Authorization: Bearer oxi_sk_live_...' -H 'Content-Type: application/json' \ -d '{"traders":["swisstony","0xabc..."],"expand":["strategy"]}' \ 'https://api.0xinsider.com/api/v1/traders/batch' --- ### 2. GET /api/v1/trader/{address}/position-timeline Question: "Show me every fill this trader made in market X, with running position and avg entry price." Parameters: address (path, required) — Trader wallet address. Case-insensitive. condition_id (query, required) — Polymarket market condition_id. limit (query, optional) — 1–100, default 20. cursor (query, optional) — From previous response's next_cursor. Response fields (object: list, each event): id — Prefixed event ID (pe_...) event_timestamp — ISO 8601 timestamp of the on-chain fill action — 'buy' or 'sell' (from the taker's perspective) outcome_side — 'yes' or 'no' amount_delta — Signed share delta (+ on buy, − on sell) price — Fill price in USDC per share (0–1) usdc_notional — Positive USDC notional of the fill tx_hash — Polygon transaction hash running_amount — Cumulative signed share balance after this fill running_avg_price — Buy-weighted entry basis (matches Polymarket /positions avgPrice) Coverage: Only HOT and WARM tier traders are captured. Other traders return 404. Notes: - Ordered newest first; running totals are computed server-side in SQL. - Running avg price does not change on sells (entry-basis convention). - Cursor-paginated via next_cursor when has_more is true. - Id-keyed alias: GET /api/v1/traders/{id}/position-timeline accepts the integer traders.id instead of the wallet address and returns the same body. Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/trader/0xabc.../position-timeline?condition_id=0x123...&limit=50' --- ### 2b. GET /api/v1/trader/{address}/export Question: "Can I export this trader, and what data would it cover?" Parameters: address (path, required) — Ethereum wallet address or known trader username-style lookup. Response fields (object: trader_export_snapshot): address — Canonical trader wallet address source_range.first_pnl_date / last_pnl_date — Local export P&L date coverage source_range.latest_trade_at — Latest synced local market activity timestamp completeness.status — complete, partial, or empty completeness.sync_coverage — Synced local markets divided by provider markets_traded when available reconciliation.provider_lifetime_volume — Provider-owned lifetime trader volume, if known reconciliation.exported_activity_volume — Local daily_pnl activity volume reconciliation.exported_market_cost_basis — Local trader_markets cost-basis sum counts.estimated_trade_rows — O(1) estimate from sync_cursors.last_trade_count large_export_policy.mode — metadata_only_in_v1 Notes: - V1 returns metadata only; it does not stream or create the raw dataset export. - Provider lifetime volume and local export activity volume are separate fields; do not subtract one as if it were the same unit. - Full internal exports still use /api/export/{address}/start with direct streaming or async job handling. Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/trader/swisstony/export' --- ### 3. GET /api/v1/market/{condition_id}/intel Question: "What's the smart money doing on this market?" Parameters: condition_id (path, required) — 0xinsider market condition ID (Polymarket condition_id or Kalshi event_ticker). Use /api/v1/markets/search and pass condition_id, not the prefixed market.id (mkt_...). timeframe (query, optional) — 1h, 4h, 24h, 7d. Default: 24h Response fields (object: market_intel): market.id — Prefixed market ID (mkt_...) market.condition_id — Raw condition ID market.title — Market question market.slug — URL slug market.category — Market category market.platform — polymarket or kalshi smart_money.net_flow_usd — Net YES minus NO volume from graded traders smart_money.direction — YES or NO (which side has more smart money) smart_money.whale_trade_count — Number of whale trades in timeframe smart_money.buy_volume_usd — Total buy volume smart_money.sell_volume_usd — Total sell volume smart_money.top_positions — Array (top 5 by grade): { id, address, username, grade, side, size_usd } timeframe — Echo of requested timeframe Notes: - Returns 400 if condition_id is empty or uses a prefixed mkt_... market.id instead of the raw condition_id - Returns 404 if market not found in our database - All data from our DB — no external API calls at request time - Cache: 60s (1h timeframe), 300s (24h/7d) Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/market/0x123.../intel?timeframe=24h' ### 3b. POST /api/v1/markets/intel/batch Question: "Which of these markets has the strongest smart-money signal?" Request JSON: condition_ids (array, required) — 1-25 raw provider condition_id values timeframe (string, optional) — 1h, 4h, 24h, 7d. Default: 24h Response fields (object: market_intel_batch): data[] preserves request order and duplicate inputs data[].index — Zero-based input index data[].input — Original requested condition_id data[].status — ok or error data[].data — MarketIntel object when status is ok data[].error — { code, message, doc_url, param } when status is error meta.request_cost and meta.rate_limit follow the same batch item quota contract as /traders/batch Notes: - Maximum 25 items per request. - Do not pass prefixed mkt_... IDs; those become per-item bad_request errors. - Unknown raw condition_id values become per-item not_found errors. - Invalid shared timeframe returns 400 for the whole request before item execution. Example: curl -X POST -H 'Authorization: Bearer oxi_sk_live_...' -H 'Content-Type: application/json' \ -d '{"condition_ids":["0x123...","KXNBAGAME-26MAR23LALDET-LAL"],"timeframe":"24h"}' \ 'https://api.0xinsider.com/api/v1/markets/intel/batch' --- ### 4. GET /api/v1/whale-trades Question: "What big moves are happening?" Parameters: min_size (query, optional) — Minimum trade size in USD. Default: 5000 category (query, optional) — Filter by provider-backed market_canonical category (case-insensitive) min_grade (query, optional) — Minimum trader grade: S, A, B, C, D, F limit (query, optional) — Max results, 1-100. Default: 20 cursor (query, optional) — Pagination cursor from previous next_cursor Response fields (object: list, items: whale trades): id — Prefixed whale trade ID (wt_...) traded_at — Trade timestamp (ISO 8601) size_usd — Trade size in USD side — BUY or SELL price — Execution price (0.0-1.0) signal_score — 0.0-1.0 normalized signal (higher = more significant) trader.id — Prefixed trader ID trader.address — Wallet address trader.username — Polymarket username (nullable) trader.grade — Trader grade (nullable) market.id — Prefixed market ID market.condition_id — Raw condition ID market.title — Market question market.slug — URL slug market.category — Provider-backed market_canonical category (nullable) Pagination: Cursor-based (composite timestamp+ID). Use next_cursor for next page. has_more: true if more results exist. Newest trades first. Notes: - Signal score is normalized 0-1 (higher = more significant) - min_grade=S returns only S-grade traders. min_grade=A returns S and A. - Category and grade filters are applied before pagination in SQL. - SQL-backed limit + 1 pagination makes has_more and next_cursor reflect the filtered result set. - Cache: 15s Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/whale-trades?min_grade=S&limit=10' ### 4b. GET /api/v1/whale-trades/history Question: "Replay whale activity for a market, trader, category, or time window" Parameters: condition_id (query, optional) — Exact raw provider condition_id. Unknown markets return an empty list. trader (query, optional) — Wallet address, timestamp-suffixed wallet alias, or username resolved against traders. Unknown traders return an empty list. category (query, optional) — Filter by provider-backed market_canonical category (case-insensitive) min_grade (query, optional) — Minimum trader grade: S, A, B, C, D, F platform (query, optional) — polymarket, kalshi, or all. Filters whale_alerts.platform. from (query, optional) — Inclusive RFC3339 lower bound on traded_at to (query, optional) — Exclusive RFC3339 upper bound on traded_at. Must be after from when both are present. min_size (query, optional) — Minimum trade size in USD. Default: 5000 limit (query, optional) — Max results, 1-100. Default: 20 cursor (query, optional) — wth_ cursor from previous next_cursor. URL-encode when replaying as a query parameter. Response fields: same whale trade item shape as GET /api/v1/whale-trades plus history metadata: id — Prefixed whale trade ID (wt_...) traded_at — Trade timestamp (ISO 8601) size_usd — Trade size in USD side — BUY or SELL price — Execution price (0.0-1.0) signal_score — 0.0-1.0 normalized signal trader.id — Prefixed trader ID trader.address — Wallet address trader.username — Polymarket username (nullable) trader.grade — Trader grade (nullable) market.id — Prefixed market ID market.condition_id — Raw condition ID market.title — Market question market.slug — URL slug market.category — Provider-backed market_canonical category (nullable) meta.source.kind — local_replay meta.source.table — whale_alerts meta.source.provider_fetch_at_request_time — false meta.completeness.status — best_effort meta.completeness.reason — Explains local replay completeness can vary by market and time window Pagination: Cursor-based (wth_ composite timestamp+ID). Use next_cursor for next page. Results ordered newest first by traded_at desc, id desc. All filters are pushed into SQL before LIMIT. No offset pagination. Notes: - Source is local whale_alerts replay; this endpoint does not fetch providers at request time. - This is historical replay, not a live/current feed, and metadata exposes best_effort completeness. - Unknown trader or condition_id filters return an empty list rather than an error. Examples: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/whale-trades/history?condition_id=0x123&from=2026-05-01T00:00:00Z&to=2026-05-02T00:00:00Z&limit=50' const res = await fetch('https://api.0xinsider.com/api/v1/whale-trades/history?trader=swisstony&min_grade=A&limit=20', { headers: { Authorization: 'Bearer oxi_sk_live_...' } }); const page = await res.json(); import requests page = requests.get( 'https://api.0xinsider.com/api/v1/whale-trades/history', headers={'Authorization': 'Bearer oxi_sk_live_...'}, params={'category': 'crypto', 'from': '2026-05-01T00:00:00Z', 'limit': 100}, timeout=30, ).json() --- ### 5. GET /api/v1/positions Question: "What do the sharpest wallets currently hold?" Parameters: min_size (query, optional) — Minimum current position value in USD. Default: 100 category (query, optional) — Exact match against provider-backed market_canonical.category min_grade (query, optional) — Minimum trader grade: S, A, B, C, D, F (allowlist expansion) side (query, optional) — yes or no. Maps to outcome_index 0/1 limit (query, optional) — Max results, 1-100. Default: 20 cursor (query, optional) — Pagination cursor from previous next_cursor Response fields (object: list, items: positions): id — Composite prefixed ID (pos_::) platform — polymarket (Slice 5 is Polymarket-only; field stays in shape for forward compat) wallet — Lowercased proxy wallet side — YES or NO shares — Live share count from the wallet_positions mirror avg_price — Volume-weighted entry price (nullable when cost basis is not populated) current_value_usd — Current mark-to-market value in USD (always non-null on V1) initial_value_usd — Polymarket initialValue sum (nullable) cash_pnl — Unrealized P&L for the open position (Polymarket cashPnl, nullable) realized_pnl — Closed-leg P&L rolled up (Polymarket realizedPnl, nullable) last_reconciled_at — Max updated_at across mirror legs (nullable) freshness — fresh | refreshing | stale | unknown (backend-computed staleness bucket) trader.id — Prefixed trader ID (trd_0x...) trader.address — Wallet address trader.username — Polymarket username (nullable) trader.grade — S, A, B, C, D, F (nullable) trader.win_rate — Percentage 0-100 (nullable) trader.pnl — All-time P&L (nullable) trader.markets — Markets traded count (nullable) trader.wallet_age_days — Days since join_date (nullable) trader.is_new_wallet — True when the wallet is younger than 30 days market.id — Prefixed market ID (mkt_...) market.condition_id — Raw condition ID market.title — Market question market.slug — Provider slug (nullable) market.event_slug — Parent event slug (nullable) market.category — Provider-backed market_canonical category (nullable) market.outcome_label — Provider-reported outcome label (nullable; separate from side) market.end_date — Resolution date (nullable) Pagination: Keyset cursor on (current_value_usd DESC, wallet ASC, condition_id ASC, outcome_index ASC) has_more: true if more results exist. next_cursor base64-encoded. Notes: - Pre-reconcile rows (current_value_usd IS NULL) are excluded from V1 - min_grade=A means S OR A; min_grade=B means S, A, or B (allowlist expansion) - Non-binary positions (sports n-outcome) are not surfaced on V1 - Polymarket-only in Slice 5; Kalshi positions land when the Kalshi mirror does Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/positions?min_grade=A&min_size=1000&limit=10' --- ### 6. GET /api/v1/leaderboard Question: "Who are the best traders?" Parameters: category (query, optional) — Filter by category slug strategy (query, optional) — Filter by ML-detected strategy type limit (query, optional) — Max results, 1-100. Default: 20 cursor (query, optional) — Pagination cursor from previous next_cursor Response fields (object: list, items: leaderboard entries): id — Prefixed trader ID (trd_...) address — Wallet address username — Username (nullable) grade — S, A, or B (leaderboard only shows graded traders) score — Numeric grade score pnl — Total P&L in USD volume — Total trading volume markets_traded — Number of markets win_rate — Win rate (0.0-1.0) strategy_type — ML-detected strategy (nullable) platform — polymarket or kalshi last_active — Last activity timestamp Pagination: Cursor-based (composite score+address). Sorted by score descending. has_more: true if more results exist. Strategy types (for filtering): accumulator, algo_trader, arbitrageur, directional, event_driven, market_maker, momentum, scalper, speculator, swing_trader Notes: - Materialized view, refreshed every 12h - Cache: 300s - Returns an ETag header; send If-None-Match to receive 304 Not Modified when unchanged Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/leaderboard?category=crypto&limit=10' --- ### 7. GET /api/v1/markets/search Question: "Find markets about X" Parameters: q (query, required) — Search query, 1-512 characters before whitespace trimming and non-empty after trimming (e.g., 'bitcoin', 'trump', 'world cup') category (query, optional) — Filter by category status (query, optional) — active, closed, or all. Default: all limit (query, optional) — Max results, 1-100. Default: 20 cursor (query, optional) — Pagination cursor from previous next_cursor Response fields (object: list, items: market search results): id — Prefixed market ID (mkt_...) condition_id — Raw condition ID title — Market question slug — URL slug (nullable) category — Market category (nullable) platform — polymarket or kalshi (nullable) status — active or closed Notes: - Case-insensitive title search (ILIKE + trigram similarity) - Pagination is over representative market groups, not raw sub-markets - Use condition_id with /market/{condition_id}/intel for detailed analysis - Cache: 30s Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/markets/search?q=bitcoin&status=active' --- ### 8. GET /api/v1/markets/explore Question: "Which markets deserve attention right now?" Parameters: category (query, optional) — Filter by provider-native market category (case-insensitive, no parent/child expansion) status (query, optional) — active, closed, or all. Default: all platform (query, optional) — polymarket, kalshi, or all. Default: all sort (query, optional) — trending, whales, volume, newest. Default: trending limit (query, optional) — Max results, 1-48. Default: 24 cursor (query, optional) — Pagination cursor from previous next_cursor q (query, optional) — Keyword search against market titles Response fields (object: list, items: explore entries): type — group or standalone standalone.market — Single ExploreMarket item with market metadata and whale activity group.event_slug — Event-level slug for grouped discovery rows group.parent_title — Shared event title for the grouped markets group.markets — Array of ExploreMarket items under the event cluster total — Total matching visible entries after grouping (present on the first page, omitted on cursor pages) facets.categories[] — Live category facet values (value, label, count). Categories come straight from Polymarket Gamma and Kalshi — no local parent/child taxonomy, no synthetic aggregates. facets.platforms[] — Live platform facet values with labels and counts Notes: - Returns whale-active titled markets only; empty titles are excluded - Pagination is over visible discovery entries, not raw market rows - Results are grouped into event clusters when multiple related markets share the same event - total is returned on the first page only; cursor pages omit it to avoid recounting the full result set - Use url_slug for first-party market-page links and slug for provider-native links - Returns an ETag header; send If-None-Match to receive 304 Not Modified when unchanged Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/markets/explore?sort=trending&limit=24' --- ### 9. GET /api/v1/insider-radar Question: "What suspicious trading patterns are happening?" Parameters: min_suspicion (query, optional) — Minimum suspicion score, 0-100. Default: 0 severity (query, optional) — flag or watch limit (query, optional) — Max results, 1-100. Default: 20 cursor (query, optional) — Pagination cursor from previous next_cursor Response fields (object: list, items: radar flags): id — Prefixed radar flag ID (rf_...) suspicion_score — 0-100 suspicion score severity — flag (high) or watch (moderate) trader.id — Prefixed trader ID trader.address — Wallet address trader.username — Username (nullable) market.id — Prefixed market ID market.condition_id — Raw condition ID market.title — Market question scores.timing — Timing component score (nullable) scores.edge — Edge component score (nullable) scores.size — Size component score (nullable) scores.fresh_wallet — Fresh wallet component score (nullable) evidence — Structured JSON with detection details created_at — Detection timestamp (ISO 8601) Pagination: Cursor-based (composite suspicion_score+ID). Highest suspicion first. Notes: - Unique data — no other platform exposes insider radar via API - Scores break down WHY a trade is suspicious - Cache: 30s Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/insider-radar?min_suspicion=60&limit=10' --- ### 10. GET /api/v1/events/feed/since Question: "What public intelligence changed since my bot last checked?" Parameters: cursor (query, optional) — Opaque event replay cursor from previous next_cursor limit (query, optional) — Max public-safe events, 1-100. Default: 50 Response fields (object: event_replay): data[].id — Opaque event ID; currently identical to the event cursor data[].type — whale_trades_inserted data[].cursor — Cursor positioned at this event data[].sequence — Global whale_alerts.id sequence data[].published_at — whale_alerts.traded_at timestamp for the durable event data[].payload — Public event payload: {count, whale_alert_id, condition_id, trader_id, platform} data[].source.kind — local_durable_replay data[].source.producer_family — whale_trades data[].source.provider_fetch_at_request_time — false data[].freshness.status — observed data[].freshness.observed_at — Same timestamp as published_at next_cursor — Cursor to store for the next replay request meta.retention.status — durable_database meta.retention.cursor_expired — false for the durable whale_alerts cursor meta.completeness.status — complete or caught_up Pagination: Cursor-based over whale_alerts_id_asc. Pass next_cursor on the next request. If has_more is true, keep paging until false. Notes: - This is the public API-key-safe durable projection, not the browser/session SSE feed - Browser-only sports/trader-sync/large-position events and private alert, following, radar, and position patch events are excluded until they have a durable public outbox - The cursor maps to whale_alerts.id and is valid across backend replicas - No provider fetch happens at request time; source.kind is local_durable_replay Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/events/feed/since?limit=50' TypeScript: const res = await fetch('https://api.0xinsider.com/api/v1/events/feed/since?cursor=' + encodeURIComponent(cursor), { headers: { Authorization: 'Bearer ' + key } }); const replay = await res.json(); cursor = replay.next_cursor; --- ### 11. GET /api/v1/webhooks Question: "Send 0xinsider events to my backend instead of polling" Supported methods: GET /api/v1/webhooks — List webhook destinations POST /api/v1/webhooks — Create a pending destination GET /api/v1/webhooks/{id} — Fetch one destination PATCH /api/v1/webhooks/{id} — Update name, url, event_types, or enabled DELETE /api/v1/webhooks/{id} — Disable a destination POST /api/v1/webhooks/{id}/verify — Activate with the one-time verification token POST /api/v1/webhooks/{id}/rotate-secret — Rotate and return a new signing secret once Create body: name — Human-readable endpoint name, max 100 chars url — Public HTTPS callback URL event_types — Array of public event types Public event types: whale_trades_inserted live_sports_updated whale_trader_synced large_positions_updated Response fields (object: webhook): id — Webhook destination ID name, url, event_types, status status — pending_verification, active, or disabled signing_secret — Returned only on create or rotate-secret verification.token — Returned only on create; expires after 24h retry_policy.max_attempts — 8 retry_policy.terminal_status — dead_letter Security: - URLs must be public HTTPS. The API rejects localhost, private IPs, .local, .internal, URL credentials, invalid ports, and non-HTTPS schemes. - Webhook payloads are signed with timestamped HMAC-SHA256. - Verify `${timestamp}.${rawBody}` using the signing secret and reject signatures older than 5 minutes. - Delivery idempotency keys are stable per endpoint/event pair. - Private browser/session alert, following, radar, and position-cache events are not public webhook event types. Signature headers: 0xinsider-timestamp: Unix timestamp seconds 0xinsider-signature: v1= 0xinsider-idempotency-key: stable delivery key Example create: curl -X POST -H 'Authorization: Bearer oxi_sk_live_...' -H 'Content-Type: application/json' \ -d '{"name":"Ops bot","url":"https://example.com/0xinsider","event_types":["whale_trades_inserted"]}' \ 'https://api.0xinsider.com/api/v1/webhooks' --- ### 12. GET /api/v1/reports/daily Daily report snapshot for a UTC date. Parameters: date (query, required) — YYYY-MM-DD Response fields (object: report_snapshot): kind — daily source_range.start_date / end_date — UTC source range snapshot.status — final or rolling completeness.status — complete, partial, or empty reconciliation.volume_kind — local_whale_activity_volume report.total_whale_trades / total_whale_volume — Whale-alert activity totals for the requested range Notes: - Snapshot metadata tells agents whether the source range is final or can still change. - Report whale volume comes from local whale_alerts.usdc_notional_num, not provider lifetime trader volume. Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/reports/daily?date=2026-04-18' --- ### 13. GET /api/v1/reports/weekly Weekly report snapshot for an ISO week or explicit UTC date range. Parameters: week (query, optional) — ISO YYYY-WW from/to (query, optional) — YYYY-MM-DD range; use both together Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/reports/weekly?week=2026-16' --- ### 14. GET /api/v1/reports/monthly Monthly report snapshot for a UTC month. Parameters: month (query, required) — YYYY-MM Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/reports/monthly?month=2026-04' --- ### 15. GET /api/v1/health No authentication required. Rate limit: 60 requests/minute per IP. Exceeding the cap returns 429 with Retry-After. Response fields (object: health): status — ok, degraded, down, or maintenance db — Database connectivity (boolean) cache — Redis connectivity (boolean) subsystems.background_jobs.status — ok, degraded, down, or not_checked subsystems.background_jobs.checked — whether heartbeat state was evaluated subsystems.background_jobs.total/healthy/stale/missing/invalid/unconfigured — public-safe heartbeat counts Notes: - Returns an ETag header; send If-None-Match to receive 304 Not Modified when unchanged - Background job health is aggregate-only and does not expose Redis keys, job names, raw errors, provider payloads, wallet addresses, or condition IDs --- ### 16. GET /api/v1/market/{condition_id}/snapshot Question: "Give me one reliable market card with prices, liquidity, and live context." Parameters: condition_id (path, required) — Raw provider-backed market key from /api/v1/markets/search or /api/v1/markets/explore. Do not pass prefixed market.id (mkt_...). Response fields (object: market_snapshot): market.condition_id — Raw market condition ID market.provider — polymarket or kalshi market.title / slug / page_slug / event_slug — Provider-backed identity fields when available outcomes[].label — Provider-backed outcome labels, fallback only to literal Yes/No outcomes[].token_id — Provider token ID when stored outcomes[].top_of_book — Cached CLOB best bid/ask when available, otherwise explicit unavailable liquidity.volume_usd / liquidity_usd / volume_24h_usd — Read-model liquidity fields sports.status — fresh, stale, not_live, or unavailable freshness.market_data.status — fresh, stale, or unavailable freshness.top_of_book.status — available or unavailable freshness.live_sports.status — fresh, stale, not_live, or unavailable Notes: - No request-time provider fanout; reads markets, market_canonical, CLOB best_bid_ask cache, and live_sports cache - Missing provider values stay null/unavailable; the endpoint never derives teams, sides, category, or identity from title/slug - Market data older than 24h is marked stale, not current Example: curl -H 'Authorization: Bearer oxi_sk_live_...' \ 'https://api.0xinsider.com/api/v1/market/0x123.../snapshot' --- ## MCP Server Two ways to connect: stdio (Node package) or remote HTTP (no install). ### Remote HTTP transport (no install) Endpoint: POST https://api.0xinsider.com/api/v1/mcp Also accepts GET for the optional server-to-client SSE stream. Protocol: MCP Streamable HTTP, protocolVersion 2025-11-25. Auth: Pass your API key as Authorization: Bearer oxi_sk_live_.... ?token= remains a legacy URL-only compatibility path, but prefer headers or stdio because URL secrets are easier to leak through logs and history. Rate limits, tier checks, and billing behave exactly like the REST API — the remote MCP endpoint runs through the same api_key middleware. Session handshake: send `initialize` first. The server mints an Mcp-Session-Id header; echo that on every follow-up request. Example initialize body: { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {} } The initialize response includes protocolVersion "2025-11-25", capabilities.tools.listChanged = false, and serverInfo { name: "0xinsider", version: }. Origin validation: if the request carries an Origin header it must match the 0xinsider allowlist or localhost; otherwise the server returns HTTP 403 with JSON-RPC error -32000. ### Stdio transport (npm package) npm package: @0xinsider/mcp Install/setup: npx -y @0xinsider/mcp init Detects local Claude Code or Cursor configs, plus installed Codex or Gemini CLI clients. Run via stdio: OXINSIDER_API_KEY=oxi_sk_live_... npx -y @0xinsider/mcp ### Per-client install notes Prefer the stdio package (`npx -y @0xinsider/mcp init`) for Claude Code, Cursor, Codex, and Gemini CLI. It stores the key in the local MCP env config instead of embedding it in a URL. For remote HTTP clients that support headers, configure: url: https://api.0xinsider.com/api/v1/mcp headers.Authorization: Bearer oxi_sk_live_... If a remote MCP client only supports a single URL, ?token= still works as a legacy compatibility path. Treat that as a last resort because URLs can be captured by shell history, browser history, proxy logs, and crash reports. Current MCP tools (9 read-only): get_trader — Evaluate a trader by wallet address or username (grade, strategy, P&L, categories) get_market_intel — Smart money flow for a specific market get_whale_trades — Recent large trades with signal scoring get_leaderboard — Top traders by grade, P&L, volume, win rate get_positions — Current positions-board feed with trader, market, value, side, P&L, and freshness context get_position_timeline — Per-market trader fills with running amount and average entry price search_markets — Find markets by keyword with status/category/platform metadata explore_markets — Browse whale-active markets with facets and grouped discovery entries get_insider_radar — Suspicious trading patterns and coordinated wallets All tools have readOnlyHint: true. Resources: oxinsider://docs/api — Full API reference from llms-full.txt oxinsider://docs/agents — Agent instructions and decision rules oxinsider://data/leaderboard — Current top 20 leaderboard oxinsider://data/whale-trades — Latest 20 whale trades Prompts: analyze_trader — Full trader assessment (grade, strategy, recent trades, risk factors) market_report — Smart money report for a market (flow, traders, suspicion) trading_signals — Find highest-conviction plays (cross-reference top traders) --- ## Common Workflows ### Find what top traders are buying 1. GET /api/v1/leaderboard?limit=5 (get top 5 traders) 2. GET /api/v1/whale-trades?min_grade=S (see their recent large trades) ### Analyze a specific market 1. GET /api/v1/markets/search?q=bitcoin (find the market) 2. GET /api/v1/market/{condition_id}/intel (smart money flow) 3. GET /api/v1/insider-radar (check for suspicious patterns) ### Discover whale-active markets GET /api/v1/markets/explore?sort=trending&limit=24 Filter by category or platform to build watchlists and dashboards. ### Build a whale alert bot Poll GET /api/v1/events/feed/since with your stored next_cursor to detect public retained changes. When type=whale_trades_inserted, call GET /api/v1/whale-trades?min_grade=A&limit=10 and use its cursor/IDs to avoid duplicates. ### Retry authenticated POST mutations safely Reuse the same Idempotency-Key only when repeating the exact same request body. Internal mutation routes that support this include /api/billing/checkout, /api/billing/portal, /api/keys, and /api/keys/regenerate. ### Evaluate a trader before copying GET /api/v1/trader/swisstony?expand=strategy&expand=categories&expand=quant_metrics Check grade, win_rate, strategy type, and Sharpe ratio. Full OpenAPI spec: https://0xinsider.com/api/v1/openapi.json Website: https://0xinsider.com