Schemas and Data Formats
Every object Synpath returns, field by field, and the conventions that hold across all of them.
Synpath maps every venue onto one set of types. The same Market comes back from Kalshi, Polymarket and Polymarket US; the same Order is what you send and what you read back. The types are Pydantic models, so they validate on the way in, serialize to JSON on the way out, and appear unchanged in the REST API's OpenAPI schema.
from synpath import Market, Order, OrderRequest, Position # read and trading types alike
market = synpath.Client().fetch_market("kalshi:KXFEDDECISION-26SEP-C25")
market.model_dump() # a plain dict, JSON-ready
Market.model_validate(data) # and back againConventions
Identifiers
id on a market or event is a Synpath ID, venue:native. The venue's own id is kept beside it on venue_market_id / venue_event_id. See Synpath IDs.
Timestamps
Every timestamp is UTC. Fields ending in _timestamp, _at or named timestamp are integers in milliseconds since epoch. Where the same instant is useful to read, a sibling field ending in _datetime carries it as ISO 8601 (2026-09-17T14:00:00Z). Never seconds, never mixed.
Prices
Every price is a probability in 0 to 1: 0.42 means 42¢ per contract on a $1 payout, on every venue, even where the venue itself prints cents. Every price is the YES price. Where you asked for the NO side (market.no.quote, a book with side="no") the object says so, and its prices are what NO costs.
Read types carry prices as float. Trading types carry them as Decimal, because a price that will be signed and sent must be exact; strings and ints are accepted on the way in.
Amounts and units
Order sizes are contracts (shares). Volume and liquidity are labelled with their unit, contracts or collateral, because Kalshi counts one and Polymarket the other.
Missing values
A figure a venue did not publish is None, never 0. A mid without both sides quoted is None. A bool a venue did not answer (neg_risk, mutually_exclusive) is None, never False.
The venue's own payload
Every object has info: the venue's response, untouched, for the field Synpath did not map. On aMarket it is the raw catalog row; on an Order it holds the request that was sent and the answer that came back.
yes and no are found by their place in the venue's payload, never by label text: some Kalshi markets label both sides identically.Market data
Event
A real-world question grouping one or more markets.
| Field | Type | Meaning |
|---|---|---|
id | str | Synpath ID, venue:native |
venue | str | kalshi, polymarket or polymarket_us |
venue_event_id | str | The venue's own event id |
title | str | |
description | str | None | |
slug | str | None | URL name, where the venue has one |
markets | list[Market] | The markets under this event |
status | MarketStatus | The most open status among its markets |
native_status | str | None | The venue's own status word |
category | str | None | |
tags | list[str] | |
series_id | str | None | The recurring series above the event, where the venue has the tier |
mutually_exclusive | bool | None | Whether exactly one market resolves YES. None when the venue did not say |
close_timestamp | int | None | ms; the latest close among its markets |
close_datetime | str | None | ISO 8601 |
url | str | None | The event page on the venue |
image_url | str | None | |
settlement_sources | list[dict] | Who decides the outcomes: [{name, url}] |
info | dict | The venue's payload |
Market
One tradeable proposition: the thing that resolves and pays out.
| Field | Type | Meaning |
|---|---|---|
id | str | Synpath ID, venue:native |
venue | str | |
venue_market_id | str | The venue's own id: ticker, Gamma id or slug |
event_id | str | None | The parent event's Synpath ID |
title | str | The whole question |
description | str | None | Resolution criteria, verbatim from the venue |
slug | str | None | |
yes | Outcome | The YES side and its quote |
no | Outcome | The NO side and its quote |
status | MarketStatus | unopened, open, closed or settled |
native_status | str | None | The venue's own word |
active | bool | Accepting orders right now; separate from status because a venue can halt without changing lifecycle |
market_type | str | binary, categorical, scalar or unknown |
open_timestamp | int | None | ms |
close_timestamp | int | None | ms; when trading stops |
resolution_timestamp | int | None | ms; the venue's scheduled resolution, not when it actually resolved |
open_datetime, close_datetime, resolution_datetime | str | None | ISO 8601 twins of the above |
tick_size | float | None | Minimum price increment |
face_value | float | What one contract pays at settlement; 1.0 on every venue today |
book_model | BookModel | Whether both sides share one book |
stats | MarketStats | Volume, liquidity, open interest |
url | str | None | |
image_url | str | None | |
category | str | None | |
tags | list[str] | |
series_id | str | None | Kalshi keys its fee schedule on this |
outcome_label | str | None | This market's short name inside its event ("50+ bps decrease") |
neg_risk | bool | None | Whether a NO here converts into YES exposure on the event's other markets |
settlement_sources | list[dict] | Who rules on the outcome: [{name, url}] |
info | dict | The venue's payload; Polymarket's conditionId lives here |
Outcome
One side of a market. It has no id: the side is said on the call.
| Field | Type | Meaning |
|---|---|---|
label | str | The venue's display text: Yes, No, Up, a team name. Never used for logic |
quote | Quote | In this side's own terms: the NO quote is what NO costs |
venue_token_id | str | None | Polymarket's CLOB token id for this side; None elsewhere |
price_change_24h | float | None | Absolute probability change over 24h, where published |
info | dict |
Quote
Four prices, each independently nullable, because each is absent for its own reason.
| Field | Type | Meaning |
|---|---|---|
bid | float | None | Best price someone will pay. None when nobody is bidding |
bid_size | float | None | Contracts at the bid |
ask | float | None | Best price someone will sell at |
ask_size | float | None | |
mid | float | None | (bid + ask) / 2, only when both sides are quoted |
last | float | None | Last traded price; can be months old on a thin market |
last_timestamp | int | None | ms; always read it with last |
last_datetime | str | None | |
spread | float | None | Computed: ask − bid, or None |
MarketStats
Venue-reported headline numbers, with their units spelled out.
| Field | Type | Meaning |
|---|---|---|
volume_24h | float | None | |
volume_total | float | None | |
liquidity | float | None | Resting on the book |
open_interest | float | None | Contracts outstanding |
volume_unit | contracts | collateral | None | Kalshi counts contracts, Polymarket dollars |
liquidity_unit | contracts | collateral | None | |
as_of | int | None | ms; when the venue says these were current |
OrderBook
Resting orders on one side of a market, best price first on both sides whatever the venue stores.
| Field | Type | Meaning |
|---|---|---|
market_id | str | Synpath ID |
side | yes | no | Which side the prices are in |
venue | str | |
bids | list[OrderLevel] | Descending by price |
asks | list[OrderLevel] | Ascending by price |
best_bid | OrderLevel | None | Computed: bids[0], or None on an empty side |
best_ask | OrderLevel | None | Computed: asks[0] |
timestamp | int | None | ms |
datetime | str | None | |
book_model | BookModel | |
derived | bool | True when this side was mirrored from the other side's book (Kalshi, Polymarket US) |
depth_scope | full | top_n | unknown | Whether the levels are the whole book or a requested depth |
info | dict |
OrderLevel
| Field | Type | Meaning |
|---|---|---|
price | float | 0 to 1, in the book's side |
size | float | Contracts resting |
Trade
One public execution, in the YES price.
| Field | Type | Meaning |
|---|---|---|
id | str | |
market_id | str | Synpath ID |
timestamp | int | ms |
datetime | str | |
price | float | The YES price: a NO buy at 0.30 is reported at 0.70 |
amount | float | Contracts |
side | buy | sell | unknown | What the taker did on the YES leg: buy took YES, sell took NO |
info | dict |
Candle
One OHLCV bar, in the YES price, labelled with where its prices came from.
| Field | Type | Meaning |
|---|---|---|
timestamp | int | ms; start of the bar |
datetime | str | |
open, high, low, close | float | None | None when nothing traded and the venue has no substitute |
volume | float | None | None when the venue publishes no volume for the bar, which is not zero |
trade_count | int | None | |
price_source | PriceSource | trade, bid_ask_mid or sampled_mid; read it before using the bar |
bid_close, ask_close | float | None | Book state at the close, where the venue reports it |
info | dict |
FeeSchedule
What trading a market costs, before you trade it.
| Field | Type | Meaning |
|---|---|---|
venue | str | |
scope | venue | series | market | What the schedule applies to |
scope_id | str | |
fee_type | str | quadratic (Kalshi) or quadratic_theta (Polymarket, Polymarket US) |
multiplier | float | None | Kalshi: fee per contract is multiplier × p × (1 − p) |
taker_rate, maker_rate | float | None | Per-trade rates, where the venue publishes them |
exponent | float | None | Polymarket: the power on p × (1 − p); 1 on every live market |
rounding | str | None | |
info | dict |
FeeSchedule.estimate(price, contracts, taker=True) evaluates the formula, or returns None when it is unknown.
Series
A recurring question above an event (a weekly Fed decision). Kalshi and Polymarket US only.
| Field | Type | Meaning |
|---|---|---|
id | str | The venue's series id |
venue | str | |
title | str | None | |
category | str | None | |
tags | list[str] | |
fee | FeeSchedule | None | Kalshi publishes fees per series |
settlement_sources | list[dict] | |
info | dict |
Page
Every listing call returns a Page: a list with a next_cursor attribute. Pass the cursor back to continue; None means the end. Over HTTP a list is enveloped as {"data": [...], "next_cursor": "...", "count": n}.
Trading
Trading types carry money as Decimal. An order names a market and a side on the YES leg; see Orders for what each venue does with that.
OrderRequest
What you send. Validated against the market's tick and minimum size before anything is signed.
| Field | Type | Meaning |
|---|---|---|
market_id | str | Synpath ID; a bare native id is accepted by the venue's own adapter |
side | Side | buy takes YES, sell takes NO |
amount | Decimal | Contracts |
type | OrderType | limit (default) or market for a venue; the rest are held by the engine |
price | Decimal | None | The YES price. Required for a limit; the protection price for a market order |
stop_price | Decimal | None | For stop orders |
time_in_force | TimeInForce | gtc (default), ioc, fok, gtd, day |
expires_at | int | None | ms; required with gtd |
post_only | bool | Rest or be refused; never take |
reduce_only | bool | Only reduce a position. On Polymarket this is what makes sell sell your YES tokens instead of buying NO |
client_order_id | str | None | Your idempotency key; generated if absent |
account | Account | None | Which venue account, where you hold several |
book | str | None | The strategy or desk this belongs to; positions and P&L roll up by it |
trader | str | None | |
tags | dict[str, str] | Free-form, kept on the order |
notes | str | None | |
params | dict | Venue-specific extras passed through untouched |
Order
An order as the venue, or the engine, reports it.
| Field | Type | Meaning |
|---|---|---|
id | str | The venue's order id |
client_order_id | str | None | Yours |
venue | str | |
account | Account | None | |
market_id | str | Synpath ID |
side | Side | On the YES leg, whatever the venue's own wording |
type | OrderType | |
time_in_force | TimeInForce | |
status | OrderStatus | |
held_by | venue | engine | Where the order rests |
price | Decimal | None | The YES price |
stop_price | Decimal | None | |
amount | Decimal | Contracts asked for |
filled | Decimal | Contracts matched so far |
remaining | Decimal | None | amount − filled unless the venue says otherwise |
average_price | Decimal | None | Of what filled |
cost | Decimal | None | Collateral committed so far |
fee, fee_currency | Decimal | None, str | None | Charged so far |
last_fill_price, last_fill_amount | Decimal | None | |
post_only, reduce_only | bool | |
expires_at, created_at, updated_at | int | None | ms |
parent_id | str | None | The engine-held parent this is a child of |
queue_priority_preserved | bool | None | After an edit: whether the order kept its place in the queue |
book, trader, tags | | As on the request |
info | dict | The request sent and the venue's answer |
Fill
One execution of your order, in the YES price.
| Field | Type | Meaning |
|---|---|---|
id | str | |
order_id | str | |
client_order_id | str | None | |
venue | str | |
account | Account | None | |
market_id | str | Synpath ID |
side | Side | On the YES leg |
price | Decimal | The YES price |
amount | Decimal | Contracts |
fee, fee_currency | Decimal | None, str | None | |
liquidity | maker | taker | unknown | Which side of the match you were |
settlement | matched | confirmed | failed | Polymarket: a fill matches, then confirms on chain, or fails. Final elsewhere |
timestamp | int | ms |
info | dict |
Position
One market's position, net on the YES leg, with the token inventories kept beside it where a venue does not net.
| Field | Type | Meaning |
|---|---|---|
venue | str | |
account | Account | None | |
market_id | str | Synpath ID |
side | long | short | flat | long holds YES, short holds NO |
contracts | Decimal | Net exposure on the side named, positive |
inventory_yes, inventory_no | Decimal | None | Tokens actually held per side (Polymarket); None elsewhere |
entry_price | Decimal | None | Average cost, in the YES price |
mark_price | Decimal | None | |
unrealized_pnl, realized_pnl | Decimal | None | |
margin | Decimal | None | Collateral locked, where the venue reports it |
resolved | bool | The market has resolved |
final | bool | And is past any dispute window |
won | bool | None | |
payout | Decimal | None | |
redeemable | Decimal | None | Payout waiting to be claimed on chain (Polymarket) |
timestamp | int | None | ms |
info | dict |
Balance
Per venue account, never pooled.
| Field | Type | Meaning |
|---|---|---|
venue | str | |
account | Account | |
currency | str | USD, or pUSD on Polymarket |
total | Decimal | |
available | Decimal | |
locked | Decimal | None | Reserved by open orders, where the venue reports it |
buying_power | Decimal | None | The venue's own figure, or None. Never zero |
timestamp | int | None | ms |
info | dict |
Settlement
A resolved market paid out on your position.
| Field | Type | Meaning |
|---|---|---|
venue | str | |
account | Account | None | |
market_id | str | Synpath ID |
held | long | short | None | Which side you held into settlement |
result | str | None | The venue's result word: yes or no |
won | bool | None | |
amount | Decimal | None | Contracts settled |
cost, payout, pnl | Decimal | None | |
timestamp | int | None | ms |
info | dict |
FeeEstimate
What an order would cost, before it is placed.
| Field | Type | Meaning |
|---|---|---|
venue | str | |
market_id | str | |
side | Side | |
price | Decimal | The YES price it was estimated at |
amount | Decimal | |
taker_fee | Decimal | None | |
maker_fee | Decimal | None | Negative where the venue pays makers |
builder_fee | Decimal | None | |
currency | str | |
info | dict | The schedule used |
Account
One set of credentials at one venue, optionally one subaccount.
| Field | Type | Meaning |
|---|---|---|
venue | str | |
name | str | default unless you name it |
subaccount | str | None | Kalshi subaccount number, where used |
Enumerations
MarketStatus
| Value | Meaning |
|---|---|
unopened | Listed, not yet accepting orders |
open | Trading; active says whether orders are accepted right now |
closed | Trading has stopped; not yet paid |
settled | Resolved and paid out |
BookModel
| Value | Meaning |
|---|---|
shared_complement | One book serves both sides (Kalshi, Polymarket US); the NO view is the YES book mirrored |
native_per_outcome | Each side owns its own book (Polymarket) |
PriceSource
| Value | Meaning |
|---|---|
trade | Built from executions |
bid_ask_mid | No trades in the period; the midpoint of the venue's bid/ask bars |
sampled_mid | The venue publishes price samples, not bars, and these were bucketed by Synpath |
Side
| Value | Meaning |
|---|---|
buy | Take the YES side |
sell | Take the NO side |
OrderType
| Value | Meaning |
|---|---|
limit | Rests at a price. Native on every venue |
market | Takes what is resting, up to the protection price. Native where the venue has it, otherwise an immediate-or-cancel limit |
stop_market, stop_limit, trailing_stop | Held by the engine; submitted when the trigger is met |
iceberg, oco, bracket, twap, peg, smart_taker, rfq_taker | Held by the engine |
TimeInForce
| Value | Meaning |
|---|---|
gtc | Good till cancelled |
ioc | Immediate or cancel |
fok | Fill or kill |
gtd | Good till expires_at |
day | Rewritten by the engine to gtd at the session end; not a venue concept |
OrderStatus
| Value | Meaning |
|---|---|
pending | Accepted by Synpath, not yet acknowledged by the venue |
open | Resting at the venue; read filled and remaining |
pending_cancel, pending_replace | A cancel or edit is in flight |
closed | Fully filled |
canceled | Ended by a cancel; filled may be non-zero |
rejected | Refused by the venue |
expired | Time in force ran out |
waiting, triggered | An engine-held parent before and after its condition fired |
PositionSide
| Value | Meaning |
|---|---|
long | Holding YES |
short | Holding NO |
flat | Nothing |
Liquidity
| Value | Meaning |
|---|---|
maker | Your order was resting |
taker | Your order crossed |
unknown | The venue did not say |
SettlementState
| Value | Meaning |
|---|---|
matched | Matched, not yet confirmed on chain (Polymarket) |
confirmed | Final |
failed | Matched and then lost on chain; it never happened |

