Server-built OHLCV candles from real onchain trades. Anchor-based pagination with buy/sell volume split, VWAP, and trade counts. Resolutions from 1m to 1d.
Build OHLCV candles directly from settled CLOB fills. Each candle includes open, high, low, close, total volume in USD and shares, buy and sell volume split, trade count, and VWAP. Backed by the same trade source asDocumentation Index
Fetch the complete documentation index at: https://polynode.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
/v2/onchain/trades, so candles and trades stay in lockstep.
Pagination is anchor-based rather than range-based. Each request returns up to 1000 trades worth of candles, anchored at a timestamp, block, or transaction hash. Walk older history by passing the cursor from the previous response. This is the same model used by major exchange APIs (Binance, Kraken, Coinbase) and avoids open-ended range queries timing out on hot markets.
The response includes a window.duration_seconds field so callers immediately see how dense the market is — a hot market may pack 500 trades into 10 seconds, while a sleepy market may span weeks.
| Endpoint | Source | Best for |
|---|---|---|
GET /v2/onchain/candles/{token_id} | Real settled CLOB fills on Polygon | Charting any Polymarket outcome token with full history, VWAP, and buy/sell split. This is the endpoint you want for a price chart. |
GET /v1/candles/{token_id} | Live rolling in-memory buffer | Short, live tail of recent activity. No historical depth, no pagination. Useful as a lightweight live poll but not for charts. |
GET /v1/crypto/candles | Chainlink oracle feed | 5-minute OHLC for crypto assets (BTC, ETH, SOL…). These are the same prices that resolve Polymarket’s short-form crypto markets — not CLOB trade data. |
/v2/onchain/candles.
/v2/movers returns the biggest daily movers with the full outcomes array already enriched — one REST call gives you the token_id for both the Yes and No outcome without any extra lookups.
outcomes[0].token_id is the Yes side. That’s the identifier you pass to the candles endpoint.
/v2/trending has the exact same shape if you’d rather chart what’s popular than what’s moving.
window.duration_seconds tells you the 500 trades covered ~71 minutes of wall time — a moderately active market. The header fields (question, outcome, image, condition_id) are included so a chart header can render in the same round trip.
That’s the full loop: discover → chart, two REST calls, everything you need.
pagination.older_end_ts. Pass it back as anchor_ts on the next call to fetch the window immediately before it.
older_end_ts → anchor_ts until you have the depth you need.
| Parameter | Type | Required | Description |
|---|---|---|---|
token_id | string | One of these | Outcome token ID. Can also be passed as ?token_id= query param. |
| Parameter | Type | Default | Description |
|---|---|---|---|
token_id | string | — | Outcome token ID (alternative to path param) |
condition_id | string | — | Condition ID. Errors if the condition has multiple outcomes — pass token_id to disambiguate. |
market_slug | string | — | Market slug. Errors if the slug has multiple outcomes — pass token_id to disambiguate. |
resolution | string | 1h | Bucket size: 1m, 5m, 15m, 1h, 4h, 1d |
limit | integer | 500 | Trades per page. Clamped to [100, 1000]. The candles are built from this trade window. |
direction | string | before | before returns the limit trades ending at the anchor (newest-first walk). after returns the limit trades starting at the anchor (oldest-first walk). |
anchor_ts | integer | now | Unix timestamp anchor |
anchor_block | integer | — | Polygon block number anchor. Resolved to its block timestamp. |
anchor_tx | string | — | Polygon transaction hash anchor. Resolved to its block timestamp. |
gap_fill | boolean | false | When true, empty buckets between active candles are filled with flat carry-forward candles (O=H=L=C=prev_close, volume=0). |
token_id, condition_id, or market_slug is required. If multiple anchor params are passed, precedence is anchor_tx > anchor_block > anchor_ts.
| Field | Type | Description |
|---|---|---|
time | number | Bucket start time in milliseconds since epoch (TradingView convention) |
open | number | First trade price in the bucket |
high | number | Highest trade price in the bucket |
low | number | Lowest trade price in the bucket |
close | number | Last trade price in the bucket |
volume | number | Total volume in USD |
volume_shares | number | Total volume in outcome shares |
volume_buy | number | USD volume where the taker was buying the outcome token (aggressor buys) |
volume_sell | number | USD volume where the taker was selling the outcome token (aggressor sells) |
trades | number | Count of fills in the bucket |
vwap | number | Volume-weighted average price for the bucket |
| Field | Type | Description |
|---|---|---|
window.start_ts | number | Unix timestamp of the oldest trade in the window |
window.end_ts | number | Unix timestamp of the newest trade in the window |
window.trade_count | number | Number of trades that built these candles |
window.duration_seconds | number | Wall-clock span of the window. Use this to gauge market density. |
| Field | Type | Description |
|---|---|---|
pagination.older_end_ts | number | Pass as anchor_ts with direction=before to fetch the next older window |
pagination.newer_start_ts | number | Pass as anchor_ts with direction=after to fetch the next newer window |
question, slug, outcome, condition_id, and image are pulled from our market index. Returned alongside the candles so a chart can render header metadata in one round trip.
pagination.older_end_ts. Pass that as anchor_ts to fetch the previous window.
direction=after to walk forward from a specific timestamp.
gap_fill=true to fill them with flat carry-forward candles for charting libraries that expect a continuous time axis.
| Status | Response | Condition |
|---|---|---|
| 400 | {"error": "token_id, condition_id, or market_slug required"} | No market identifier passed |
| 400 | {"error": "Invalid resolution. Use one of: 1m, 5m, 15m, 1h, 4h, 1d"} | Bad resolution value |
| 400 | {"error": "condition_id resolves to multiple outcomes — pass token_id to select one"} | Multi-outcome condition_id |
| 400 | {"error": "market_slug resolves to multiple outcomes — pass token_id to select one"} | Multi-outcome market_slug |
| 401 | {"error": "API key required. Pass via ?key= or x-api-key header."} | Missing API key |
| 403 | {"error": "V2 endpoints require a paid plan. See polynode.dev/pricing for details."} | Free tier key |
| 429 | {"error": "Rate limited. N req/s for your tier.", "retryAfterMs": ...} | Rate limited |
volume_buy and volume_sell are taker-side attributions — i.e. the side that lifted/hit the book. Same convention as every major exchange API.pagination.older_end_ts. Use window.duration_seconds in each response to gauge market density up front.CTF outcome token ID
Alternative to token_id. Errors if multi-outcome.
Alternative to token_id. Errors if multi-outcome.
Bucket size
1m, 5m, 15m, 1h, 4h, 1d Trades per page (clamped 100-1000)
100 <= x <= 1000Walk direction from anchor
before, after Unix timestamp anchor (defaults to now)
Polygon block number anchor
Polygon transaction hash anchor
Fill empty buckets with carry-forward candles
OHLCV candles built from trade window