Synpath
Core Concepts

Synpath IDs

Every market listing is assigned a unique Synpath ID: one identifier format used across every venue.

Why Synpath IDs?

Each exchange uses its own identifier system:

  • Kalshi uses tickers (e.g., KXBTC-24DEC31)
  • Polymarket uses condition IDs, token IDs, slugs and a numeric catalog id
  • Polymarket US uses slugs

Synpath IDs abstract this away, allowing you to:

  • Use one identifier format no matter which exchange a market trades on
  • Place orders with a single field: the venue is read off the id, and the order goes to the right exchange
  • Track a market's orders, positions and fills using the same ID you found it under

How they work

A Synpath ID is the venue's name, a colon, and the venue's own id for the listing. Nothing is hashed or re-keyed, so the part after the colon is what you would paste into the exchange's own website or API.

VenueSynpath IDWhat follows the colon
Kalshikalshi:KXFEDDECISION-26SEP-C25the market ticker
Polymarketpolymarket:2252244the numeric Gamma catalog id
Polymarket USpolymarket_us:tec-mlb-nlchamp-2026-09-27-atlthe market slug

When you search for markets, every result carries its Synpath ID alongside the exchange-native identifiers:

import synpath

client = synpath.Client()
market = client.fetch_markets(venue="kalshi", query="fed", limit=1)[0]

market.id                # "kalshi:KXFEDDECISION-26SEP-C25"
market.venue             # "kalshi"
market.venue_market_id   # "KXFEDDECISION-26SEP-C25", the exchange's own id
market.event_id          # "kalshi:KXFEDDECISION-26SEP", the event it belongs to

Use the Synpath ID everywhere: it names the market on every read and every order.

book = client.fetch_order_book(market.id)             # routed to Kalshi by the prefix
order = await client.create_order(OrderRequest(
    market_id=market.id, side="buy", type="limit", price="0.42", amount=10,
))
positions = await client.fetch_positions(market_id=market.id)

One Synpath ID per exchange listing

A Synpath ID identifies a single listing on a single exchange. If the same real-world outcome trades on both Kalshi and Polymarket, each listing has its own Synpath ID.

A market has two sides, YES and NO, and neither has an id of its own. The side is said on the call instead:

  • On an order, side="buy" takes YES and side="sell" takes NO. The price is always the YES price, so buying NO at 0.30 is written as side="sell", price=0.70.
  • On a book, fetch_order_book(market_id, side="no") is what NO costs.
  • On a market, market.yes.quote and market.no.quote are the two sides' prices.
The two sides are found by position in the venue's payload, never by label text. Some Kalshi markets label both sides identically, and a side picked by label is the one mistake that silently inverts a position.

Native ids are still there

Every venue adapter accepts its own bare native id as well, so synpath.Kalshi().fetch_market("KXFEDDECISION-26SEP-C25") works, and an id that names another venue is refused rather than sent to the wrong one. The other identifiers a venue publishes are kept on the object for anyone who needs them:

IdentifierWhere
Kalshi event tickermarket.event_id, event.venue_event_id
Kalshi series tickermarket.series_id
Polymarket condition id (on-chain)market.info["conditionId"]
Polymarket token ids (one per side)market.yes.venue_token_id, market.no.venue_token_id
Polymarket slugmarket.slug
Polymarket US numeric idmarket.info["id"]

Order ids

An order has two ids, for two different jobs.

  • order.id is the venue's id, assigned when the venue accepts the order. Use it to fetch, edit or cancel.
  • order.client_order_id is one you can choose before sending. It is the idempotency key: a retry reuses it, and a process that dies mid-submit asks the venue whether an order with that id exists before sending again. Left out, Synpath generates one.

An order id alone does not say which exchange it lives on, so cancels and lookups through synpath.Client take the market id too: cancel_order(order.id, market_id=order.market_id).

Across venues

To trade or track the same outcome across venues, Synpath's hosted catalog groups equivalent listings (their Synpath IDs) into one cross-venue asset. That is what the Unified Market Research tool shows, with a verdict on whether the settlement rules really say the same thing. From code, ask Match market or synpath.match_market() with any Synpath ID, and get back the same market on the other venues.

Where to next