# Batch Get Market Intel Source: https://docs.0xinsider.com/api-reference/endpoint/batch-get-market-intel POST /api/v1/markets/intel/batch Returns smart-money market intelligence for 1-25 raw provider condition_id values. Results preserve request order, duplicate inputs return duplicate rows, and each item is charged one batch item unit before execution. Do not pass prefixed mkt_ IDs; use market.condition_id from search or explore. Fetch market intel for up to 25 markets in one call. Each item has the same shape as [Get Market Intel](/api-reference/endpoint/get-market-intel), plus a per-item `error` field when a condition ID fails. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"condition_ids": ["0xabc...", "0xdef...", "0x123..."]}' \ "https://api.0xinsider.com/api/v1/markets/intel/batch" ``` Each item costs one unit against the batch budget: a 25-market batch reserves 25 units. The top-level status stays `200` even when some items fail, so check `data[i].error` per item. See [Rate Limits](/rate-limits). # Batch Get Traders Source: https://docs.0xinsider.com/api-reference/endpoint/batch-get-traders POST /api/v1/traders/batch Returns trader intelligence for 1-25 wallet addresses or known usernames. Results preserve request order, duplicate inputs return duplicate rows, and each item is charged one batch item unit before execution. Unknown trader lookups return data with sync_status "unknown" matching the single trader endpoint. Fetch up to 25 trader profiles in one call. Each item has the same shape as [Get Trader](/api-reference/endpoint/get-trader), plus a per-item `error` field when an address fails. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"traders": ["0xabc...", "0xdef...", "swisstony"]}' \ "https://api.0xinsider.com/api/v1/traders/batch" ``` Each item costs one unit against the batch budget: a 25-address batch reserves 25 units. The top-level status stays `200` even when some items fail, so check `data[i].error` per item. See [Rate Limits](/rate-limits). # Create Webhook Source: https://docs.0xinsider.com/api-reference/endpoint/create-webhook POST /api/v1/webhooks Creates a pending HTTPS webhook destination. The response includes one-time signing_secret and verification.token values. Deliveries are not sent until the endpoint is verified. Register an endpoint to receive whale-trade and radar events as they happen. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Idempotency-Key: webhook-create-2026-06-01" \ -H "Content-Type: application/json" \ -d '{ "name": "Production webhook", "url": "https://api.yourapp.com/webhooks/0xinsider", "event_types": ["whale_trades_inserted"] }' \ "https://api.0xinsider.com/api/v1/webhooks" ``` The response includes a one-time signing secret. **Copy it now**. You can't retrieve it later. Use it to verify the `X-0xinsider-Signature` header on every delivery; see [Verify Webhook](/api-reference/endpoint/verify-webhook). If it leaks, [rotate it](/api-reference/endpoint/rotate-webhook-secret). Send `Idempotency-Key` when retrying after a timeout. The same key with the same body returns the original webhook; the same key with a different body returns `422`. # Delete Webhook Source: https://docs.0xinsider.com/api-reference/endpoint/delete-webhook DELETE /api/v1/webhooks/{id} Soft-deletes a webhook destination owned by the authenticated API key user. Existing delivery audit rows remain retained. Permanently remove a webhook. No further events are delivered to that URL, and the signing secret is invalidated. ```bash theme={null} curl -X DELETE \ -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Idempotency-Key: webhook-delete-2026-06-01" \ "https://api.0xinsider.com/api/v1/webhooks/wh_abc123" ``` To pause deliveries without losing the webhook, [update](/api-reference/endpoint/update-webhook) it to `enabled: false` instead. Send `Idempotency-Key` when retrying a delete. A matching retry returns the original response instead of deleting again. # Explore Markets Source: https://docs.0xinsider.com/api-reference/endpoint/explore-markets GET /api/v1/markets/explore Browse whale-active titled markets with category, platform, status, and keyword filters. Paginates visible discovery entries rather than raw market rows, returns live category/platform facets alongside grouped event clusters or standalone markets, and includes total on the first page only. Categories come straight from provider metadata (Polymarket Gamma, Kalshi) and facets are flat value/label/count rows. Browse whale-active markets. This is the "what's going on right now" feed, already filtered to titled, user-facing markets with real activity. Omit `q` for the full feed, or pass it to narrow by keyword. Grouped events (e.g. "Next US president by candidate") return one row per event with a primary market injected, so you always have something to link to. Common filters: * `q=bitcoin`: keyword search against market titles. * `category=crypto`: restrict to a category. * `platform=polymarket` or `platform=kalshi`: restrict to one platform. * `status=active`: exclude resolved markets. * `sort=volume`: sort by recent volume. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/markets/explore?category=crypto&status=active&limit=20" ``` Cursor-paginated. See [Pagination](/concepts/pagination). # Get API Discovery Source: https://docs.0xinsider.com/api-reference/endpoint/get-api-discovery GET /api/v1 Unauthenticated API-origin discovery document pointing agents to the canonical API base URL, full docs, web-origin OpenAPI spec, health check, and representative authenticated data routes. Discover the public V1 API surface without a key. `GET /api/v1` returns the API base URL, docs URL, OpenAPI URL, unauthenticated health URL, and representative authenticated data routes. ```bash theme={null} curl "https://api.0xinsider.com/api/v1" ``` Use it as the first probe for agents, SDK setup, and uptime checks that need the docs and health endpoints before authenticating. # Get Daily Report Snapshot Source: https://docs.0xinsider.com/api-reference/endpoint/get-daily-report-snapshot GET /api/v1/reports/daily Returns a dated daily whale-activity report snapshot with source_range, snapshot.status, completeness, and reconciliation metadata. Report whale volume is local whale-alert activity volume, not provider lifetime trader volume. The daily recap for a given date: top traders, biggest whale trades, smart-money rotations, pre-baked. Power morning-email digests, Slack briefs, or "what happened yesterday?" panels without rerunning every query. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/reports/daily?date=2026-05-08" ``` For longer windows, use [Weekly](/api-reference/endpoint/get-weekly-report-snapshot) or [Monthly](/api-reference/endpoint/get-monthly-report-snapshot). Snapshots carry trust metadata, so partial or unavailable sections are explicit. # Get Event Replay Since Source: https://docs.0xinsider.com/api-reference/endpoint/get-event-replay-since GET /api/v1/events/feed/since Returns durable public whale-trade intelligence events strictly after an opaque cursor backed by whale_alerts.id. This is a separate API-key contract from the browser/session /api/events/feed stream: browser-only and private alert, following, radar, and position patch events are excluded until they have a durable public outbox. Replay feed events you missed during a disconnection. Pass the timestamp (or event ID) of the last event you processed, and the response is everything after it. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/events/feed/since?since=2026-05-08T12:34:56Z&limit=100" ``` Cursor-paginated. Catch a worker back up after a crash or deploy without back-filling from the live feed. Pair with [Webhooks](/api-reference/endpoint/list-webhooks) if you'd rather not poll at all. # Get Insider Radar Source: https://docs.0xinsider.com/api-reference/endpoint/get-insider-radar GET /api/v1/insider-radar Suspicious trading patterns — pre-resolution accumulation, coordinated wallets, unusual timing. Cursor-paginated by suspicion score. Flags wallets that look like they know something the market doesn't: pre-resolution accumulation, well-timed entries, or one-sided conviction with no hedges. Each flag carries a `suspicion_score` and a reason. A high score is worth a closer look, not proof of wrongdoing. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/insider-radar?limit=20" ``` Cursor-paginated by score. See [Pagination](/concepts/pagination). To fetch one returned `rf_...` item again, use [Get Insider Radar Flag](/api-reference/endpoint/get-insider-radar-flag). # Get Insider Radar Flag Source: https://docs.0xinsider.com/api-reference/endpoint/get-insider-radar-flag GET /api/v1/insider-radar/{id} Returns one suspicious-trading radar flag by raw radar_flags.id or the rf_-prefixed id emitted by list responses. Fetch one radar flag by ID. Use either the raw `radar_flags.id` or the `rf_...` ID returned by insider-radar list responses. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/insider-radar/rf_123" ``` The response is a single `radar_flag` envelope with the same item shape as [Get Insider Radar](/api-reference/endpoint/get-insider-radar). # Get Leaderboard Source: https://docs.0xinsider.com/api-reference/endpoint/get-leaderboard GET /api/v1/leaderboard Returns ranked traders (grades S/A/B) sorted by score descending. Supports cursor pagination and optional category/strategy filters. Top traders by composite score. Only S, A, and B grades appear; see [Trader Grades](/concepts/grades). Filter by category (`crypto`, `politics`, `sports`) or strategy (`swing_trader`, and others). Some traders rank with no detected strategy, so `strategy_type` is nullable. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/leaderboard?limit=20&category=crypto" ``` Cursor-paginated. Pass `next_cursor` from one response as `cursor` on the next. See [Pagination](/concepts/pagination). # Get Market Intel Source: https://docs.0xinsider.com/api-reference/endpoint/get-market-intel GET /api/v1/market/{condition_id}/intel Smart money flow analysis for a specific market — net flow direction, whale trade count, buy/sell volumes, and top graded trader positions. Smart-money breakdown for one market: buy vs sell volume from graded traders, top positions, and which side has conviction. Pass either the raw provider-backed `condition_id` or the `mkt_...` market ID emitted by V1 responses. The API returns `400 bad_request` for known non-market prefixes such as `trd_`, `wt_`, or `rf_`. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/market/0xabc.../intel" ``` For multiple markets in one call, use [Batch Get Market Intel](/api-reference/endpoint/batch-get-market-intel). # Get Market Snapshot Source: https://docs.0xinsider.com/api-reference/endpoint/get-market-snapshot GET /api/v1/market/{condition_id}/snapshot Provider-first market card snapshot with canonical identity, outcome labels, cached top-of-book when available, liquidity, live sports context, and explicit freshness/unavailable states. One-shot view of a single market: price, volume, status, recent activity. Trust-metadata fields tell you which values are live and provider-backed and which are cached, partial, or unavailable. Pass either the raw provider-backed `condition_id` or the `mkt_...` market ID emitted by V1 responses. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/market/0xabc.../snapshot" ``` If a field comes back `unavailable`, treat it as missing. Don't flatten it to `0`. See [Trust metadata](/api-reference/introduction#trust-metadata). # Get Monthly Report Snapshot Source: https://docs.0xinsider.com/api-reference/endpoint/get-monthly-report-snapshot GET /api/v1/reports/monthly Returns a UTC monthly whale-activity report snapshot with source_range, completeness, and reconciliation metadata. The monthly recap: rolling-30-day leaderboard, category-rotation summary, and biggest realized P\&L by trader and by market. Use it for end-of-month digests and longer newsletters. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/reports/monthly?month=2026-05" ``` # Get position timeline Source: https://docs.0xinsider.com/api-reference/endpoint/get-position-timeline GET /api/v1/trader/{address}/position-timeline Returns every Polymarket fill for one trader in one market, newest first, with server-computed running_amount and running_avg_price. Only HOT and WARM tier traders are tracked; other traders return 404. running_avg_price is a buy-weighted entry basis (sells do not change the running average) matching Polymarket /positions avgPrice semantics. Cursor-paginated. An id-keyed alias exists at GET /api/v1/traders/{id}/position-timeline. Per-market fill history for one trader. Each fill carries a server-computed running amount and average entry price, so you can see how a position was built or unwound without recomputing it client-side. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/trader/0x863134d00841b2e200492805a01e1e2f5defaa53/position-timeline?condition_id=0xabc..." ``` If you have the integer internal trader ID instead of the wallet address, use [Get Position Timeline by ID](/api-reference/endpoint/get-position-timeline-by-id). # Get position timeline by ID Source: https://docs.0xinsider.com/api-reference/endpoint/get-position-timeline-by-id GET /api/v1/traders/{id}/position-timeline Id-keyed alias of GET /api/v1/trader/{address}/position-timeline. Response body is byte-identical for the same underlying trader. Useful for worker tasks and agent clients already holding a numeric traders.id. Same data as [Get Position Timeline](/api-reference/endpoint/get-position-timeline), keyed on the integer internal `traders.id` instead of a wallet address. Use it when you're paging through other API responses and already hold that numeric ID. # Get positions Source: https://docs.0xinsider.com/api-reference/endpoint/get-positions GET /api/v1/positions Returns the current positions-board feed backed by the wallet_positions mirror. Ordered by current_value_usd DESC with deterministic (wallet, condition_id, outcome_index) tiebreakers. Pre-reconcile rows (current_value_usd IS NULL) are excluded. Cursor-paginated. Every filter pushes into SQL. Current positions across traders or markets. Each row carries the trader, market, current value, side, and trust-metadata fields (source, freshness, completeness) so you can tell a live provider-backed value from a cached or partial one. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/positions?trader=0x863134d00841b2e200492805a01e1e2f5defaa53&limit=50" ``` For per-fill history (running amount and average entry price), use [Position Timeline](/api-reference/endpoint/get-position-timeline). When a value is unavailable from the provider, don't flatten it to `0`. See [Trust metadata](/api-reference/introduction#trust-metadata). # Get Trader Source: https://docs.0xinsider.com/api-reference/endpoint/get-trader GET /api/v1/trader/{address} Returns a trader's grade (S through F), P&L, win rate, and optional strategy/category data. The path accepts either an Ethereum wallet address, a known trader username, or a trd_-prefixed trader ID emitted by this API. Unknown lookups return sync_status "unknown" instead of 404. Full profile for a single wallet: grade, realized P\&L, win rate, strategy classification, category strengths, and current open positions. The path takes a raw wallet address (strip the `trd_` prefix) or a known trader username. Opt into heavy fields with repeated `expand` query params (`expand=strategy&expand=categories`). The legacy `expand[]` form still works. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/trader/0x863134d00841b2e200492805a01e1e2f5defaa53?expand=strategy&expand=categories" ``` Use this when you have an address (from the leaderboard or a whale trade) and want the full story. For multiple traders in one call, see [Batch Get Traders](/api-reference/endpoint/batch-get-traders). # Get Trader Export Snapshot Source: https://docs.0xinsider.com/api-reference/endpoint/get-trader-export-snapshot GET /api/v1/trader/{address}/export Returns export source-range, completeness, volume reconciliation, row-count estimate, and large-export policy for one trader. V1 is metadata-only; full raw dataset export remains on the internal streaming or async export route. One-shot export of everything 0xinsider knows about a trader: profile, positions, recent trades, category breakdown. Built for offline analysis or feeding into an LLM prompt. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/trader/0x863134d00841b2e200492805a01e1e2f5defaa53/export" ``` Each section carries trust metadata, so you can tell which fields are live provider-backed and which are cached or partial. # Get Usage Source: https://docs.0xinsider.com/api-reference/endpoint/get-usage GET /api/v1/usage Returns the authenticated caller sliding-window request budget and UTC-day usage. This endpoint is authenticated and does not increment the primary Redis rate-limit counter or log itself into the API usage table; it is separately throttled at 100 reads/minute per user to protect the usage-count query. Read your current request budget without spending primary quota. Returns the live per-minute primary limiter window plus UTC-day usage. It does not increment the primary request counter and does not log itself into daily usage. The endpoint has its own 100 reads/minute per-user guard; a 429 here is a backoff signal, not proof you spent primary quota. The daily `limit` and `remaining` fields are `null` because V1 has no daily hard cap. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/usage" ``` Check quota here instead of polling a data endpoint to guess your remaining budget. # Get Webhook Source: https://docs.0xinsider.com/api-reference/endpoint/get-webhook GET /api/v1/webhooks/{id} Returns one webhook destination owned by the authenticated API key user. Inspect a single registered webhook: its URL, subscribed events, active flag, and recent delivery status. The signing secret is not returned; it is shown once at create time. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/webhooks/wh_abc123" ``` # Get Weekly Report Snapshot Source: https://docs.0xinsider.com/api-reference/endpoint/get-weekly-report-snapshot GET /api/v1/reports/weekly Returns a weekly whale-activity report snapshot. Pass either from/to UTC dates or an ISO YYYY-WW week token. The response identifies closed ranges as final and current ranges as rolling. The weekly recap snapshot: top movers, sustained-flow markets, leaderboard shifts, pre-baked for the requested week. Same shape as the [daily report](/api-reference/endpoint/get-daily-report-snapshot), rolled up over seven days. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/reports/weekly?week_of=2026-05-04" ``` `week_of` accepts any date inside the target week. # Get Whale Trade Source: https://docs.0xinsider.com/api-reference/endpoint/get-whale-trade GET /api/v1/whale-trades/{id} Returns one whale trade by raw whale_alerts.id or the wt_-prefixed id emitted by list and history responses. Fetch one whale trade by ID. Use either the raw `whale_alerts.id` or the `wt_...` ID returned by whale-trade list and history responses. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades/wt_123" ``` The response is a single `whale_trade` envelope with the same item shape as [Get Whale Trades](/api-reference/endpoint/get-whale-trades). # Get Whale Trades Source: https://docs.0xinsider.com/api-reference/endpoint/get-whale-trades GET /api/v1/whale-trades Returns recent large trades with signal scoring. Filter by size, category, or trader grade. Filters are applied before pagination, and every request uses SQL-backed limit + 1 pagination so has_more and next_cursor reflect the filtered result set. Cursor-paginated, newest first. Market categories come from provider-backed market_canonical identity. Recent large trades, newest first, each with the trader's grade and a signal score. Useful filters: * `min_grade=A`: only trades from S/A-grade traders (set `B` to widen). * `category=crypto`: restrict to a market category. * `side=buy`: `buy` or `sell`. * `min_size_usd=10000`: floor on trade size. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades?min_grade=A&category=crypto&side=buy&limit=50" ``` Cursor-paginated by timestamp. For a fixed time range (backtests, recap reports), use [Whale Trades History](/api-reference/endpoint/get-whale-trades-history). To fetch one returned `wt_...` item again, use [Get Whale Trade](/api-reference/endpoint/get-whale-trade). # Get Whale Trades History Source: https://docs.0xinsider.com/api-reference/endpoint/get-whale-trades-history GET /api/v1/whale-trades/history Returns historical whale trades from local whale_alerts rows, not request-time provider fetches. Filter by condition_id, trader, category, minimum grade, platform, and RFC3339 from/to windows. All filters are pushed into SQL before LIMIT, every request uses SQL-backed limit + 1 pagination, and results are ordered newest first by traded_at desc, id desc. Metadata exposes local_replay source and best_effort completeness. Bounded historical whale-trade ranges. Built for backtests, recap reports, and warming a cache after a deploy. For the live feed, use [Get Whale Trades](/api-reference/endpoint/get-whale-trades). ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades/history?from=2026-04-01T00:00:00Z&to=2026-04-30T23:59:59Z&min_grade=A&limit=100" ``` Responses carry trust metadata, so you can tell provider-backed from reconciled or partial ranges. See [Trust metadata](/api-reference/introduction#trust-metadata). # Health Check Source: https://docs.0xinsider.com/api-reference/endpoint/health GET /api/v1/health Returns API health status. No authentication required. Limited to 60 requests per minute per IP. A liveness probe. Returns `200` with database and cache status when the API is up. No auth required, so it works as a smoke test from CI or a status dashboard. ```bash theme={null} curl https://api.0xinsider.com/api/v1/health ``` ```json theme={null} { "object": "health", "data": { "status": "ok", "db": true, "cache": true }, "meta": { "request_id": "req_abc123", "cached": false } } ``` # List Webhooks Source: https://docs.0xinsider.com/api-reference/endpoint/list-webhooks GET /api/v1/webhooks Returns webhook destinations owned by the authenticated API key user. Disabled endpoints are omitted. List every webhook registered on your account. Each entry has the destination URL, subscribed events, delivery status, and signature-verification metadata. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/webhooks" ``` ## The webhook lifecycle * [Create](/api-reference/endpoint/create-webhook) a webhook with the URL and event types you care about. * [Get](/api-reference/endpoint/get-webhook) one to inspect its current state. * [Update](/api-reference/endpoint/update-webhook) to change URL, events, or active flag. * [Delete](/api-reference/endpoint/delete-webhook) when you no longer need it. * [Verify](/api-reference/endpoint/verify-webhook) signed delivery on your side using HMAC. * [Rotate secret](/api-reference/endpoint/rotate-webhook-secret) if a signing secret leaks. # Redirect OpenAPI Spec Source: https://docs.0xinsider.com/api-reference/endpoint/redirect-api-openapi-spec GET /api/v1/openapi.json Unauthenticated API-origin compatibility redirect to the canonical web-origin OpenAPI JSON document at https://0xinsider.com/api/v1/openapi.json. Resolve the canonical OpenAPI document from the API origin. Returns a temporary redirect to the web-origin spec at `https://0xinsider.com/api/v1/openapi.json`. One spec, one owner, still discoverable from the API origin. ```bash theme={null} curl -I "https://api.0xinsider.com/api/v1/openapi.json" ``` Use the `Location` header as the canonical OpenAPI URL for code generation and docs tooling. # Remote MCP Source: https://docs.0xinsider.com/api-reference/endpoint/remote-mcp POST /api/v1/mcp Model Context Protocol (MCP) Streamable HTTP transport. Accepts a JSON-RPC 2.0 request and returns a JSON-RPC response. Supported methods: initialize, notifications/initialized, ping, tools/list, tools/call. Remote MCP exposes 21 read-only tools for public V1 read operations: get_leaderboard, get_trader, batch_get_traders, get_whale_trades, get_whale_trades_history, get_market_intel, batch_get_market_intel, get_market_snapshot, get_insider_radar, get_positions, get_position_timeline, get_position_timeline_by_id, search_markets, explore_markets, get_event_replay_since, list_webhooks, get_webhook, get_daily_report_snapshot, get_weekly_report_snapshot, get_monthly_report_snapshot, get_trader_export_snapshot. Webhook create/update/delete/verify/rotate operations are intentionally not exposed as remote MCP tools. The remote endpoint advertises tools only; it does not implement resources/list, resources/read, prompts/list, or prompts/get. Each tool dispatches to the matching /api/v1/* handler in-process so auth, rate limits, and payload shape match. Auth should use Authorization: Bearer . ?token= remains a legacy compatibility path for URL-only MCP clients, but URL secrets can land in shell history, browser history, and logs, so prefer headers or the stdio package. Mcp-Session-Id is minted on initialize and echoed on every response. Origin header, when present, is validated against the 0xinsider + localhost allowlist. Hosted, streamable HTTP MCP endpoint. Use it when your agent can't spawn a local `npx` subprocess: a serverless function, a browser-based agent, or a hosted automation runtime. Remote MCP exposes the 21 read-only V1 data operations below as tools. Each tool dispatches to the matching `/api/v1/*` handler in-process, so auth, rate limits, and payload contracts match direct REST calls. Meta endpoints (`/usage`, `/health`) and webhook mutations are not exposed as tools. The remote endpoint is tools-only. It supports `initialize`, `notifications/initialized`, `ping`, `tools/list`, and `tools/call`; it does not implement resources or prompts. Current tools: * `get_leaderboard` * `get_trader` * `batch_get_traders` * `get_whale_trades` * `get_whale_trades_history` * `get_market_intel` * `batch_get_market_intel` * `get_market_snapshot` * `get_insider_radar` * `get_positions` * `get_position_timeline` * `get_position_timeline_by_id` * `search_markets` * `explore_markets` * `get_event_replay_since` * `list_webhooks` * `get_webhook` * `get_daily_report_snapshot` * `get_weekly_report_snapshot` * `get_monthly_report_snapshot` * `get_trader_export_snapshot` ## Authentication Prefer the header form: ```bash theme={null} curl -X POST \ -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' \ https://api.0xinsider.com/api/v1/mcp ``` A `?token=...` query parameter is still available for URL-only clients but is **legacy**. URL secrets leak into shell history, browser history, proxies, and logs. Use headers wherever you can. For the streaming response, see [Remote MCP Stream](/api-reference/endpoint/remote-mcp-stream). # Remote MCP stream Source: https://docs.0xinsider.com/api-reference/endpoint/remote-mcp-stream GET /api/v1/mcp Opens a text/event-stream connection for server-initiated notifications as described in the MCP Streamable HTTP transport. The endpoint currently sends no notifications — clients that only care about request/response use POST. Open the server-to-client streaming channel for [Remote MCP](/api-reference/endpoint/remote-mcp). Pass the `Mcp-Session-Id` from the `initialize` call to attach to your session, plus `Authorization: Bearer ...` if your client supports headers. ```bash theme={null} curl -N \ -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Mcp-Session-Id: $SESSION_ID" \ https://api.0xinsider.com/api/v1/mcp ``` This is the stdio analog over HTTP. Hold the connection open to receive streamed tool responses, progress events, and resource updates. # Rotate Webhook Secret Source: https://docs.0xinsider.com/api-reference/endpoint/rotate-webhook-secret POST /api/v1/webhooks/{id}/rotate-secret Rotates the endpoint signing secret and returns the new signing_secret once in the response. Generate a fresh signing secret for a webhook. The response includes the new secret **once**, so copy it immediately. The old secret stops working the moment this call returns. Deploy the new secret to your verification code before you rotate. ```bash theme={null} curl -X POST \ -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Idempotency-Key: webhook-rotate-2026-06-01" \ "https://api.0xinsider.com/api/v1/webhooks/wh_abc123/rotate-secret" ``` Rotate right away if a secret leaks (committed to git, exposed in a log, sent in a screenshot). Use `Idempotency-Key` when retrying a rotate after a timeout. A matching retry returns the same one-time secret response instead of rotating again. # Search Markets Source: https://docs.0xinsider.com/api-reference/endpoint/search-markets GET /api/v1/markets/search Search prediction markets by keyword. Returns representative market matches with status, category, and platform metadata. Cursor pagination advances over grouped market results rather than raw sub-market rows. Keyword search across Polymarket and Kalshi markets. Best when you know what you want and need the raw `condition_id` for other endpoints. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/markets/search?q=trump&category=politics&status=active" ``` Pass the returned `condition_id` or returned `mkt_...` market ID into [Market Intel](/api-reference/endpoint/get-market-intel) or [Market Snapshot](/api-reference/endpoint/get-market-snapshot). For browsing rather than searching, use [Explore Markets](/api-reference/endpoint/explore-markets). # Smart Money Flows Source: https://docs.0xinsider.com/api-reference/endpoint/smart-money-flows GET /api/v1/markets/smart-money-flows Ranks markets by absolute net S/A/B-grade whale flow over a requested timeframe. Use this discovery endpoint to answer where smart money is flowing before drilling into a specific market with /api/v1/market/{condition_id}/intel. Pagination is anchored by an opaque cursor carrying the first page as_of timestamp so new whale trades do not reorder page 2. Rank markets by where graded traders are putting money. This is the "where is smart money flowing right now?" feed: it aggregates whale flow from S, A, and B grade traders and ranks markets by absolute net flow over your chosen window. Use it for discovery, before you know a `condition_id`. Once you have a market, follow up with [Get Market Intel](/api-reference/endpoint/get-market-intel) for the single-market breakdown. Common filters: * `timeframe=24h` — lookback window (`1h`, `4h`, `24h`, or `7d`). * `min_grade=B` — minimum trader grade in the flow. The default `B` means S, A, and B graded traders only. * `platform=polymarket` or `platform=kalshi`. * `direction=YES` or `direction=NO` — restrict to one side of the flow. * `category=crypto` — case-insensitive exact match against the provider-backed market category. ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/markets/smart-money-flows?timeframe=7d&min_grade=B&limit=10" ``` Cursor-paginated. The cursor is anchored to the first page's `as_of` timestamp, so new whale trades do not reorder later pages. See [Pagination](/concepts/pagination). # Update Webhook Source: https://docs.0xinsider.com/api-reference/endpoint/update-webhook PATCH /api/v1/webhooks/{id} Updates name, HTTPS URL, event types, or enabled state. URL changes force pending_verification and return a new verification token. Change a webhook's destination URL, subscribed events, or active flag without recreating it. Promote a staging URL to production, or pause delivery during maintenance without losing the registration. ```bash theme={null} curl -X PATCH \ -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Idempotency-Key: webhook-update-2026-06-01" \ -H "Content-Type: application/json" \ -d '{"enabled": false}' \ "https://api.0xinsider.com/api/v1/webhooks/wh_abc123" ``` The signing secret is not affected by `PATCH`. To change it, use [Rotate Webhook Secret](/api-reference/endpoint/rotate-webhook-secret). Use `Idempotency-Key` when retrying the same update body. A matching retry replays the original response; a different body with the same key returns `422`. # Verify Webhook Source: https://docs.0xinsider.com/api-reference/endpoint/verify-webhook POST /api/v1/webhooks/{id}/verify Activates a pending webhook destination when the one-time verification token matches and has not expired. Send a signed test payload to your webhook URL to confirm signature verification on your side before live deliveries start. ```bash theme={null} curl -X POST \ -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/webhooks/wh_abc123/verify" ``` The webhook receives a `verify.test` event with an `X-0xinsider-Signature` header. Compute `HMAC_SHA256(secret, raw_body)` on your side and compare in constant time. Reject deliveries with mismatched signatures. # API Reference Source: https://docs.0xinsider.com/api-reference/introduction What every 0xinsider endpoint shares: base URL, auth, envelope, IDs, rate limits, and trust metadata. ## Base URL ``` https://api.0xinsider.com/api/v1/ ``` ## Authentication Every endpoint except `/health` needs a Bearer token: ```bash theme={null} Authorization: Bearer oxi_sk_live_... ``` Generate yours at [0xinsider.com/developers](https://0xinsider.com/developers). Full details in [Authentication](/authentication). ## Response envelope Single-resource endpoints return: ```json theme={null} { "object": "trader", "data": { ... }, "meta": { "request_id": "req_550e8400", "cached": false } } ``` List endpoints add pagination fields: ```json theme={null} { "object": "list", "data": [ ... ], "has_more": true, "next_cursor": "97.94_0x863...", "meta": { "request_id": "req_550e8400", "cached": false } } ``` | Field | Meaning | | -------------------------- | ------------------------------------------------------------------------------- | | `object` | Shape of `data`. A singular type (`trader`, `market`, `health`, ...) or `list`. | | `data` | The payload: an object or an array. | | `meta.request_id` | Give us this when you contact support. | | `meta.cached` | `true` when the response came from cache. | | `has_more` / `next_cursor` | Present on list responses. See [Pagination](/concepts/pagination). | Errors share the same envelope, with `"object": "error"`. See [Errors](/errors). ## Prefixed IDs Every ID is prefixed with its type, so it's self-describing in logs and chat transcripts. | Entity | Prefix | Example | | ----------- | ------ | -------------------- | | Trader | `trd_` | `trd_0xabc123def456` | | Market | `mkt_` | `mkt_0x789condition` | | Whale trade | `wt_` | `wt_12345` | | Radar flag | `rf_` | `rf_67890` | | Request | `req_` | `req_550e8400` | Trader path endpoints accept raw addresses and valid `trd_...` wallet IDs. Market path endpoints such as `/market/{condition_id}/intel` and `/market/{condition_id}/snapshot` accept either raw provider-backed condition IDs or the `mkt_...` IDs emitted by V1 responses. Single-record whale trade and radar endpoints accept raw integer IDs or their `wt_...` / `rf_...` forms. ## Rate limits 100 requests per minute per user, sliding window. Batch endpoints have an additional 100-item-unit-per-minute budget. `GET /api/v1/usage` does not spend primary quota, but it has its own 100 reads/minute guard. | Header | Meaning | | ----------------------------- | ------------------------------------------------ | | `X-RateLimit-Limit` | Maximum requests per window (`100`). | | `X-RateLimit-Remaining` | How many you have left in the current window. | | `X-RateLimit-Reset` | Unix timestamp (seconds) when the window resets. | | `X-Request-Cost` | Item units this single batch call charged. | | `X-Batch-RateLimit-Limit` | Max batch item units per minute. | | `X-Batch-RateLimit-Remaining` | Batch item units remaining. | | `X-Batch-RateLimit-Reset` | Unix timestamp when the batch window resets. | | `Retry-After` | Seconds to wait. Only on `429`. | See [Rate Limits](/rate-limits) for backoff patterns. ## Browser CORS Public REST `/api/v1/*` endpoints, excluding remote MCP (`/api/v1/mcp`), are callable from third-party browser origins with `Authorization: Bearer ...`. Do not send cookies or `credentials: "include"` on public API calls. Remote MCP at `/api/v1/mcp` is also non-credentialed, but still validates `Origin` against the 0xinsider/localhost allowlist per the MCP Streamable HTTP DNS-rebinding guidance. Allowed public request headers: * `Authorization` * `Content-Type` * `If-None-Match` * `Mcp-Session-Id` Browser JavaScript may read these response headers: * `X-RateLimit-Limit` * `X-RateLimit-Remaining` * `X-RateLimit-Reset` * `Retry-After` * `ETag` * `X-Request-Id` * `X-Request-Cost` * `X-Batch-RateLimit-Limit` * `X-Batch-RateLimit-Remaining` * `X-Batch-RateLimit-Reset` * `Mcp-Session-Id` * `X-Mcp-Error-Code` Credentialed first-party routes such as `/api/keys`, `/api/billing`, and auth endpoints remain restricted to configured 0xinsider origins. ## Trust metadata Newer builder endpoints (snapshots, history ranges, batch reads, reports) attach metadata to provider-owned values so you can tell provider-backed, cached, partial, stale, and unavailable data apart. Per value: * `source`: where the value came from (`provider`, `cache`, `computed`). * `freshness`: how stale it is (an ISO timestamp or `live`). * `reconciliation`: whether it's been cross-checked against the source of truth. * `completeness`: `full`, `partial`, or `unavailable`. Rule of thumb: **don't flatten unavailable values into `0`, `[]`, or `{}`.** Read the metadata and surface "unavailable" to your consumer instead of inventing a zero. Provider data that quietly becomes `0` causes silent bugs downstream. # Authentication Source: https://docs.0xinsider.com/authentication API keys, headers, and what to do if a key leaks. Every request except `/health` uses a Bearer token: ```bash theme={null} Authorization: Bearer oxi_sk_live_... ``` ## The key | Property | Value | | ----------------------- | ------------------------------------------------------------ | | Format | `oxi_sk_live_` + 64 hex chars (76 chars total) | | Storage on our side | HMAC-SHA256 hash. We never store plaintext. | | Active keys per account | 1. Regenerating revokes the old key. | | Where to generate | [0xinsider.com/developers](https://0xinsider.com/developers) | The key shows **once**, at generation. After that the dashboard shows only the prefix (`oxi_sk_live_XXXX`) so you can identify it. ## Generate a key 1. Log in at [0xinsider.com](https://0xinsider.com). 2. Open [Developers](https://0xinsider.com/developers). 3. Click **Generate Key**. 4. Copy it immediately. ## Common mistakes Wrong: ``` Authorization: oxi_sk_live_... ``` Right: ``` Authorization: Bearer oxi_sk_live_... ``` Without the `Bearer` prefix you get `401 invalid_api_key`. The full key is 76 characters. Anything shorter is a partial copy. A valid key with an expired subscription returns `402 subscription_required`. Re-subscribe at [pricing](https://0xinsider.com/pricing); the same key resumes. Regenerating revokes the old key in the same call. Update every place it lives: `.env` files, deployed secrets, MCP configs. ## If a key leaks Treat it like any production secret: 1. Go to [Developers](https://0xinsider.com/developers). 2. Click **Regenerate Key**. The old key dies immediately. 3. Roll the new key into every consumer: bots, MCP configs, CI secrets, dashboards. ## Key management endpoints These manage *your own* keys from the dashboard. They use the session cookie (JWT), not an API key, so you can't call them from a script with `oxi_sk_live_...`. | Action | Method | Endpoint | | ---------- | -------- | ---------------------- | | Create key | `POST` | `/api/keys` | | List keys | `GET` | `/api/keys` | | Revoke key | `DELETE` | `/api/keys/{id}` | | Regenerate | `POST` | `/api/keys/regenerate` | ## A subscription-blocked response ```json theme={null} { "object": "error", "error": { "code": "subscription_required", "message": "Active Insider subscription required.", "doc_url": "https://docs.0xinsider.com/authentication" } } ``` # API changelog Source: https://docs.0xinsider.com/changelog Externally visible changes to the 0xinsider REST API. This changelog tracks externally visible REST API changes only. Documentation-only edits are intentionally excluded. Added [`GET /api/v1/markets/smart-money-flows`](/api-reference/endpoint/smart-money-flows), a ranked discovery feed that answers where smart money is flowing before you know a `condition_id`. It ranks markets by absolute net flow from S, A, and B grade traders over a `1h`, `4h`, `24h`, or `7d` window, with `platform`, `category`, `min_grade`, and `direction` filters. Pagination uses an opaque cursor anchored to the first page's `as_of`, so new whale trades do not reorder later pages. Drill into a single market with [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel). **Remote MCP read parity.** [`POST /api/v1/mcp`](/api-reference/endpoint/remote-mcp) now exposes 21 read-only tools through `tools/list`, covering the public V1 reads: batch reads, history, event replay, webhook reads, reports, market snapshots, and trader exports. Webhook mutations stay REST-only, and the endpoint is tools-only (no resources or prompts). **See your usage.** Added [`GET /api/v1/usage`](/api-reference/endpoint/get-usage), an authenticated peek at your current per-minute limiter window and UTC-day usage. It doesn't spend primary quota, but has its own 100 reads/minute guard. **Cheaper polling, safe retries.** Deterministic reads now support `ETag` / `If-None-Match` conditional GETs, so an unchanged read returns `304` with no body. Webhook create/update/delete/rotate accept an `Idempotency-Key`. **Easier discovery.** Added [`GET /api/v1`](/api-reference/endpoint/get-api-discovery) (an API discovery document) and [`GET /api/v1/openapi.json`](/api-reference/endpoint/redirect-api-openapi-spec) (a redirect to the canonical OpenAPI spec). Operation IDs are now codegen-friendly, with examples, code samples, and response-header metadata. **Round-trippable IDs.** Market Intel and Market Snapshot now accept the `mkt_...` market ID or the raw `condition_id`. New [`GET /api/v1/whale-trades/{id}`](/api-reference/endpoint/get-whale-trade) and [`GET /api/v1/insider-radar/{id}`](/api-reference/endpoint/get-insider-radar-flag) dereference a single `wt_...` / `rf_...` record. Non-market prefixes return `400 bad_request`. [`POST /api/v1/mcp`](/api-reference/endpoint/remote-mcp) now exposes nine read-only tools through `tools/list`. The new tools are `get_positions`, `get_position_timeline`, and `explore_markets`. Each dispatches to the existing public REST handler, so MCP clients receive the same auth, pagination, and payload contracts as direct REST callers. Added task-shaped builder endpoints for lower-call-count integrations: * [`POST /api/v1/traders/batch`](/api-reference/endpoint/batch-get-traders) * [`POST /api/v1/markets/intel/batch`](/api-reference/endpoint/batch-get-market-intel) * [`GET /api/v1/whale-trades/history`](/api-reference/endpoint/get-whale-trades-history) * [`GET /api/v1/events/feed/since`](/api-reference/endpoint/get-event-replay-since) * [`GET /api/v1/market/{condition_id}/snapshot`](/api-reference/endpoint/get-market-snapshot) * [`GET /api/v1/reports/daily`](/api-reference/endpoint/get-daily-report-snapshot), [`weekly`](/api-reference/endpoint/get-weekly-report-snapshot), and [`monthly`](/api-reference/endpoint/get-monthly-report-snapshot) * [`GET /api/v1/trader/{address}/export`](/api-reference/endpoint/get-trader-export-snapshot) * [`GET /api/v1/webhooks`](/api-reference/endpoint/list-webhooks) plus webhook create, read, update, delete, verify, and rotate-secret operations Batch endpoints expose item-weighted cost headers. New snapshot/history/report payloads document source, freshness, completeness, and reconciliation semantics so clients can distinguish provider-backed, cached, partial, stale, and unavailable values. Added [TypeScript client guidance](/integrations/typescript-client) for the repo-owned client source in `web/src/lib/api-client`. The client source is drift-tested against OpenAPI and handles bearer auth, path params, repeated query params, JSON bodies, and V1 error envelopes. It is not a published npm package yet. [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel) now returns a clearer `400 bad_request` when callers pass a prefixed `market.id` value such as `mkt_...` instead of the raw `condition_id`. Use [`GET /api/v1/markets/search`](/api-reference/endpoint/search-markets) first, then pass the returned `condition_id` into the Market Intel path. [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader) now accepts a known trader username in the path in addition to an Ethereum wallet address. Heavy trader fields can be requested with repeated `expand` query params, and the legacy `expand[]` form remains supported for existing clients. [`GET /api/v1/leaderboard`](/api-reference/endpoint/get-leaderboard) now safely returns traders without a classified strategy. Clients should treat `strategy_type` as nullable for ranked traders without a strategy classification. [`GET /api/v1/markets/explore`](/api-reference/endpoint/explore-markets) no longer returns untitled markets. This tightens the response set to titled, user-facing markets only. [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader) now returns the canonical realized P\&L from the `realized_pnl` source-of-truth field. The `pnl.realized` field stopped deriving realized P\&L from an inconsistent approximation. Added [`GET /api/v1/markets/explore`](/api-reference/endpoint/explore-markets) for cursor-paginated market discovery. The endpoint supports category, status, platform, and text filters, plus primary-market injection so grouped events include a main market when one exists. Launched the first public developer API: * [`GET /api/v1/trader/{address}`](/api-reference/endpoint/get-trader) * [`GET /api/v1/whale-trades`](/api-reference/endpoint/get-whale-trades) * [`GET /api/v1/leaderboard`](/api-reference/endpoint/get-leaderboard) * [`GET /api/v1/markets/search`](/api-reference/endpoint/search-markets) * [`GET /api/v1/market/{condition_id}/intel`](/api-reference/endpoint/get-market-intel) * [`GET /api/v1/insider-radar`](/api-reference/endpoint/get-insider-radar) * [`GET /api/v1/health`](/api-reference/endpoint/health) The initial contract shipped with Bearer auth, `expand[]`, cursor pagination, prefixed IDs, and rate-limit headers. Money values and scores are truncated to 2 decimal places across V1 responses. Prices and rates are truncated to 4 decimal places. # Trader Grades Source: https://docs.0xinsider.com/concepts/grades What S, A, B, C, D, F mean, with real profile examples. Every trader gets one letter grade. It answers one question: should you pay attention to this wallet? Grades show up on the leaderboard, on every trader profile, and inside every whale trade object. ## The scale | Grade | One-line meaning | On the leaderboard? | | ----- | -------------------------------------------------------------------- | ------------------- | | **S** | Elite. Years of evidence, outsized P\&L, high win rate, real volume. | Yes | | **A** | Strong. Consistently profitable, well-diversified across markets. | Yes | | **B** | Above average. Solid recent track record, smaller sample. | Yes | | **C** | Roughly breakeven. Not a clear signal. | No | | **D** | Net losing across the sample. | No | | **F** | Persistently losing. Often coin-flip or chasing resolved markets. | No | The leaderboard ranks only S, A, and B. Those are the wallets worth following. ## What goes into the grade The score is a composite (0-100) of five inputs: 1. **Realized P\&L**: actual profit from closed positions, not unrealized markings. 2. **Win rate**: share of markets that resolved in their favor. 3. **Volume**: total traded size. More volume means more signal per trade. 4. **Market count**: distinct markets they have touched (diversification). 5. **Recency**: penalizes wallets that have not traded in a long time. Score thresholds assign the letter. Only B or better makes the leaderboard. ## Two real profiles, side by side ### S-grade: deep history, sustained edge ```json theme={null} { "object": "trader", "data": { "id": "trd_0x863134d00841b2e200492805a01e1e2f5defaa53", "username": "RepTrump", "grade": "S", "score": 97.94, "pnl": 7532409.67, "win_rate": 1.0, "markets_traded": 28, "strategy_type": "swing_trader", "best_category": "politics" } } ``` Very high realized P\&L, near-perfect win rate, a classifiable strategy, a clear category strength. ### C-grade: noisy and small ```json theme={null} { "object": "trader", "data": { "id": "trd_0xc111...", "username": null, "grade": "C", "score": 42.10, "pnl": 318.55, "win_rate": 0.5238, "markets_traded": 21, "strategy_type": null, "best_category": null } } ``` P\&L near breakeven, a coin-flip win rate, no detectable strategy. Visible in the API, but not on the leaderboard. ## Using grades in the API ### Filter whale trades by grade Only see trades from A-grade or better: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades?min_grade=A&limit=50" ``` `min_grade` accepts `S`, `A`, `B`. Setting `min_grade=A` returns S **and** A. ### Filter the leaderboard by strategy Pull only S/A/B-grade swing traders: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/leaderboard?strategy=swing_trader" ``` Some traders make the leaderboard but lack a classifiable strategy. Their `strategy_type` is `null`, so treat the field as nullable when filtering client-side. ### Combine grade + category What are A-grade or better crypto traders buying right now? ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades?min_grade=A&category=crypto&side=buy&limit=50" ``` ## A note on null strategies A leaderboard trader without a strategy classification just means we haven't detected a stable pattern yet. They are still a graded trader. Don't filter them out unless you actually need a labeled strategy. # Number Formatting Source: https://docs.0xinsider.com/concepts/number-formatting How numeric values are formatted in API responses. Numbers come back as plain JSON numbers, not strings. Floating-point values are **truncated**, not rounded, at the API edge. The displayed value never overstates the real one. ## Precision | Field type | Decimals | Example | | ------------------------------------ | -------- | ------------------- | | Money (`pnl`, `volume`, `size_usd`) | 2 | `7532409.67` | | Scores (`score`, `suspicion_score`) | 2 | `97.94` | | Rates (`win_rate`, `daily_win_rate`) | 4 | `0.4545` (= 45.45%) | | Prices | 4 | `0.8899` | ## Truncated, not rounded `97.9488...` becomes `97.94`, not `97.95`. `-12.345` becomes `-12.34`. Always toward zero. Need stricter precision for accounting? Compute from the source data. The edge value is display-safe, not accounting-grade. ## Integer fields These are exact integers. No decimals, no truncation: * `markets_traded` * `rank` * `whale_trade_count` ## Nulls and `unavailable` Many fields are nullable (e.g. `strategy_type`, `best_category`). Treat them as nullable even when an endpoint usually populates them. Newer builder endpoints also return **trust metadata**: explicit `unavailable` or `partial` markers when a provider-owned value can't be returned at request time. Don't convert these into `0`, `[]`, or `{}`. Read the metadata field and treat the value as missing. # Pagination Source: https://docs.0xinsider.com/concepts/pagination Cursor-based pagination, with a full loop in JS and Python. Every list endpoint uses **cursor pagination**. No `offset`, no `page` number. Cursors stay stable as long as the sort order holds, so they beat offsets on live data. ## The shape A list response looks like this: ```json theme={null} { "object": "list", "data": [ /* up to `limit` items */ ], "has_more": true, "next_cursor": "95.85_0x885783760858e1bd5dd09a3c3f916cfa251ac270", "meta": { "request_id": "req_abc123", "cached": false } } ``` To get the next page, pass `next_cursor` back as the `cursor` query param: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/leaderboard?limit=20&cursor=95.85_0x885..." ``` Repeat until `has_more` is `false`. ## Parameters | Parameter | Type | Default | Max | | --------- | ------- | ------- | ----- | | `limit` | integer | `20` | `100` | | `cursor` | string | — | — | ## Full loop, end to end This pulls every page of the leaderboard. ```javascript JavaScript theme={null} const KEY = process.env.OXINSIDER_API_KEY; const headers = { Authorization: `Bearer ${KEY}` }; async function listAll(path, params = {}) { const items = []; let cursor; do { const qs = new URLSearchParams({ limit: "100", ...params }); if (cursor) qs.set("cursor", cursor); const res = await fetch( `https://api.0xinsider.com/api/v1${path}?${qs}`, { headers } ); const body = await res.json(); items.push(...body.data); cursor = body.has_more ? body.next_cursor : undefined; } while (cursor); return items; } const leaders = await listAll("/leaderboard"); console.log(`Fetched ${leaders.length} traders`); ``` ```python Python theme={null} import os, requests BASE = "https://api.0xinsider.com/api/v1" H = {"Authorization": f"Bearer {os.environ['OXINSIDER_API_KEY']}"} def list_all(path, **params): items, cursor = [], None while True: p = {"limit": 100, **params} if cursor: p["cursor"] = cursor body = requests.get(f"{BASE}{path}", params=p, headers=H).json() items.extend(body["data"]) if not body.get("has_more"): return items cursor = body["next_cursor"] leaders = list_all("/leaderboard") print(f"Fetched {len(leaders)} traders") ``` ## Cursors are opaque Don't parse, construct, or store cursors long-term. Always use the `next_cursor` from the response you just got. Different endpoints encode cursors differently: * **Leaderboard**: `{score}_{address}` * **Whale trades**: `{timestamp}_{id}` (ISO 8601) * **Insider radar**: `{score}_{id}` You don't need to know this. Just pass the string back. ## Gotchas * **Don't mix cursors across filters.** A cursor from `?category=crypto` won't work on `?category=politics`. Restart pagination when filters change. * **Don't mix cursors across endpoints.** A leaderboard cursor won't work on whale trades. * **`400 Invalid cursor format`** means the cursor came from a different filter set, a different endpoint, or got mangled. Drop it and start over. * **Stale cursors expire.** Pause for hours and the underlying sort can shift. Expect to restart. # Errors Source: https://docs.0xinsider.com/errors How errors come back, what each code means, and how to recover. Errors come back with a non-2xx HTTP status and the same JSON envelope every time: ```json theme={null} { "object": "error", "error": { "code": "invalid_api_key", "message": "Invalid or missing API key.", "doc_url": "https://docs.0xinsider.com/authentication", "param": null }, "meta": { "request_id": "req_550e8400" } } ``` Two fields matter in production: `error.code` (machine-readable) and `meta.request_id` (the ID you give us when you contact support). ## Error codes | HTTP | `error.code` | What happened | What to do | | ----- | ----------------------- | ----------------------------------------------- | ----------------------------------------------------------------------- | | `400` | `bad_request` | A parameter was invalid. Check `error.param`. | Fix the input. | | `401` | `invalid_api_key` | Key missing, malformed, or revoked. | Re-check the `Authorization` header. | | `402` | `subscription_required` | Key is valid, but no active Insider sub. | Subscribe at [pricing](https://0xinsider.com/pricing). | | `403` | `forbidden` | The account was deleted. | Contact support. | | `404` | `not_found` | The trader / market / resource does not exist. | Verify the ID. | | `423` | `account_locked` | Account is suspended. | Contact support. | | `429` | `rate_limited` | Over 100 req/min (or 100 batch item units/min). | Sleep `Retry-After` seconds and retry. See [Rate Limits](/rate-limits). | | `500` | `internal_error` | Bug on our side. | Retry. Include `meta.request_id` if you contact us. | ## Handling errors in code ```javascript JavaScript theme={null} async function call(path, opts = {}) { const res = await fetch(`https://api.0xinsider.com/api/v1${path}`, { headers: { Authorization: `Bearer ${process.env.OXINSIDER_API_KEY}` }, ...opts, }); const body = await res.json(); if (!res.ok) { const { code, message, param } = body.error; if (code === "rate_limited") { const wait = Number(res.headers.get("retry-after") ?? 1) * 1000; await new Promise(r => setTimeout(r, wait)); return call(path, opts); } if (code === "subscription_required") { throw new Error("Insider subscription required"); } throw new Error(`${code}: ${message}${param ? ` (param=${param})` : ""}`); } return body; } ``` ```python Python theme={null} import os, time, requests BASE = "https://api.0xinsider.com/api/v1" H = {"Authorization": f"Bearer {os.environ['OXINSIDER_API_KEY']}"} def call(path, **params): r = requests.get(f"{BASE}{path}", headers=H, params=params) body = r.json() if r.ok: return body code = body["error"]["code"] if code == "rate_limited": time.sleep(int(r.headers.get("Retry-After", "1"))) return call(path, **params) if code == "subscription_required": raise RuntimeError("Insider subscription required") raise RuntimeError(f"{code}: {body['error']['message']}") ``` ## Per-item batch errors Batch endpoints (e.g. `POST /api/v1/traders/batch`) return `200 OK` even when individual items fail. Each item carries its own `error` field. Read `data[i].error` per item, not just the top-level status. ## Quick troubleshooting * The header needs `Authorization: Bearer oxi_sk_live_...`. * The key is 76 characters. Confirm you copied the full string. * If you regenerated, the old key is dead. Update every consumer. The key is fine; billing is not. Re-subscribe at [pricing](https://0xinsider.com/pricing) and the same key resumes. Sleep `Retry-After` seconds, then retry. See the backoff example in [Rate Limits](/rate-limits). Market Intel takes the raw `condition_id` or the `mkt_...` market ID from V1 responses. It rejects non-market prefixes (`trd_`, `wt_`, `rf_`) with `400 bad_request`. If you only have one of those, resolve the market first via [`/markets/search`](/api-reference/endpoint/search-markets). Retry once. If it persists, email [support@0xinsider.com](mailto:support@0xinsider.com) with the `meta.request_id` from the response. # 0xinsider API Source: https://docs.0xinsider.com/index Prediction market intelligence for AI agents, trading bots, and research tools. Trader grades, whale-trade signals, smart-money flow, positions, and insider detection for Polymarket and Kalshi. The same data behind the [0xinsider terminal](https://0xinsider.com), as an API. Three ways in: * **REST API**: `https://api.0xinsider.com/api/v1/` for bots, dashboards, and research code. * **Local MCP server**: [`@0xinsider/mcp`](https://www.npmjs.com/package/@0xinsider/mcp) on stdio for Claude Code, Cursor, Codex, Gemini CLI. * **Remote MCP**: streamable HTTP for agents that can't run a local subprocess. One [Insider subscription](https://0xinsider.com/pricing) covers all three. Working in Claude Code, Cursor, or another AI agent? Feed it [llms-full.txt](https://docs.0xinsider.com/llms-full.txt), the whole docs site as one plain-text file. Drop it into context and ask the model to wire up calls, draft a bot, or surface ideas you can build on the data. ## What it solves Polymarket and Kalshi publish raw trades. They don't publish grades, signal scores, smart-money breakdowns, position timelines, or pattern detection. 0xinsider builds that layer. The API exposes it. So you can answer: * Which traders consistently beat the market on crypto resolution events? * Did anyone buy big into this market in the last hour, and are they sharp? * Is someone accumulating shares in a market that hasn't resolved yet? * Where is smart money flowing this week? * What price did that S-grade trader get filled at? ## What you can build * **Trading bots** that fire on whale buys from S-grade traders in a category. * **AI agents** that summarize who's winning, what they hold, and at what cost. * **Research tools** that pull leaderboards, trader profiles, history ranges, and category performance. * **Dashboards** that show where capital is rotating across prediction markets. * **Webhooks** that push whale-trade and radar events to your stack in real time. ## A real response The top trader by composite score, right now: ```bash theme={null} curl -H "Authorization: Bearer oxi_sk_live_..." \ "https://api.0xinsider.com/api/v1/leaderboard?limit=1" ``` ```json theme={null} { "object": "list", "data": [ { "id": "trd_0x863134d00841b2e200492805a01e1e2f5defaa53", "username": "RepTrump", "grade": "S", "score": 97.94, "pnl": 7532409.67, "win_rate": 1.0, "markets_traded": 28, "strategy_type": "swing_trader" } ], "has_more": true, "next_cursor": "97.94_0x863134d00841b2e200492805a01e1e2f5defaa53" } ``` One trader. The leaderboard ranks thousands. ## Endpoints Full profile for a wallet: grade, P\&L, win rate, strategy, category strengths. Up to 25 trader profiles in one round trip. Recent large trades with signal scoring. Filter by grade, category, side. Historical whale-trade ranges for backtesting and recap reports. Current positions across traders or markets, with freshness metadata. Server-computed running amount and average entry price per fill. Browse whale-active titled markets by category, platform, status. Smart-money flow direction and top positions for a single market. One-shot market state with trust-metadata fields. Top traders by composite score, cursor-paginated. Keyword search across markets with filters. Suspicious patterns: pre-resolution accumulation, unusual timing. Replay missed feed events after a disconnection. Push whale-trade and radar events to your endpoint. Daily, weekly, monthly recap exports. Streamable HTTP MCP endpoint for hosted agents. ## Where to go next Generate a key, fire your first request, and follow the whales end to end. Plug 0xinsider into Claude Code, Cursor, Codex, or Gemini CLI in two minutes. Drift-tested source client with typed errors and repeated `expand` params. What S, A, B, C, D, F actually mean, with real profile examples. # Local MCP Server Source: https://docs.0xinsider.com/integrations/mcp Give your AI agent direct, read-only access to 0xinsider intelligence over stdio. [`@0xinsider/mcp`](https://www.npmjs.com/package/@0xinsider/mcp) is the official local Model Context Protocol server. It exposes the same data as the REST API (trader grades, whale trades, smart-money flow, positions, insider detection) as MCP tools your agent calls directly. Works with **Claude Code, Cursor, Codex, Gemini CLI**, and any stdio MCP client. Need a hosted HTTP endpoint instead of a local subprocess? See [Remote MCP](/api-reference/endpoint/remote-mcp). ## Install in one command ```bash theme={null} npx -y @0xinsider/mcp init ``` `init` detects your installed clients and writes the right config in the right place. It asks for your API key once. Prefer to edit configs by hand? The per-client paths and snippets are below. ## Manual install per client `~/.claude/settings.json` ```json theme={null} { "mcpServers": { "0xinsider": { "command": "npx", "args": ["-y", "@0xinsider/mcp"], "env": { "OXINSIDER_API_KEY": "oxi_sk_live_..." } } } } ``` `~/.cursor/mcp.json` (restart Cursor after saving) ```json theme={null} { "mcpServers": { "0xinsider": { "command": "npx", "args": ["-y", "@0xinsider/mcp"], "env": { "OXINSIDER_API_KEY": "oxi_sk_live_..." } } } } ``` `~/.codex/config.toml` ```toml theme={null} [mcp_servers."0xinsider"] command = "npx" args = ["-y", "@0xinsider/mcp"] [mcp_servers."0xinsider".env] OXINSIDER_API_KEY = "oxi_sk_live_..." ``` `~/.gemini/settings.json` ```json theme={null} { "mcpServers": { "0xinsider": { "command": "npx", "args": ["-y", "@0xinsider/mcp"], "env": { "OXINSIDER_API_KEY": "oxi_sk_live_..." } } } } ``` Gemini exposes the tools through `/mcp`. Any stdio-MCP client works: ```bash theme={null} OXINSIDER_API_KEY=oxi_sk_live_... npx -y @0xinsider/mcp ``` See all options: ```bash theme={null} npx -y @0xinsider/mcp --help ``` ## What the server exposes ### Tools (read-only) | Tool | What it does | | ----------------------- | -------------------------------------------------------------------- | | `get_trader` | Wallet profile: grade, P\&L, win rate, strategy, category strengths. | | `get_whale_trades` | Recent large trades, filterable by size, category, grade. | | `get_leaderboard` | Top-ranked traders (S/A/B) with optional category/strategy filter. | | `get_positions` | Current positions across traders or markets. | | `get_position_timeline` | Per-market trader fills with running amount and average entry price. | | `search_markets` | Keyword search across prediction markets. | | `explore_markets` | Browse whale-active markets by category, platform, status. | | `get_market_intel` | Smart-money breakdown for a single market. | | `get_insider_radar` | Suspicious accumulation and timing patterns. | Every tool advertises `readOnlyHint: true`. The server can't place trades or write data. ### Resources (auto-attached context) | URI | What you get | | ------------------------------- | ------------------------------------------------- | | `oxinsider://docs/api` | Full API reference, ready for the model to read. | | `oxinsider://docs/agents` | Decision tree for agents: when to use which tool. | | `oxinsider://data/leaderboard` | Live top 20 traders. | | `oxinsider://data/whale-trades` | Live latest 20 whale trades. | ### Prompts (one-shot templates) | Prompt | Use when | | ----------------- | ----------------------------------------------------------- | | `analyze_trader` | You want a full breakdown of a specific wallet. | | `market_report` | You want smart-money flow on a market topic. | | `trading_signals` | You want a scan for high-conviction signals across markets. | ## Try it After install, ask your agent: * "Who are the top prediction-market traders right now?" * "What are A-grade or better whales buying in crypto markets today?" * "Analyze trader `0x863134d00841b2e200492805a01e1e2f5defaa53`. Is their strategy worth following?" * "Are there suspicious accumulation patterns on the Trump election market?" * "Show me the position timeline for that whale on the Ethereum market." The agent picks the right tool and calls it for you. ## Environment variables | Variable | Required | What it controls | | ------------------- | -------- | --------------------------------------------------- | | `OXINSIDER_API_KEY` | Yes | Your API key (`oxi_sk_live_...`). | | `OXINSIDER_API_URL` | No | Override the base URL (mostly for self-hosted dev). | The MCP server uses your normal API key and shares the 100 req/min rate limit with direct API calls. One key, one budget. Get yours at [0xinsider.com/developers](https://0xinsider.com/developers). # TypeScript Client Source: https://docs.0xinsider.com/integrations/typescript-client Drift-tested source client for the 0xinsider API. A typed TypeScript client lives in the app repo at `web/src/lib/api-client`. It's drift-tested against the checked-in OpenAPI spec: when the spec moves, the client moves with it or the test suite fails. It's **not** on npm yet. Use it as source or as a reference implementation. Want a package release? That needs decisions on package name, semver policy, changelog ownership, and npm access. Open an issue if you depend on it. ## What it handles * `Authorization: Bearer` header injection. * Path parameter interpolation (`/trader/{address}`, `/market/{condition_id}/intel`). * Repeated query parameters like `expand=strategy&expand=categories`. The API also accepts the legacy `expand[]` form. * JSON request bodies for batch and webhook endpoints. * V1 error envelopes as typed exceptions (`code`, `message`, `param`, `request_id`). ## Example ```ts theme={null} import { OxinsiderApiClient } from "./api-client"; const client = new OxinsiderApiClient({ baseUrl: "https://api.0xinsider.com", apiKey: process.env.OXINSIDER_API_KEY, }); // Wallet address or username — both work. const trader = await client.getTrader("swisstony", { query: { expand: ["strategy", "categories"] }, }); const markets = await client.searchMarkets("NBA", { query: { limit: 5, status: "active" }, }); ``` ## Handling errors The client throws typed exceptions instead of a generic error object, so you match on `error.code` directly: ```ts theme={null} import { OxinsiderApiError } from "./api-client"; try { const trader = await client.getTrader("not-a-real-trader"); } catch (err) { if (err instanceof OxinsiderApiError) { if (err.code === "not_found") { // expected: unknown trader } else if (err.code === "rate_limited") { await new Promise(r => setTimeout(r, err.retryAfterMs ?? 1000)); } else { throw err; } } else { throw err; } } ``` ## Keep OpenAPI as the source of truth The client operation table regenerates from [`api-reference/openapi.json`](https://github.com/0xinsider/docs/blob/main/api-reference/openapi.json). Change the spec and the client follows. Don't hand-edit the client to add operations without updating the spec. # Quickstart Source: https://docs.0xinsider.com/quickstart From zero to your first whale-trade signal in two minutes. Generate a key, confirm it works, then run a real "follow the smartest traders" workflow. ## 1. Generate your API key API access is bundled with the [Insider subscription](https://0xinsider.com/pricing) (\$89/mo). [0xinsider.com/sign-up](https://0xinsider.com/sign-up) Pick the Insider plan on [Pricing](https://0xinsider.com/pricing). On [Developers](https://0xinsider.com/developers), click **Generate Key**. It's shown once, so copy it now. You can regenerate a lost key, but the old one stops working. Keys look like `oxi_sk_live_` followed by 64 hex characters. Export it once so the rest of this page just works: ```bash theme={null} export OXINSIDER_API_KEY="oxi_sk_live_..." ``` ## 2. Confirm the key works ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ https://api.0xinsider.com/api/v1/health ``` ```json theme={null} { "object": "health", "data": { "status": "ok", "db": true, "cache": true }, "meta": { "request_id": "req_abc123", "cached": false } } ``` `status: "ok"` means you're wired up. Browser apps can call REST endpoints under `https://api.0xinsider.com/api/v1/*` directly from any origin with `Authorization: Bearer ...`; do not send cookies or `credentials: "include"`. Remote MCP at `/api/v1/mcp` still validates `Origin` against the 0xinsider/localhost allowlist. Browser JavaScript can read `X-RateLimit-*`, `Retry-After`, `ETag`, `X-Request-Id`, `X-Request-Cost`, `X-Batch-RateLimit-*`, `Mcp-Session-Id`, and `X-Mcp-Error-Code` response headers. Account/key-management routes such as `/api/keys` stay first-party-only and credentialed. ## 3. Follow the smartest traders Not "who's #1," but "what are the best traders doing right now, and am I early?" ### Step A: Pull the top 5 S-grade traders ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/leaderboard?limit=5" ``` Each entry has the wallet address (`id`), grade, score, P\&L, and strategy. Pick one to follow. ### Step B: Look up that trader's full profile The trader endpoint takes a wallet address or a known username: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/trader/0x863134d00841b2e200492805a01e1e2f5defaa53" ``` You get their realized P\&L, win rate, category strengths, and current open positions. ### Step C: See what whales are buying now A-grade or better, last 50 trades: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades?min_grade=A&limit=50" ``` Layer filters. A-grade or better, crypto only, buy side: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/whale-trades?min_grade=A&category=crypto&side=buy&limit=50" ``` ### Step D: Drill into one market Grab the `condition_id` from a trade you like (raw hex, not the prefixed `mkt_...` form), then: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ "https://api.0xinsider.com/api/v1/market//intel" ``` Market Intel returns the smart-money breakdown: buy volume vs sell volume from graded traders, top positions, and which side has conviction. The loop: **leaderboard -> trader profile -> whale trades -> market intel**. Wire it to a cron, a chatbot, or a dashboard. ## Same workflow, in code ```javascript JavaScript theme={null} const KEY = process.env.OXINSIDER_API_KEY; const headers = { Authorization: `Bearer ${KEY}` }; const top = await fetch( "https://api.0xinsider.com/api/v1/leaderboard?limit=5", { headers } ).then(r => r.json()); const topId = top.data[0].id.replace(/^trd_/, ""); const trader = await fetch( `https://api.0xinsider.com/api/v1/trader/${topId}`, { headers } ).then(r => r.json()); const whales = await fetch( "https://api.0xinsider.com/api/v1/whale-trades?min_grade=A&limit=50", { headers } ).then(r => r.json()); console.log({ top: top.data[0], trader: trader.data, whales: whales.data.length }); ``` ```python Python theme={null} import os, requests KEY = os.environ["OXINSIDER_API_KEY"] H = {"Authorization": f"Bearer {KEY}"} BASE = "https://api.0xinsider.com/api/v1" top = requests.get(f"{BASE}/leaderboard", params={"limit": 5}, headers=H).json() top_id = top["data"][0]["id"].removeprefix("trd_") trader = requests.get(f"{BASE}/trader/{top_id}", headers=H).json() whales = requests.get( f"{BASE}/whale-trades", params={"min_grade": "A", "limit": 50}, headers=H, ).json() print(top["data"][0], trader["data"]["grade"], len(whales["data"])) ``` ## Lower the call count with a batch endpoint Already have the wallet addresses or usernames you care about? Fetch them in one call: ```bash theme={null} curl -H "Authorization: Bearer $OXINSIDER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"traders": ["0xabc...", "0xdef...", "0x123..."]}' \ "https://api.0xinsider.com/api/v1/traders/batch" ``` Batch reads return the same per-item shape, with per-item error fields when an address fails. They count against a separate batch-item rate-limit budget. See [Rate Limits](/rate-limits). ## Next Skip the HTTP plumbing. Give your AI agent the same tools directly. Use the repo-owned source client with typed errors and `expand` helpers. What S, A, B, C, D, F actually mean. What to do when a request fails. # Rate Limits Source: https://docs.0xinsider.com/rate-limits How many requests you can make, and how to back off cleanly. You get **100 requests per minute** on a sliding window. The limit is **per user**, shared across every key and every endpoint. Batch read endpoints (e.g. `POST /api/v1/traders/batch`, `POST /api/v1/markets/intel/batch`) get a **separate** budget in *item units*, also 100 per minute. A 25-item batch reserves 25 item units before it runs. `GET /api/v1/usage` does not spend primary quota or log into daily usage. It has its own 100 reads/minute per-user guard so checking quota can't itself blow up usage-count load. | Setting | Value | | --------------------------- | ------------------------------------------------------------ | | Requests per minute | 100 | | Usage reads per minute | 100 | | Batch item units per minute | 100 | | Window type | Sliding (not bucket-of-60-seconds) | | Scope | Per user (sum of all keys) | | Header on success | `X-RateLimit-*` (+ `X-Batch-RateLimit-*` on batch endpoints) | | Header on `429` | `Retry-After` | ## Headers you should read Every authenticated response carries: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1774450631 X-Request-Id: req_550e8400 ``` | Header | Meaning | | ----------------------- | ------------------------------------------------------------- | | `X-RateLimit-Limit` | Max requests per minute. | | `X-RateLimit-Remaining` | Remaining slots in the current window. | | `X-RateLimit-Reset` | Unix timestamp (seconds) when the window resets. | | `X-Request-Id` | Request identifier to include when reporting a support issue. | Batch responses additionally carry: | Header | Meaning | | ----------------------------- | --------------------------------------------------------- | | `X-Request-Cost` | Item units this single call charged (one per batch item). | | `X-Batch-RateLimit-Limit` | Max item units per minute. | | `X-Batch-RateLimit-Remaining` | Item units remaining in the window. | | `X-Batch-RateLimit-Reset` | Unix timestamp when the batch window resets. | Browser clients can read these headers on public REST `/api/v1/*` responses because the public API exposes them through CORS. The public API also exposes `Retry-After`, `ETag`, `X-Request-Id`, `X-Request-Cost`, `Mcp-Session-Id`, and `X-Mcp-Error-Code`. Remote MCP at `/api/v1/mcp` still validates `Origin` against the 0xinsider/localhost allowlist. Do not use credentialed CORS for public API calls; send only the Bearer token header. If you go over either budget, you get a `429` plus a `Retry-After` header in seconds: ``` HTTP/1.1 429 Too Many Requests Retry-After: 12 ``` ```json theme={null} { "object": "error", "error": { "code": "rate_limited", "message": "Rate limit exceeded. Retry after 12s.", "doc_url": "https://docs.0xinsider.com/rate-limits" } } ``` ## A client that respects the retry ```javascript JavaScript theme={null} async function fetchWithBackoff(url, opts = {}, maxRetries = 5) { for (let attempt = 0; attempt < maxRetries; attempt++) { const res = await fetch(url, opts); if (res.status !== 429) return res; const wait = Number(res.headers.get("retry-after") ?? 1) * 1000; await new Promise(r => setTimeout(r, wait)); } throw new Error("Rate limit retries exhausted"); } const res = await fetchWithBackoff( "https://api.0xinsider.com/api/v1/whale-trades?limit=50", { headers: { Authorization: `Bearer ${process.env.OXINSIDER_API_KEY}` } } ); const body = await res.json(); ``` ```python Python theme={null} import os, time, requests def get_with_backoff(url, params=None, max_retries=5): headers = {"Authorization": f"Bearer {os.environ['OXINSIDER_API_KEY']}"} for _ in range(max_retries): r = requests.get(url, params=params, headers=headers) if r.status_code != 429: return r time.sleep(int(r.headers.get("Retry-After", "1"))) raise RuntimeError("Rate limit retries exhausted") body = get_with_backoff( "https://api.0xinsider.com/api/v1/whale-trades", params={"limit": 50}, ).json() ``` ## Staying well under the limit * **Cache.** Most of this data updates every 30-120 seconds. Re-fetching every second wastes budget. * **Paginate, don't re-list.** Use cursors instead of refetching the full leaderboard each loop. * **Ask for more per request.** Bump `limit` to 100 instead of making 10 calls of `limit=10`. * **Batch when you know your IDs.** One batch call for 25 traders costs 25 batch-item units but only one regular request. * **Watch `X-RateLimit-Remaining`.** Below 10, pause polling until the next reset. * **Use `/usage` for budget checks.** `GET /api/v1/usage` reads the current primary limiter window without incrementing it. Respect its own 100 reads/minute cap; don't probe quota with another endpoint. * **One process owns the polling.** Don't have every container in a fleet poll the same endpoint with the same key. ## Conditional GETs Deterministic read endpoints return an `ETag` header. Send it back as `If-None-Match` to get `304 Not Modified` with an empty body when nothing changed. This covers trader, positions, whale-trades, whale-trades/history, leaderboard, markets/explore, market intel, market snapshot, insider-radar, position-timeline, and health responses. Report snapshots aren't conditional yet because their body includes a request-time `generated_at`.