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:
REST https://api.polysink.io
WebSocket wss://api.polysink.ioEvery 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:
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.
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.
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": "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
/v1/marketsList markets across the catalog.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
category | string | Filter by category slug. |
status | string | Filter by market status, e.g. active. |
search | string | Free-text search over titles. |
Returns MarketSummary[]
/v1/markets/{condition_id}Fetch one market by its condition id, including outcomes and current pricing.
Returns MarketDetail
/v1/markets/{condition_id}/tradesTrade history for one market, newest first.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns TradeRecord[]
/v1/markets/{condition_id}/candlesOHLCV candles for one market.
| Parameter | Type | Description |
|---|---|---|
interval | string | 1m, 5m, 15m, 1h, 4h, or 1d. Defaults to 1h. |
token_id | string | Restrict to one outcome token. |
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns Candle[]
/v1/markets/{condition_id}/orderbookCurrent orderbook for each outcome of the market.
Returns Orderbook[]
/v1/markets/{condition_id}/holdersCurrent holders of the market's outcome tokens.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns MarketParticipant[]
/v1/markets/{condition_id}/tradersTraders active in the market. Pass sort=upnl to rank by unrealized PnL.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
sort | string | upnl 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.
/v1/markets/matchMatch free text against the market catalog.
| Parameter | Type | Description |
|---|---|---|
text | string | Required. The text to match. Empty text returns 400. |
reference_text | string | Optional additional context. |
limit | integer | Maximum matches to return. |
Returns { matches: MarketMatch[] }
{
"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"
}
]
}/v1/markets/matchableThe compact market catalog used by matching and benchmark clients.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns MatchableMarketSummary[]
Orderbook history
/v1/orderbook/historyHistorical orderbook snapshots for one outcome token, for replaying liquidity over time.
| Parameter | Type | Description |
|---|---|---|
token_id | string | Required (alias: asset_id). The outcome token. |
start_time | integer | Window start, epoch milliseconds. |
end_time | integer | Window end, epoch milliseconds. |
limit | integer | Defaults to 100, clamped to 1–1000. |
pagination_key | string | Cursor from the previous page, formatted <timestamp_ms>:<snapshot_id>. |
Returns OrderbookHistoryResponse
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.
/v1/tradesThe global trade tape, newest first.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns TradeRecord[]
Wallets
/v1/wallets/{address}/positionsCurrent positions with cost basis for a wallet.
Returns WalletPosition[]
/v1/wallets/{address}/tradesFull trade history for a wallet.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns TradeRecord[]
/v1/wallets/{address}/statsAll-time performance stats — volume, realized/unrealized PnL, win rate. Unknown wallets return 404.
Returns WalletStats
Leaderboard & categories
/v1/leaderboardTop-1000 traders, global or per category, refreshed continuously.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
category | string | Rank within one category. |
Returns LeaderboardEntry[]
/v1/categoriesPer-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.
/v1/analytics/execution-qualityEffective spreads and execution quality in 5-minute buckets.
| Parameter | Type | Description |
|---|---|---|
condition_id | string | Filter to one market. |
token_id | string | Filter to one outcome token. |
source | string | onchain or clob. |
from / to | RFC3339 | Time window. |
bucket | string | Currently 5m. |
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns ExecutionQualityPoint[]
/v1/analytics/liquidity-fragilityHow quickly displayed liquidity evaporates under pressure, in 5-minute buckets.
| Parameter | Type | Description |
|---|---|---|
condition_id | string | Filter to one market. |
token_id | string | Filter to one outcome token. |
source | string | clob. |
from / to | RFC3339 | Time window. |
bucket | string | Currently 5m. |
limit | integer | Maximum rows to return. |
offset | integer | Rows to skip before returning results. |
Returns LiquidityFragilityPoint[]
/v1/analytics/informed-flowDaily informed-flow metrics — where the smart money is trading.
| Parameter | Type | Description |
|---|---|---|
source | string | onchain or clob. |
from / to | date | Date window. |
bucket | string | 1d or daily. |
limit | integer | Maximum rows to return. |
offset | integer | Rows 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.
/v1/ws/marketsLive market updates. Subscribe to specific condition ids, or "*" for everything.
Returns MarketUpdate
{ "subscribe": ["0x1a9e…", "*"] }
{ "unsubscribe": ["0x1a9e…"] }/v1/ws/tradesThe global trade firehose. No subscription message needed — trades start flowing on connect.
Returns TradeUpdate
/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
@tenz-app:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
pnpm add @tenz-app/polysink-sdkimport { 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 });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));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
/healthPublic liveness probe. Returns { "status": "ok" }.
Returns { status }
/health/matcherPublic matcher readiness probe. Returns ok once the matcher snapshot is loaded, starting before that.
Returns { status }