ALPHA

API

Every alert on the live feed is available over HTTP. No key required at this stage — the endpoints below are public and read-only. Authentication, subscriptions and webhook delivery arrive with the notification phase.

Endpoints

GET /api/v1/trades/latest?limit=50&since=<iso8601>

Recent qualifying trades, newest first. Add refresh=1 to run a poll cycle inline before responding. The response meta carries total_archived — how many trades the archive behind /trades/history currently holds — so a client can tell whether older trades exist without spending a request to find out.

GET /api/v1/trades/history?limit=100&cursor=<opaque>

Paginated archive, newest first. Unlike /trades/latest, which serves a rolling buffer of recent qualifying trades, this reads the archive — every trade detected within the retention window (default 30 days), including ones the public feed filters out. The response meta carries next_cursor (null when exhausted), has_more and total_archived. Pass the cursor back verbatim; it is stable against new trades arriving mid-scroll.

GET /api/v1/traders/top?limit=10

The currently tracked traders, in leaderboard rank order.

GET /api/v1/traders/:wallet

One trader. stats holds settled performance counted from Polymarket’s closed-position records — realizedPnl, positionsClosed, wins, losses, breakeven, winRate, avgWin, avgLoss, profitFactor, biggestWin/biggestLoss and a byGame breakdown. observed is a separate, smaller sample derived from trades this deployment has seen — do not conflate the two. winRate excludes breakeven positions from its denominator and is null when nothing has settled; profitFactor is null rather than infinite when there are no losses. truncated is true when the trader has more history than was fetched.

GET /api/v1/bootstrap

Everything a client needs to run its own feed: tracked wallets, the esports condition-ID index, URL templates and default filters.

GET /api/v1/status

Public service status: health, data freshness, measured alert latency per ingest source, and recent activity. Operator internals (storage backend, deploy target, poll plumbing) are omitted unless ADMIN_TOKEN is supplied via ?token= or the X-Admin-Token header, in which case a diagnostics object is included.

Response envelope

{ "ok": true, "data": <payload>, "meta": { "generated_at": "..." } }

Errors use the same envelope with { "ok": false, "error": { "code", "message" } }.

Event schema

One normalized shape, independent of both Polymarket’s wire format and any notification provider. It is what the webhook body will carry unchanged.

{
  "event_id": "9f2c1ab4e7d0435c8a61f0d3c72b19ee",
  "event_type": "new_trade",
  "timestamp": "2026-08-22T06:32:13.000Z",

  "trader": {
    "username": "BOOMBOYS.Kiritych",
    "wallet": "0xcd30f4698c6f5f3829893e68e183a8e5ea18f316",
    "rank": 1,
    "monthly_profit": 1525246.07,
    "profile_url": "https://polymarket.com/profile/0xcd30…f316",
    "profile_image": null
  },

  "market": {
    "id": "0x72f93cc5347291e42699dc9db76a38e184a00a088b368fe0a71148148d0260b4",
    "title": "Dota 2: Nigma Galaxy vs BoomBoys - Game 2 Winner",
    "slug": "dota2-ngx-boombo-2026-08-22-game2",
    "event_slug": "dota2-ngx-boombo-2026-08-22",
    "category": "esports",
    "game": "dota2",
    "game_label": "Dota 2",
    "game_short": "DOTA 2",
    "game_source": "title",
    "url": "https://polymarket.com/event/dota2-ngx-boombo-2026-08-22/dota2-ngx-boombo-2026-08-22-game2",
    "icon": null
  },

  "trade": {
    "side": "BUY",
    "outcome": "BoomBoys",
    "outcome_index": 1,
    "price": 0.4767867447,
    "size_usd": 1131.08548,
    "shares": 2311.83,
    "transaction_hash": "0x93010113387bdefb7b7c162b0c2eae2f05013b267db149af3acd95019ae83816",
    "asset": "42974820668140481674546125062447708867633239207219559804172577672111834920324"
  },

  "timing": {
    "source_timestamp": "2026-08-22T06:32:13.000Z",
    "detected_timestamp": "2026-08-22T06:32:14.180Z",
    "detection_latency_ms": 1180,
    "ingest_source": "stream"
  }
}

Field notes worth reading

Examples

curl

curl -s https://YOUR-SITE.netlify.app/api/v1/trades/latest?limit=10 | jq

JavaScript

const res = await fetch('https://YOUR-SITE.netlify.app/api/v1/trades/latest?limit=25');
const { data } = await res.json();

for (const event of data) {
  console.log(
    event.trader.username,
    event.trade.side,
    event.trade.outcome,
    `$${event.trade.size_usd.toFixed(0)}`,
    event.market.title,
  );
}

Python

import requests

r = requests.get("https://YOUR-SITE.netlify.app/api/v1/trades/latest", params={"limit": 25})
for event in r.json()["data"]:
    print(
        event["trader"]["username"],
        event["trade"]["side"],
        event["trade"]["outcome"],
        f'${event["trade"]["size_usd"]:.0f}',
        event["market"]["title"],
    )

Rate limits

None enforced on this deployment yet. Upstream, Polymarket’s data API allows 1,000 requests per 10 seconds; this service polls far below that. Please be reasonable until keys and quotas land.

What this API does not claim

← back to the feed