Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.
/api/v1/markets/{id}/candlesGET
Get OHLC candles for a market, optionally scoped to a source bucket window.
Authorization
bearerAuth *Bearer <token>
Clerk session JWT, or an API key (the ak_ prefix), sent as a Bearer token or an ?api_key= query parameter. Each endpoint requires the read scope for its resource (e.g. org:rates:read for rates). Token in: header
Query Parameters
page?integer
Page number
Default: 1Min: 1
per_page?integer
Items per page
Default: 100Min: 1Max: 500
from?string (date-time)
Inclusive lower bound on timestamp
to?string (date-time)
Exclusive upper bound on timestamp
interval?integer
Candle period length in minutes
Default: 60Min: 1
Response
200 · OK
data?object[]
Show item properties
timestamp *string (date-time)
End of the candle period, in UTC. The candle covers the requested interval minutes ending at this instant.
yes_bid?numbernull
Best YES bid at the end of the period, in cents (0-100), so 47 means a 47% probability. Absent when no bid was recorded for the period.
yes_ask?numbernull
Best YES ask at the end of the period, in cents (0-100), so 49 means a 49% probability. Absent when no ask was recorded for the period.
mid *number
Reference price for the period, in cents (0-100), resolved in order: the midpoint of yes_bid and yes_ask when both are present, otherwise the period's mean traded price, otherwise the closing traded price. It is therefore not always a book midpoint and can be identical to close, so do not read it as a quote without checking yes_bid and yes_ask.
close?numbernull
Last traded price in the period, in cents (0-100). Absent when the period had no trades.
volume?numbernull
Contracts traded during the period. Reported for Kalshi candles only; Polymarket candles are built from a midpoint price feed that carries no trade sizes, so this is absent for them.
source *"kalshi_candlestick" | "kalshi_historical_candlestick" | "polymarket_clob_history"
Where the row came from. polymarket_clob_history rows are built from the CLOB prices-history midpoint feed rather than from a trade tape.
synthetic_book *boolean
True when yes_bid/yes_ask were synthesized as a zero-spread book from a midpoint-only feed (source = polymarket_clob_history) rather than observed on the venue; clients should badge these books as synthetic.
meta?object
Show properties
total?integer
Total number of records matching the request across every page, not just the number returned in this one.
page?integer
The 1-based page number this response covers.
per_page?integer
Maximum number of items on a page. The last page may hold fewer.
total_pages?integer
Number of pages available at this per_page. It is at least 1, even when nothing matched.
has_next?boolean
True when a page exists after this one.
has_prev?boolean
True when this is not the first page.
403 · The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.
error *string
Human-readable reason the request was refused.
status *integer
HTTP status code, repeated in the body.
upgrade_url?string (uri)
Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase.
404 · Market not found
error?string
Stable, machine-readable code identifying the failure; branch on this rather than on message. One of bad_request, unauthorized, forbidden, not_found, conflict, service_unavailable, upstream_error, service_error, or internal_error.
message?string
Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld.
429 · The paid organization's minute or UTC-day request budget is exhausted.
error *"rate_limited"
Always rate_limited. Branch on this to detect a throttled request.
limit *"rpm" | "daily"
Which limit was hit: rpm for the per-minute cap or daily for the daily one.
message *string
Human-readable explanation naming the limit that was exceeded.
upgrade_url?string (uri)
Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase.
Request example
curl -X GET "https://api.dev.adjacent.markets/api/v1/markets/<id>/candles" \ -H "Authorization: Bearer <token>"
Response example
{ "data": [ { "timestamp": "2026-06-01T14:00:00Z", "yes_bid": 47, "yes_ask": 49, "mid": 48, "close": 48, "volume": 12500, "source": "kalshi_candlestick", "synthetic_book": false }, { "timestamp": "2026-06-01T13:00:00Z", "yes_bid": 47, "yes_ask": 47, "mid": 47, "close": 47, "volume": 9800, "source": "polymarket_clob_history", "synthetic_book": true } ], "meta": { "total": 2, "page": 1, "per_page": 100, "total_pages": 1, "has_next": false, "has_prev": false } }