Polysink API

Everything Polymarket — one authenticated REST + WebSocket surface. Base URL https://api.polysink.io, version /v1.

Getting started

Polysink gives you the entire Polymarket dataset — markets, events, on-chain and CLOB trades, orderbooks, wallets, leaderboards, and microstructure analytics — through one REST + WebSocket API. Base URLs:

Base URLs
REST       https://api.polysink.io
WebSocket  wss://api.polysink.io

Every request is authenticated with an API key. Sign up, pick a plan, and create a key in the dashboard — then your first request is one curl away:

First request
curl -s "https://api.polysink.io/v1/markets?status=active&limit=5" \
  -H "Authorization: Bearer $POLYSINK_KEY"

If you work in TypeScript, the official SDK wraps every endpoint and stream with full types — see the SDK section below.

Authentication

All /v1 REST routes require an Authorization header with your API key. Only the health probes (GET /health and GET /health/matcher) are public.

REST
curl -s "https://api.polysink.io/v1/markets" \
  -H "Authorization: Bearer $POLYSINK_KEY"

WebSocket connections accept the same Authorization header, or — for browser clients that can't set headers — the token can ride in the WebSocket subprotocol. The server echoes the bearer subprotocol back on a successful upgrade and pings every 30 seconds to keep the connection alive.

WebSocket auth from a browser
const ws = new WebSocket(
  "wss://api.polysink.io/v1/ws/trades",
  ["bearer", POLYSINK_KEY],
);

Errors & conventions

Errors are returned as a JSON object with a single error message. Status codes follow the usual conventions:

Error shape
{ "error": "message" }

400 — invalid query or body values · 401 — missing or invalid token · 404 — unknown market, event, or wallet · 503 — the market matcher is still warming up · 500 — backend failure.

List endpoints share two pagination parameters: limit and offset. Timestamps are RFC3339 unless an endpoint says otherwise; prices are decimal strings to preserve precision — never floats.

Markets

GET/v1/markets

List markets across the catalog.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.
categorystringFilter by category slug.
statusstringFilter by market status, e.g. active.
searchstringFree-text search over titles.

Returns MarketSummary[]

GET/v1/markets/{condition_id}

Fetch one market by its condition id, including outcomes and current pricing.

Returns MarketDetail

GET/v1/markets/{condition_id}/trades

Trade history for one market, newest first.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns TradeRecord[]

GET/v1/markets/{condition_id}/candles

OHLCV candles for one market.

ParameterTypeDescription
intervalstring1m, 5m, 15m, 1h, 4h, or 1d. Defaults to 1h.
token_idstringRestrict to one outcome token.
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns Candle[]

GET/v1/markets/{condition_id}/orderbook

Current orderbook for each outcome of the market.

Returns Orderbook[]

GET/v1/markets/{condition_id}/holders

Current holders of the market's outcome tokens.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns MarketParticipant[]

GET/v1/markets/{condition_id}/traders

Traders active in the market. Pass sort=upnl to rank by unrealized PnL.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.
sortstringupnl to sort by unrealized PnL.

Returns MarketParticipant[]

Market matching

The matcher turns free text — a tweet, a headline, a search query — into ranked Polymarket markets. It runs against a prewarmed snapshot of the catalog, so responses are fast and deterministic.

POST/v1/markets/match

Match free text against the market catalog.

ParameterTypeDescription
textstringRequired. The text to match. Empty text returns 400.
reference_textstringOptional additional context.
limitintegerMaximum matches to return.

Returns { matches: MarketMatch[] }

Response
{
  "matches": [
    {
      "market_id": "512329",
      "condition_id": "0x1a9e…",
      "url": "https://polymarket.com/event/…",
      "title": "Fed cuts rates in March?",
      "relevance_score": 0.93,
      "deterministic_score": 0.88,
      "causation_label": "direct"
    }
  ]
}
GET/v1/markets/matchable

The compact market catalog used by matching and benchmark clients.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns MatchableMarketSummary[]

Orderbook history

GET/v1/orderbook/history

Historical orderbook snapshots for one outcome token, for replaying liquidity over time.

ParameterTypeDescription
token_idstringRequired (alias: asset_id). The outcome token.
start_timeintegerWindow start, epoch milliseconds.
end_timeintegerWindow end, epoch milliseconds.
limitintegerDefaults to 100, clamped to 1–1000.
pagination_keystringCursor from the previous page, formatted <timestamp_ms>:<snapshot_id>.

Returns OrderbookHistoryResponse

Events & tags

GET/v1/events

List events — the groupings that markets belong to.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.
categorystringFilter by category slug.

Returns EventSummary[]

GET/v1/events/{event_id}

Fetch one event together with its markets.

Returns EventDetail

GET/v1/tags

The tag catalog used across events and markets.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns TagRecord[]

Trades

Polysink normalizes on-chain exchange fills and off-chain CLOB executions into one trade shape, so a wallet's history and a market's tape read the same way regardless of where the fill happened.

GET/v1/trades

The global trade tape, newest first.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns TradeRecord[]

Wallets

GET/v1/wallets/{address}/positions

Current positions with cost basis for a wallet.

Returns WalletPosition[]

GET/v1/wallets/{address}/trades

Full trade history for a wallet.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns TradeRecord[]

GET/v1/wallets/{address}/stats

All-time performance stats — volume, realized/unrealized PnL, win rate. Unknown wallets return 404.

Returns WalletStats

Leaderboard & categories

GET/v1/leaderboard

Top-1000 traders, global or per category, refreshed continuously.

ParameterTypeDescription
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.
categorystringRank within one category.

Returns LeaderboardEntry[]

GET/v1/categories

Per-category rollups: volume, market counts, activity.

Returns CategoryStats[]

Analytics

Research-grade microstructure metrics computed continuously over the raw flow. All three endpoints share from/to time filters and pagination.

GET/v1/analytics/execution-quality

Effective spreads and execution quality in 5-minute buckets.

ParameterTypeDescription
condition_idstringFilter to one market.
token_idstringFilter to one outcome token.
sourcestringonchain or clob.
from / toRFC3339Time window.
bucketstringCurrently 5m.
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns ExecutionQualityPoint[]

GET/v1/analytics/liquidity-fragility

How quickly displayed liquidity evaporates under pressure, in 5-minute buckets.

ParameterTypeDescription
condition_idstringFilter to one market.
token_idstringFilter to one outcome token.
sourcestringclob.
from / toRFC3339Time window.
bucketstringCurrently 5m.
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns LiquidityFragilityPoint[]

GET/v1/analytics/informed-flow

Daily informed-flow metrics — where the smart money is trading.

ParameterTypeDescription
sourcestringonchain or clob.
from / todateDate window.
bucketstring1d or daily.
limitintegerMaximum rows to return.
offsetintegerRows to skip before returning results.

Returns InformedFlowPoint[]

WebSockets

Three streams cover live data. Authenticate as described above; the server pings every 30 seconds, and messages are JSON.

WS/v1/ws/markets

Live market updates. Subscribe to specific condition ids, or "*" for everything.

Returns MarketUpdate

Subscribe / unsubscribe
{ "subscribe": ["0x1a9e…", "*"] }
{ "unsubscribe": ["0x1a9e…"] }
WS/v1/ws/trades

The global trade firehose. No subscription message needed — trades start flowing on connect.

Returns TradeUpdate

WS/v1/ws/trades/{condition_id}

Trades for a single market.

Returns TradeUpdate

TypeScript SDK

@tenz-app/polysink-sdk wraps every REST endpoint and WebSocket stream with types generated directly from the API's Rust models. It's distributed through GitHub Packages — add the registry once, then install.

.npmrc + install
# .npmrc
@tenz-app:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

pnpm add @tenz-app/polysink-sdk
REST client
import { Polysink } from "@tenz-app/polysink-sdk";

const client = new Polysink({ apiKey: process.env.POLYSINK_KEY });

const markets = await client.markets.list({ category: "sports", limit: 50 });
const candles = await client.markets.candles(markets[0].condition_id, {
  interval: "1h",
});
const leaders = await client.leaderboard.list({ limit: 100 });
Streams
import { MarketStream, AllTradesStream } from "@tenz-app/polysink-sdk";

const stream = new MarketStream({ apiKey: process.env.POLYSINK_KEY });
stream.subscribe("0x1a9e…", (u) => quote(u.best_bid, u.best_ask));

const firehose = new AllTradesStream({ apiKey: process.env.POLYSINK_KEY });
firehose.on("trade", (t) => tape(t.condition_id, t.price, t.size));
Utilities & types
import { impliedProbability, formatUsd, vwap } from "@tenz-app/polysink-sdk/utils";
import type { MarketSummary, Candle } from "@tenz-app/polysink-sdk/types";

impliedProbability(0.75); // 75
formatUsd("1234567.89");  // "$1,234,567.89"

Health

GET/health

Public liveness probe. Returns { "status": "ok" }.

Returns { status }

GET/health/matcher

Public matcher readiness probe. Returns ok once the matcher snapshot is loaded, starting before that.

Returns { status }