File schemas

Two container formats, and two venues that do not share a field list. Everything below is a column or key you will actually find in a file, listed per dataset.

The two formats

Settlement feeds and klines are gzipped CSV with a header row. Market event streams are gzipped JSONL — one JSON object per line, in the order the frames arrived. Nothing is re-sorted on the way into the archive.

Settlement feeds — CSV (Polymarket side)

The same five columns for prices, twap30s and twap60s. This is the only place in the archive where three separate timestamps travel together.

feed_ts_msEvent time: the timestamp upstream put on the report (UTC ms)
valuePrice as a float, for convenience
full_accuracy_valueWhenever the relay publishes it, the same price as a fixed-point integer string (1e18). Use this to recompute outcomes, not value
server_ts_msWhen the upstream server sent it (UTC ms)
recv_msWhen we received it (UTC ms). All three are kept apart, never merged — so you can measure the capture path

Market events — the JSONL envelope (Polymarket side)

Every line in book, price_change, best_bid_ask and last_trade_price carries the same six top-level keys. Note there are TWO timestamps here, not three, and the event one is not called feed_ts_ms.

slugThe market this frame belongs to
asset_idWhich outcome token the frame is about. Null on price_change, because one of those lines carries the changes for both sides at once
event_typeSame name as the dataset
event_ts_msUpstream event time (UTC ms)
recv_msWhen we received it (UTC ms)
payloadThe upstream message, kept as it arrived

What is inside payload, per dataset

bookbids and asks, each an array of {price, size} objects, plus hash, market, asset_id and timestamp. One line is a snapshot of ONE outcome token — which one is the envelope asset_id — and carries both of its ladders. An empty array means that ladder holds no orders, not that it went unreported
price_changeprice_changes, an array whose items each carry hash, side, size, price, asset_id, best_ask and best_bid. Both outcome tokens appear in the same line, which is why the envelope asset_id is null
best_bid_askbest_bid, best_ask and spread, for one asset_id. Prices only — there are no sizes on this stream, so depth still comes from book or price_change
last_trade_priceside, size, price, fee_rate_bps and transaction_hash, for one asset_id

markets — one line per market

Metadata, the strike, and the settlement once it exists. The raw key holds the upstream market object unchanged, which is where the settlement configuration lives.

slug / asset / interval_secIdentity and duration. interval_sec is seconds
condition_id / token_idsOn-chain identifiers. token_ids has two entries and the FIRST is Up — established by measurement, not by assumption
start_sec / end_secMarket window, in SECONDS — not milliseconds like the event streams
resolved / outcome_pricesSettlement. ["1","0"] means Up won, ["0","1"] means Down won. Only a complete binary pair is meaningful
strike_valueThe price to beat, as a fixed-point integer string (1e18). Null when we cannot establish it honestly — never guessed from a nearby tick
rawThe upstream market object as received, including raw.cryptoMarketConfig — see how a market settles

klines — CSV

Derived from the settlement feed, so these are OHLC and there is no volume column. ticks counts settlement updates in the bucket; it is not traded size.

ts_msBucket start (UTC ms)
open / high / low / closePrices within the bucket
ticksHow many settlement updates fell in the bucket — an update count, not volume

Predict.fun does not share the schema above

Different column names, a different ladder shape, and different time units. If you subscribe to both platforms, treat them as two formats rather than one with extra fields.

prices (CSV)price_feed_id, symbol, provider, publish_time, server_ts, price, recv_ms. publish_time and server_ts are in SECONDS while recv_ms is milliseconds, and the price column is called price rather than value
orderbook (JSONL)market_id, category_slug, update_ts_ms, recv_ms, payload. Inside payload, bids and asks are arrays of [price, size] PAIRS — not {price, size} objects as on the Polymarket side — alongside version, orderCount, lastOrderSettled and settlementsPending
markets (JSONL)category_slug, asset, interval_label, market_id, price_feed_id, price_feed_symbol, price_feed_provider, condition_id, start_sec, end_sec, start_price, end_price and status. Prices here are ordinary decimal strings, not 1e18 fixed point

One thing worth knowing before you write a settlement check against this: status reports what upstream last told us, and a market stops being re-read once its end_price arrives. end_price is therefore the field that tells you a Predict.fun market has settled.

Working with one of these in particular: Polymarket order book data · Chainlink settlement data · Predict.fun historical data · Compared with other providers