PolyConsensus

API Documentation

Public API for PolyConsensus smart money market intelligence

Base URL
https://polyconsensus.com

Usage Rules & Rate Limits

60 requests per minute

Standard endpoints (markets, leaderboard, alerts, analytics, insiders, changes, entrants, chat history, watchlist, dashboard insights / summary / P&L)

20 requests per minute

Trader profiles (/api/trader/{address}) and market charts (/api/markets/{conditionId}/chart)

30 requests per minute

Order book (/api/markets/{conditionId}/orderbook) and dashboard data (/api/dashboard/data)

120 requests per minute

Health check (/api/ping) and live price deltas (/api/smart-markets/prices)

10 requests per minute; 5 new accounts per hour

Wallet sign-in (nonce and verify); accounts created by a first sign-in

10 changes per hour; 5 exports per hour

Profile changes and account deletion; account data export

30 / 120 / 60 per minute

Trade panel: builder signing, Polygon RPC (every call in a batch counts), positions

6 concurrent connections

SSE event stream (/api/events) — the site opens one shared stream per tab

1 message per 3 s, 10 per minute per account (20 per minute per client)

Chat posting (POST /api/chat); the whole site accepts at most 30 messages per 10 s

60 per minute per address; 300 per minute per API key

Bot API v1 (/api/v1/*). Keyed responses carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset

20 per hour

Creating and deleting API keys (/api/auth/api-keys)

Responses: 429 with Retry-After and RateLimit-* headers

All limited endpoints

No automated scraping

All endpoints

No API key required. All public endpoints are open. The Bot API (/api/v1) also takes an optional key for a higher limit. Abuse (aggressive scraping, DDoS) will result in IP ban.

Caching. Most endpoints return cached data. Respect Cache-Control headers. Do not poll faster than the cache TTL — you'll get identical responses.

SSE for real-time. Use /api/events instead of polling for live updates. Connect once, receive push events when data changes.

Fair use. This API is provided free for personal and research use. Commercial use or redistribution requires permission.

Quick Start

// Fetch active consensus markets
const res = await fetch("https://polyconsensus.com/api/smart-markets");
const { markets } = await res.json();
console.log(markets[0].title, markets[0].consensusPct + "% consensus");

// Get trader profile
const trader = await fetch("https://polyconsensus.com/api/trader/TraderAlpha").then(r => r.json());
console.log(trader.trader.winRate + "% win rate");

// Listen for real-time updates
const sse = new EventSource("https://polyconsensus.com/api/events");
sse.addEventListener("markets", (e) => {
  console.log("Markets updated:", JSON.parse(e.data));
});

Bot API v1

STABLE

A versioned, read-only API for trading bots that run on your own machine with your own Polymarket keys. PolyConsensus never sees your keys or your funds: the bot reads the consensus here and places its orders on Polymarket directly.

  • GET /api/v1/consensus/markets: every consensus market with CLOB token ids, prices, the consensus side and signals; filters, sorting and cursor paging.
  • GET /api/v1/consensus/markets/{id}: one market by conditionId or slug, with its largest holders or its resolution.
  • GET /api/v1/consensus/changes: new consensus markets, flips and resolutions of the last 7 days.
  • GET /api/v1/consensus/resolved: resolved markets and whether the consensus was right, for backtests.

Keys are optional

Without a key: 60 requests per minute per address. With Authorization: Bearer <key>: 300 per minute per key, from anywhere. Create keys under Dashboard → Settings → Bot API keys. A wrong or revoked key gets 401, never anonymous access.

Units

Times are epoch milliseconds (fields named …Date are ISO 8601). Percentages are 0–100, prices 0–1, money in USD.

Errors

{ "error": { "code", "message" } } with the HTTP status: 400 invalid_cursor / invalid_id / invalid_types, 401 invalid_api_key, 404 not_found, 429 rate_limited and 503 warming_up (both with Retry-After).

Paging

Lists return nextCursor: pass it back as cursor until it is null (hasMore false). Cursors are keyset positions, so a page never repeats or skips an item because the list changed in between.

Freshness

Prices refresh every minute, holders and consensus at the hourly rebuild (new consensus markets within minutes), flips as they happen. Without a key an answer can come from a cache 15–60 s old; with a key it is always live.

Stability

Within v1 fields are only added, never removed, renamed or re-scaled. A breaking change ships as /api/v2, and v1 keeps working alongside it for a deprecation period announced here.

Prices are indicative

Place orders off Polymarket's order book: a price can move between our refresh and your order. Signals are statistics, not advice; start small.

Clients

Send a User-Agent naming your bot (some HTTP libraries send none, and Cloudflare may refuse those). Browsers may call the API from any origin; never put a key in a public web page.

import time
import requests

BASE = "https://polyconsensus.com/api/v1"
HEADERS = {"User-Agent": "my-bot/1.0"}  # with a key: HEADERS["Authorization"] = "Bearer pck_..."

def markets(**filters):
    """Every consensus market matching the filters, page by page."""
    cursor = None
    while True:
        params = dict(filters, limit=500, **({"cursor": cursor} if cursor else {}))
        r = requests.get(f"{BASE}/consensus/markets", params=params, headers=HEADERS, timeout=20)
        r.raise_for_status()
        page = r.json()
        yield from page["markets"]
        cursor = page["nextCursor"]
        if not cursor:
            return

for m in markets(minHolders=10, minPct=75, contrarian="exclude"):
    c = m["consensus"]
    if c and c["tokenId"]:
        print(m["title"], "->", c["outcome"], c["headcountPct"], "% at", c["price"], "token", c["tokenId"])

# Watch for flips: ask an overlapping window every minute, skip what was already seen.
seen = set()
while True:
    since = int(time.time() * 1000) - 2 * 3600 * 1000
    r = requests.get(f"{BASE}/consensus/changes", params={"since": since, "types": "flipped"}, headers=HEADERS, timeout=20)
    if r.status_code == 429:
        time.sleep(int(r.headers.get("Retry-After", "30")))
        continue
    for ev in r.json()["changes"]:
        if ev["id"] not in seen:
            seen.add(ev["id"])
            print("flip:", ev["title"], ev["from"]["outcome"], "->", ev["to"]["outcome"])
    time.sleep(60)

Changelog

2026-10-06 · v1 released: markets, market, changes and resolved; optional API keys.

Last updated: October 2026 · 52 endpoints documented