Skip to Content
SkewtapeDocs

Get one market

GET
/v1/markets/{venue}/{market_id}

One market by venue and market_id. Missing or hidden from the plan is 404; the response never says which. A venue the data policy blocks is 403 blocked, whether or not the market exists.

Authorization

ApiKey
headerX-API-Key<token>

Data endpoints. Format st_live__ (ADR-0012).

Path Parameters

venue*string
market_id*string

Response Body

Market

application/json
  1. response
block_reason_code*|

Why fields are withheld: licence_undecided, licence_derived_only or geo_policy. Null when blocked is false.

blocked*boolean

True when the data policy withholds some of this row's fields for this request. Those fields are null and block_reason_code says why.

category?|

Venue category label when present.

close_at?|

Time the market closed for trading, UTC.

Formatdate-time
first_trade_at?|

Time of the first known trade, UTC.

Formatdate-time
last_trade_at?|

Time of the latest known trade, UTC.

Formatdate-time
market_id*string

Venue-native market identifier.

open_at?|

Time the market opened for trading, UTC.

Formatdate-time
outcomes*array<>

Selectable outcomes with labels and token ids.

quality_flags*array<string>

Quality markers such as volume_quality_flagged.

question?|

Market question text as published by the venue.

rules_hash?|

Hash of rules_text used to detect rule changes. Null when the data policy withholds rules_text.

rules_text?|

Full resolution rules text when available.

schema_version*string

Data schema version for this row.

slug?|

Short public slug when the venue publishes one.

source_kind*string

Source that supplied the market text.

Value in"chain""venue_api""bulk_dataset"
status*string

Life-cycle status of the market.

Value in"open""closed""resolved""voided"
updated_at*string

Time this row was last updated, UTC.

Formatdate-time
venue*string

Venue key that owns this market.

venue_event_id?|

The venue's own grouping key for sibling markets, when it publishes one: for Polymarket the neg-risk market id of a neg-risk group, else the Gamma event id. Not a Skewtape matched event id.

Example Request
curl -X GET 'https://api.skewtape.com/v1/markets/string/string'
Example Response
{  "block_reason_code": "string",  "blocked": true,  "category": "string",  "close_at": "2019-08-24T14:15:22Z",  "first_trade_at": "2019-08-24T14:15:22Z",  "last_trade_at": "2019-08-24T14:15:22Z",  "market_id": "string",  "open_at": "2019-08-24T14:15:22Z",  "outcomes": [    {      "label": "string",      "token_id": "string"    }  ],  "quality_flags": [    "string"  ],  "question": "string",  "rules_hash": "string",  "rules_text": "string",  "schema_version": "string",  "slug": "string",  "source_kind": "chain",  "status": "open",  "updated_at": "2019-08-24T14:15:22Z",  "venue": "string",  "venue_event_id": "string"}

Powered by Kalshi Research

Live feed (WebSocket) GET

WebSocket upgrade (ADR-0013, ARCHITECTURE 10). Builder and Pro plans; the plans table says how many connections an account may hold (Builder 3, Pro 10, counted across all its keys). Not served by a generated handler: this operation documents the protocol. Authentication: the X-API-Key header on the upgrade, or the first message {"op":"auth","key":"st_live_..."} within 10 seconds. Messages from the client: {"op":"subscribe","topics":["markets","resolutions","trades","event_spread"], "venues":["kalshi"],"markets":[{"venue":"polymarket","market_id":"0x..."}], "events":["st_evt_00042"],"resume_from":123} replaces the subscription (topics required; the filters are ORed and optional; the events filter, matched event ids, narrows event_spread, whose rows belong to an event and not a venue, so the venue and market filters do not narrow them; it needs that topic: with other topics alone it is refused, and beside event_spread it leaves those topics to the venue and market filters, whole when there are none; a market filter cuts a trades_batch to its markets' fills); {"op":"ping"} answers {"op":"pong"} at once, even during a replay. markets, resolutions and trades need Builder or above, event_spread Pro; a plan that loses a topic during a connection is told (error topic_not_in_plan) and keeps its other topics. Trades (E15-T3) are fills from venue streams, one event per fill with the stored row's identity (venue, tx_hash, log_index) up to 400 a second per venue, the rest of the second folded into one trades_batch; the hourly walk stores the row afterwards, and a leader that takes over re-reads the last blocks, so dedupe by identity. event_spread is one approved matched event's fee-adjusted spread, at most one event per matched event per five seconds (FeedSpread). Right after subscribed, a subscription to event_spread receives the latest spread of each event it names as snapshot messages (op snapshot, FeedSnapshot): a state with no seq, never a point to resume from; the replay then carries the other topics and live spreads follow as events, so a replay returns the latest per event, never each tick. A subscription sent before the instance has read the log once is answered error not_ready: send it again. Subscribes sent while the connection is busy (a replay, a slow write) are not queued: the latest one is applied when the connection is free, and each earlier one that never ran is answered error superseded. Messages from the server, each with op: hello (connection_id, plan, the current seq, the replay window and the reconnect schedule), subscribed (what was accepted, replay_to, masked_venues), snapshot (one FeedSnapshot: the latest spread of a matched event, no seq), event (one FeedEvent: seq, topic, kind, venue, market_id, at, payload), resync (resume_from is older than the replay window: read the API for what you missed, live events follow), reconnect (sent at 55 minutes with resume_from; the connection closes at 59 minutes, before the 60-minute platform limit), error (code, message). Replay (D2): resume_from replays the stored events after that seq that match the subscription, then switches to live with no gap and no duplicate; a client keeps the last seq it saw. Every connection also receives the feed's own gap notices (topic feed, kind gap) when a venue stream reconnected: the stored data has no gap, so read the API for that window or wait for the next hourly run. Policy (ADR-0028): a subscription naming a venue the live_data policy blocks is refused (error venue_blocked); a masked venue's events ship with the listed fields null and blocked true. Close codes: 4000 reconnect (the age limit, or a registration that expired while the server could not heartbeat; both carry resume_from), 4001 unauthorized (also when the key is revoked during the connection: keys and plans are read again every few minutes), 4003 plan (no feed, or a topic the plan no longer covers), 4008 connection limit, 4009 slow consumer (the reason carries resume_from), 4029 too many failed key lookups, 4400 bad message, 1001 server restarting.

Get one matched event GET

One matched event by event_id. Missing or hidden from the plan is 404; the response never says which.