Skip to main content
GET
/
v2
/
onchain
/
candles
/
{token_id}
Candles (trade-indexed OHLCV)
curl --request GET \
  --url https://api.polynode.dev/v2/onchain/candles/{token_id}

Documentation Index

Fetch the complete documentation index at: https://polynode.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

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 as /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.

Which candles endpoint should I use?

PolyNode exposes three candle-shaped endpoints. They cover different data sources and are not interchangeable.
EndpointSourceBest for
GET /v2/onchain/candles/{token_id}Real settled CLOB fills on PolygonCharting 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 bufferShort, live tail of recent activity. No historical depth, no pagination. Useful as a lightweight live poll but not for charts.
GET /v1/crypto/candlesChainlink oracle feed5-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.
If you’re building a chart for a Polymarket market, use /v2/onchain/candles.

Build a chart in 2 calls

The fastest way to go from “I have an API key” to “I have candles on screen.” Every response below is a real capture — you can paste the curls and get back the same shape.

1. Find a market and grab the token you want to chart

/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.
curl "https://api.polynode.dev/v2/movers?limit=3" \
  -H "x-api-key: YOUR_KEY"
{
  "markets": [
    {
      "id": "1707841",
      "slug": "israel-x-hezbollah-ceasefire-by-april-30-2026-989-656",
      "question": "Israel x Hezbollah ceasefire by April 30, 2026?",
      "condition_id": "0xc7140ddb5ae5dc94d4553fb05d4600816f33ff024844cebe8326f4c41c4a1a47",
      "outcomes": [
        { "name": "Yes", "token_id": "71076253073516159380702286801576688253388973161726933428722204989810362065275", "price": 0.674 },
        { "name": "No",  "token_id": "38902668316823899581329108924389881286009857048696806385615295625967267371713", "price": 0.326 }
      ],
      "one_day_price_change": 0.3815
    }
  ]
}
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.

2. Pull candles for that token

TOKEN=71076253073516159380702286801576688253388973161726933428722204989810362065275
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN?resolution=5m&limit=500" \
  -H "x-api-key: YOUR_KEY"
{
  "token_id": "71076253073516159380702286801576688253388973161726933428722204989810362065275",
  "resolution": "5m",
  "window": {
    "start_ts": 1776274178,
    "end_ts": 1776278436,
    "trade_count": 500,
    "duration_seconds": 4258
  },
  "count": 16,
  "candles": [
    { "time": 1776273900000, "open": 0.82,   "high": 0.8221, "low": 0.82,  "close": 0.82,  "volume": 1842.3, "trades": 16, "vwap": 0.8205 },
    { "time": 1776274200000, "open": 0.831,  "high": 0.8349, "low": 0.765, "close": 0.781, "volume": 6194.1, "trades": 49, "vwap": 0.7912 },
    { "time": 1776276600000, "open": 0.741,  "high": 0.766,  "low": 0.62,  "close": 0.62,  "volume": 9338.7, "trades": 68, "vwap": 0.6823 }
  ],
  "pagination": { "older_end_ts": 1776274177, "newer_start_ts": 1776278437 },
  "question": "Israel x Hezbollah ceasefire by April 30, 2026?",
  "outcome": "Yes",
  "condition_id": "0xc7140ddb5ae5dc94d4553fb05d4600816f33ff024844cebe8326f4c41c4a1a47",
  "image": "https://polymarket-upload.s3.us-east-2.amazonaws.com/israel+lebanon+dove+flags.png"
}
The 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.

3. Walk older history

Each response returns pagination.older_end_ts. Pass it back as anchor_ts on the next call to fetch the window immediately before it.
# Older page, using the anchor from the previous response
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN?resolution=5m&limit=500&anchor_ts=1776274177" \
  -H "x-api-key: YOUR_KEY"
Real response header from this exact call:
{
  "window": { "start_ts": 1776267442, "end_ts": 1776274174, "trade_count": 500, "duration_seconds": 6732 },
  "count": 23,
  "pagination": { "older_end_ts": 1776267441, "newer_start_ts": 1776274175 }
}
Same token, 500 older trades, 23 candles over ~112 minutes. Keep walking by chaining older_end_ts → anchor_ts until you have the depth you need.

Request

GET /v2/onchain/candles/{token_id}
You can also pass the market identifier as a query parameter instead of a path parameter:
GET /v2/onchain/candles?token_id=...

Path parameters

ParameterTypeRequiredDescription
token_idstringOne of theseOutcome token ID. Can also be passed as ?token_id= query param.

Query parameters

ParameterTypeDefaultDescription
token_idstringOutcome token ID (alternative to path param)
condition_idstringCondition ID. Errors if the condition has multiple outcomes — pass token_id to disambiguate.
market_slugstringMarket slug. Errors if the slug has multiple outcomes — pass token_id to disambiguate.
resolutionstring1hBucket size: 1m, 5m, 15m, 1h, 4h, 1d
limitinteger500Trades per page. Clamped to [100, 1000]. The candles are built from this trade window.
directionstringbeforebefore returns the limit trades ending at the anchor (newest-first walk). after returns the limit trades starting at the anchor (oldest-first walk).
anchor_tsintegernowUnix timestamp anchor
anchor_blockintegerPolygon block number anchor. Resolved to its block timestamp.
anchor_txstringPolygon transaction hash anchor. Resolved to its block timestamp.
gap_fillbooleanfalseWhen true, empty buckets between active candles are filled with flat carry-forward candles (O=H=L=C=prev_close, volume=0).
Exactly one of token_id, condition_id, or market_slug is required. If multiple anchor params are passed, precedence is anchor_tx > anchor_block > anchor_ts.

Response

{
  "token_id": "85713379202339219190689591569895900631137520291992037720582155738835687752247",
  "resolution": "1m",
  "window": {
    "start_ts": 1776276218,
    "end_ts": 1776276228,
    "trade_count": 500,
    "duration_seconds": 10
  },
  "count": 1,
  "candles": [
    {
      "time": 1776276180000,
      "open": 0.78,
      "high": 0.93,
      "low": 0.77,
      "close": 0.9,
      "volume": 7941.87,
      "volume_shares": 9094.21,
      "volume_buy": 1569.20,
      "volume_sell": 6372.67,
      "trades": 500,
      "vwap": 0.8733
    }
  ],
  "pagination": {
    "older_end_ts": 1776276217,
    "newer_start_ts": 1776276229
  },
  "question": "Bitcoin Up or Down - April 15, 2:00PM-2:05PM ET",
  "slug": "btc-updown-5m-1776276000",
  "outcome": "Up",
  "condition_id": "0x...",
  "image": "https://polymarket-upload.s3.us-east-2.amazonaws.com/BTC+fullsize.png"
}

Candle fields

FieldTypeDescription
timenumberBucket start time in milliseconds since epoch (TradingView convention)
opennumberFirst trade price in the bucket
highnumberHighest trade price in the bucket
lownumberLowest trade price in the bucket
closenumberLast trade price in the bucket
volumenumberTotal volume in USD
volume_sharesnumberTotal volume in outcome shares
volume_buynumberUSD volume where the taker was buying the outcome token (aggressor buys)
volume_sellnumberUSD volume where the taker was selling the outcome token (aggressor sells)
tradesnumberCount of fills in the bucket
vwapnumberVolume-weighted average price for the bucket

Window fields

FieldTypeDescription
window.start_tsnumberUnix timestamp of the oldest trade in the window
window.end_tsnumberUnix timestamp of the newest trade in the window
window.trade_countnumberNumber of trades that built these candles
window.duration_secondsnumberWall-clock span of the window. Use this to gauge market density.

Pagination fields

FieldTypeDescription
pagination.older_end_tsnumberPass as anchor_ts with direction=before to fetch the next older window
pagination.newer_start_tsnumberPass as anchor_ts with direction=after to fetch the next newer window

Market enrichment fields

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.

Examples

Default — last 500 trades, 1h buckets

curl "https://api.polynode.dev/v2/onchain/candles/85713379202339219190689591569895900631137520291992037720582155738835687752247?resolution=1h" \
  -H "x-api-key: YOUR_KEY"

Walking backwards through history

Each response includes pagination.older_end_ts. Pass that as anchor_ts to fetch the previous window.
# First page — most recent 500 trades
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN_ID?resolution=15m&limit=500" \
  -H "x-api-key: YOUR_KEY"

# Next page — 500 trades older than the first
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN_ID?resolution=15m&limit=500&anchor_ts=OLDER_END_TS_FROM_PREVIOUS" \
  -H "x-api-key: YOUR_KEY"

Forward walk from a starting point

Use direction=after to walk forward from a specific timestamp.
# Earliest 500 trades on this market
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN_ID?resolution=1h&direction=after&anchor_ts=0" \
  -H "x-api-key: YOUR_KEY"

Anchor by block number

Useful when you want to align candles to a specific Polygon block — for example to compare against another onchain event.
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN_ID?resolution=5m&anchor_block=70000000" \
  -H "x-api-key: YOUR_KEY"

Anchor by transaction hash

Same idea, but resolved from a transaction hash. Useful for “show me what the chart looked like around this trade.”
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN_ID?resolution=1m&anchor_tx=0xfffff7ed9080f46d7975f905e7f9358c436a1b177c6e19e54510c3ba6dcfddc4" \
  -H "x-api-key: YOUR_KEY"

Gap-filled candles

By default, buckets with zero trades are simply absent from the response. Set gap_fill=true to fill them with flat carry-forward candles for charting libraries that expect a continuous time axis.
curl "https://api.polynode.dev/v2/onchain/candles/$TOKEN_ID?resolution=1m&gap_fill=true" \
  -H "x-api-key: YOUR_KEY"

Error responses

StatusResponseCondition
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

Notes

  • Candles are built from real onchain fills, not midpoint snapshots. Sparse markets will show sparse candles.
  • 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.
  • The trade window is fixed-page, not range-bound. To cover a long history, walk pages via pagination.older_end_ts. Use window.duration_seconds in each response to gauge market density up front.
  • Block and transaction anchors are resolved via Polygon RPC and cached for 24 hours — repeated queries against the same anchor are free after the first hit.
  • Responses are cached server-side for 5 minutes per unique anchor, direction, and limit.

Path Parameters

token_id
string
required

CTF outcome token ID

Query Parameters

condition_id
string

Alternative to token_id. Errors if multi-outcome.

market_slug
string

Alternative to token_id. Errors if multi-outcome.

resolution
enum<string>
default:1h

Bucket size

Available options:
1m,
5m,
15m,
1h,
4h,
1d
limit
integer
default:500

Trades per page (clamped 100-1000)

Required range: 100 <= x <= 1000
direction
enum<string>
default:before

Walk direction from anchor

Available options:
before,
after
anchor_ts
integer

Unix timestamp anchor (defaults to now)

anchor_block
integer

Polygon block number anchor

anchor_tx
string

Polygon transaction hash anchor

gap_fill
boolean
default:false

Fill empty buckets with carry-forward candles

Response

OHLCV candles built from trade window