# Table of Contents - [Welcome!](#welcome-) - [DeleteQuote](#deletequote) - [GetQuote](#getquote) - [AcceptQuote](#acceptquote) - [ConfirmQuote](#confirmquote) - [GetRFQs](#getrfqs) - [GetRFQ](#getrfq) - [GetEvents](#getevents) - [DeleteRFQ](#deleterfq) - [GetEvent](#getevent) - [GetTrades](#gettrades) - [GetMarkets](#getmarkets) - [GetMarket](#getmarket) - [CreateRFQ](#createrfq) - [GetMarketOrderbook](#getmarketorderbook) - [GetSeriesList](#getserieslist) - [GetSeries](#getseries) - [GetMarketCandlesticks](#getmarketcandlesticks) - [Making Your First Request](#making-your-first-request) - [Test In The Demo Environment](#test-in-the-demo-environment) - [Changelog](#changelog) - [API Keys](#api-keys) - [Kalshi Glossary](#kalshi-glossary) - [Changelog Instructions](#changelog-instructions) - [GetApiVersion](#getapiversion) - [GetCommunicationsID](#getcommunicationsid) - [GetQuotes](#getquotes) - [Market Data Feed](#market-data-feed) - [CreateQuote](#createquote) - [Rate Limits and Tiers](#rate-limits-and-tiers) - [GetExchangeAnnouncements](#getexchangeannouncements) - [GetExchangeSchedule](#getexchangeschedule) - [GetExchangeStatus](#getexchangestatus) - [GetUserDataTimestamp](#getuserdatatimestamp) - [GetMilestone](#getmilestone) - [GetMilestones](#getmilestones) - [GetMultivariateEventCollections](#getmultivariateeventcollections) - [GetMultivariateEventCollection](#getmultivariateeventcollection) - [CreateMarketInMultivariateEventCollection](#createmarketinmultivariateeventcollection) - [GetMultivariateEventCollectionLookupHistory](#getmultivariateeventcollectionlookuphistory) - [GetBalance](#getbalance) - [LookupTickersForMarketInMultivariateEventCollection](#lookuptickersformarketinmultivariateeventcollection) - [GetFills](#getfills) - [BatchCreateOrders](#batchcreateorders) - [CreateOrder](#createorder) - [GetOrders](#getorders) - [BatchCancelOrders](#batchcancelorders) - [CancelOrder](#cancelorder) - [AmendOrder](#amendorder) - [GetOrder](#getorder) - [DecreaseOrder](#decreaseorder) - [GetPositions](#getpositions) - [GetOrderQueuePosition](#getorderqueueposition) - [GetStructuredTarget](#getstructuredtarget) - [GetPortfolioRestingOrderTotalValue](#getportfoliorestingordertotalvalue) - [GetSettlements](#getsettlements) - [GetOrderQueuePosition Endpoint Added](#getorderqueueposition-endpoint-added) - [Breaking Changes to Order Struct](#breaking-changes-to-order-struct) - [Breaking Changes to Max Order Cost](#breaking-changes-to-max-order-cost) - [Websocket Upgrades](#websocket-upgrades) - [Websocket Upgrades](#websocket-upgrades) - [Adding GetUserDataTimestamp](#adding-getuserdatatimestamp) - [GetMilestone PageSize -> Limit](#getmilestone-pagesize-limit) - [Undo Certain 2.0.1 Changes](#undo-certain-2-0-1-changes) - [](#-cdata-kalshi-developer-suite-) - [Removed Fields From GetMarket(s)](#removed-fields-from-getmarket-s-) - [GetApiVersion](#getapiversion) - [Changelog](#changelog) - [GetFills Millisecond Precision](#getfills-millisecond-precision) - [GetRFQ Cursor Response](#getrfq-cursor-response) - [Changelog](#changelog) --- # Welcome! Welcome to Kalshi exchange's trader and developer documentation. This guide outlines exchange functionality, market details and API architecture. By continuing to use or access Kalshi's API, you are agreeing to be bound to the terms of [the Kalshi Developer Agreement](https://kalshi.com/developer-agreement) --- # DeleteQuote ShellNodeRubyPHPPython --- # GetQuote ShellNodeRubyPHPPython --- # AcceptQuote ShellNodeRubyPHPPython --- # ConfirmQuote ShellNodeRubyPHPPython --- # GetRFQs ShellNodeRubyPHPPython --- # GetRFQ ShellNodeRubyPHPPython --- # GetEvents ShellNodeRubyPHPPython --- # DeleteRFQ ShellNodeRubyPHPPython --- # GetEvent ShellNodeRubyPHPPython --- # GetTrades ShellNodeRubyPHPPython --- # GetMarkets ShellNodeRubyPHPPython --- # GetMarket ShellNodeRubyPHPPython --- # CreateRFQ ShellNodeRubyPHPPython --- # GetMarketOrderbook ShellNodeRubyPHPPython --- # GetSeriesList ShellNodeRubyPHPPython --- # GetSeries ShellNodeRubyPHPPython --- # GetMarketCandlesticks ShellNodeRubyPHPPython --- # Making Your First Request To make your request we recommend testing a public endpoint like [GetMarkets](https://trading-api.readme.io/reference/getmarkets-1) . As you explore our other endpoints, you'll notice some endpoints return an `authentication_error`. If you want to experiment with these endpoints, you will need to get [API Keys](https://trading-api.readme.io/reference/api-keys) . You may also want to sign up for a [demo account](https://trading-api.readme.io/reference/creating-a-demo-account) to test without real funds. The following resources might help you on your journey to exploring Kalshi's markets: * [Python starter code](https://github.com/Kalshi/kalshi-starter-code-python/tree/main) bare-bones API interactions with authentication examples (also see [API Keys](https://trading-api.readme.io/reference/api-keys) ) * [Python starter code 2](https://kalshi-public-docs.s3.amazonaws.com/KalshiAPIStarterCodeWithApiKey.zip) this Python client is not maintained, but you may still find it useful as a reference for how to call certain endpoints * [Discord](https://discord.gg/kalshi) and check out #dev and #support --- # Test In The Demo Environment For testing purposes, Kalshi offers a _demo_ environment with mock funds. You can access the Demo environment at [https://demo.kalshi.co/](https://demo.kalshi.co/) . For safety, credentials are not shared between this environment and production. To set up a Kalshi Demo account, [follow this step-by-step tutorial](https://docs.google.com/presentation/d/e/2PACX-1vRvhUAqRBYzJmt7JCinMXmu6KVWkj-cc7ikDXGConmqjcv4mnlJacgHPcZJ20fWWnrYdubn-oczclKP/pub?start=false&loop=false&delayms=3000&slide=id.p) . Demo's API root is`https://demo-api.kalshi.co/trade-api/v2`. --- # Changelog [GetOrderQueuePosition Endpoint Added](https://trading-api.readme.io/changelog/00012_order_queue_position) =========================================================================================================== 19 days ago by ReadMe API GetOrderQueuePosition Endpoint Added [](https://trading-api.readme.io/changelog#getorderqueueposition-endpoint-added) ========================================================================================================================= removed [Breaking Changes to Order Struct](https://trading-api.readme.io/changelog/breaking-order-struct) ================================================================================================== about 1 month ago by ReadMe API This is a **breaking change** to the Order struct that is returned several places in the API. The following fields are being deprecated: fixed [Breaking Changes to Max Order Cost](https://trading-api.readme.io/changelog/breaking-max-order-cost) ====================================================================================================== about 1 month ago by ReadMe API This is a **breaking change** to the Max Order Cost field in CreateOrder. added [Websocket Upgrades](https://trading-api.readme.io/changelog/websocket-upgrades-20250506) ========================================================================================== 2 months ago by ReadMe API new channels are added - `ticker_v2` and `market_lifecycle_v2` that are slightly different from their previous iterations and preparing the older versions to be retired soon (~1-2 weeks) with a new version release added [Websocket Upgrades](https://trading-api.readme.io/changelog/websocket-upgrades) ================================================================================= 3 months ago by ReadMe API delta messages in `orderbook_delta` will now "updated\_ts" and, when the update is caused by your order, a "client\_order\_id" field be populated as well. added [Adding GetUserDataTimestamp](https://trading-api.readme.io/changelog/add-api-user-clock) ========================================================================================== 4 months ago by ReadMe API Adding GetUserDataTimestamp endpoint. improved [Undo Certain 2.0.1 Changes](https://trading-api.readme.io/changelog/undo-version-201-changes) =============================================================================================== 4 months ago by ReadMe API Due to the api log being new, some users were not able to prepare for the upcoming changes. We are releasing API version 2.0.2 on Friday March 7th 2025 to undo the changes in improved [GetMilestone PageSize -> Limit](https://trading-api.readme.io/changelog/get-milestone-limit) ============================================================================================== 4 months ago by ReadMe API Consistent with our API conventions, GetMilestone now returns `limit` instead of `page_size` removed [Removed Fields From GetMarket(s)](https://trading-api.readme.io/changelog/removed-fields) =========================================================================================== 5 months ago by ReadMe API GetMarket(s) will no longer return fields `Title`, `Subtitle`, `NoSubTitle`, `FeeWaiverExpirationTime`, `RiskLimitCents` Orders will no longer contain `QueuePosition` OrderConfirmations, returned on create endpoints, will no longer contain `SelfTradePreventionType` added [GetApiVersion](https://trading-api.readme.io/changelog/version-endpoint) ========================================================================== 5 months ago by ReadMe API Added an endpoint that will give the current API version. This can be used to synchronize with changelog updates. --- # API Keys This process is the same for the demo or production environment. ### Generating an API Key [](https://trading-api.readme.io/reference/api-keys#generating-an-api-key) #### Access the Account Settings Page:\*\* [](https://trading-api.readme.io/reference/api-keys#access-the-account-settings-page) Log in to your account and navigate to the “Account Settings” page. You can typically find this option by clicking on your profile picture or account icon in the top-right corner of the application. #### Generate a New API Key [](https://trading-api.readme.io/reference/api-keys#generate-a-new-api-key) In the “Profile Settings” page [https://kalshi.com/account/profile](https://kalshi.com/account/profile) , locate the “API Keys” section. Click on the “Create New API Key” button. This action will generate a new API key in the RSA\_PRIVATE\_KEY format. #### Store Your API Key and Key ID: [](https://trading-api.readme.io/reference/api-keys#store-your-api-key-and-key-id) After generating the key, you will be presented with: • Private Key: This is your secret key in RSA\_PRIVATE\_KEY format. • Key ID: This is a unique identifier associated with your private key. Important: For security reasons, the private key will not be stored by our service, and you will not be able to retrieve it again once this page is closed. Please make sure to securely copy and save the private key immediately. The key will also be downloaded as txt file with the name provided. ### Using a API Key \*\* [](https://trading-api.readme.io/reference/api-keys#using-a-api-key-) Each request to Kalshi trading api will need to be signed with the private key generated above. The following header values will need to be provided with each request: `KALSHI-ACCESS-KEY`\- the Key ID `KALSHI-ACCESS-TIMESTAMP` - the request timestamp in ms `KALSHI-ACCESS-SIGNATURE`\- request hash signed with private key The above signature is generated by signing a concatenation of the timestamp, the HTTP method and the path. Sample code for generating the required headers is below (alternatively use our example code [here](https://github.com/Kalshi/kalshi-starter-code-python/tree/main) ): **Python** Load the private key stored in a file `from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend def load_private_key_from_file(file_path): with open(file_path, "rb") as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=None, # or provide a password if your key is encrypted backend=default_backend() ) return private_key` Sign text with private key `import base64 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding, rsa from cryptography.exceptions import InvalidSignature def sign_pss_text(private_key: rsa.RSAPrivateKey, text: str) -> str: # Before signing, we need to hash our message. # The hash is what we actually sign. # Convert the text to bytes message = text.encode('utf-8') try: signature = private_key.sign( message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.DIGEST_LENGTH ), hashes.SHA256() ) return base64.b64encode(signature).decode('utf-8') except InvalidSignature as e: raise ValueError("RSA sign PSS failed") from e` Send request `import requests import datetime # Get the current time current_time = datetime.datetime.now() # Convert the time to a timestamp (seconds since the epoch) timestamp = current_time.timestamp() # Convert the timestamp to milliseconds current_time_milliseconds = int(timestamp * 1000) timestampt_str = str(current_time_milliseconds) # Load the RSA private key private_key = load_private_key_from_file('kalshi-key-2.key') method = "GET" base_url = 'https://demo-api.kalshi.co' path='/trade-api/v2/portfolio/balance' msg_string = timestampt_str + method + path sig = sign_pss_text(private_key, msg_string) headers = { 'KALSHI-ACCESS-KEY': 'a952bafb-12dd-4955-9e7c-3895265e812d', 'KALSHI-ACCESS-SIGNATURE': sig, 'KALSHI-ACCESS-TIMESTAMP': timestampt_str } response = requests.get(base_url + path, headers=headers) print("Status Code:", response.status_code) print("Response Body:", response.text)` **JS** `const fs = require('fs'); const crypto = require('crypto'); const axios = require('axios'); function loadPrivateKeyFromFile(filePath) { const keyData = fs.readFileSync(filePath, 'utf8'); const privateKey = crypto.createPrivateKey({ key: keyData, format: 'pem', // If your key is encrypted, you'd need to provide a passphrase here // passphrase: 'your-passphrase' }); return privateKey; } function signPssText(privateKey, text) { // Before signing, we need to hash our message. // The hash is what we actually sign. // Convert the text to bytes const message = Buffer.from(text, 'utf-8'); try { const signature = crypto.sign( 'sha256', message, { key: privateKey, padding: crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST } ); return signature.toString('base64'); } catch (error) { throw new Error("RSA sign PSS failed: " + error.message); } } // Get the current time const currentTime = new Date(); // Convert the time to a timestamp (milliseconds since the epoch) const currentTimeMilliseconds = currentTime.getTime(); const timestampStr = currentTimeMilliseconds.toString(); // Load the RSA private key const privateKey = loadPrivateKeyFromFile('baseKey.txt'); const method = "POST"; const baseUrl = 'https://demo-api.kalshi.co'; const path = '/trade-api/v2/portfolio/orders'; const body = {"action": "buy", "client_order_id": "1fa1be86-3f8e-49be-8c1e-1e46ea490d59", "count": 3, "side": "yes", "ticker": "HOMEUSY-24-T4", "type": "limit", "yes_price": 30}; const msgString = timestampStr + method + path; console.log(msgString); const sig = signPssText(privateKey, msgString); const headers = { 'KALSHI-ACCESS-KEY': '164c4e3e-f653-4847-b962-bc4975b91ddc', 'KALSHI-ACCESS-SIGNATURE': sig, 'KALSHI-ACCESS-TIMESTAMP': timestampStr, 'Content-Type': 'application/json' }; axios.post(baseUrl + path, body, { headers }) .then(response => { console.log("Status Code:", response.status); console.log("Response Body:", response.data); }) .catch(error => { console.error("Error:", error.message); console.log(error.response.data); });` --- # Kalshi Glossary Here are some core terminologies used in Kalshi exchange * **Market:**A single binary market. This is a low level object which rarely will need to be exposed on its own to members. The usage of the term “market” here is consistent with how it’s used in the backend and API. * **Event:** An event is a collection of markets and the basic unit that members should interact with on Kalshi. * **Series:**A series is a collection of related events. The following should hold true for events that make up a series: * Each event should look at similar data for determination, but translated over another, disjoint time period. * Series should never have a logical outcome dependency between events. Events in a series should have the same ticker prefix. * Please see the "Timeline and Payout" dropdown on a market's page to find the Market, Event, and Series tickers. Note that the market ticker will depend on which market you are looking at on that page. For example, Trump and Harris are each their own market. --- # Changelog Instructions You can subscribe to the rss changelog at [https://trading-api.readme.io/changelog.rss](https://trading-api.readme.io/changelog.rss) if you'd like to stay ahead of breaking changes. You can reference the pending API spec under the "version" dropdown menu at the top left. When the actual API is upgraded to this new version, you will see the version marked as "Stable" in the drop-down menu and become the new default on the landing page. This changelog is a work in progress. As always, we welcome any feedback in our Discord #dev channel! --- # GetApiVersion ShellNodeRubyPHPPython --- # GetCommunicationsID ShellNodeRubyPHPPython --- # GetQuotes ShellNodeRubyPHPPython --- # Market Data Feed Protocol overview [](https://trading-api.readme.io/reference/ws#protocol-overview) ====================================================================================== Our websockets api is only served over an encrypted connection. There is a single endpoint to establish WS connections: `wss://api.elections.kalshi.com/trade-api/ws/v2`. We provide multiple channels of information over a single connection. So after establishing a WS connection, the client has the freedom to chose which channels they are interested in at any given moment. To express the intention of receiving messages for a specific channel the client has to send subscription messages that will be defined latter on in this document. This endpoint only can be used by signed-up users (private channels only). The communication between the user (client) and Kalshi's backend (server) is async. All the messages exchanged should be encoded in JSON format. We call messages in the client -> server direction _commands_, these commands specify the set of message types and specific markets the client is interested on. Typically, the client starts the connection and sends commands to the server and eventually receives messages related to the commands whenever there is an update on the server. Example: `(cli => srv) (srv => cli) => cmd1 => cmd2 <= msg_related_to_cmd_2 <= msg_related_to_cmd_1 <= msg_related_to_cmd_2 ...` Connecting [](https://trading-api.readme.io/reference/ws#connecting) ======================================================================== You can connect to our PROD websocket api at `wss://api.elections.kalshi.com/trade-api/ws/v2` by using API key authentication. Note that since user-password authentication is no longer supported the /trade-api/v2/login endpoint is not needed when connecting to the websocket api. Commands [](https://trading-api.readme.io/reference/ws#commands) ==================================================================== The initial version of the protocol provides only subscription commands. Eventually, we may want to offer a complete trading API through WebSocket, but, for now, you should continue using the REST API for trading, while the WS interface provides a stream of notifications/updates. Without WS, you would have to be constantly polling the GET end-points from [api v2](https://trading-api.readme.io/reference/getting-started) to keep yourself up to date with what is going on in the markets. Each command uses the following format: JSON `{ "id": , // Unique ID of the command request. "cmd": , // Command name: "subscribe" or "update_subscription" or "unsubscribe". "params": {...} // Params that are specific to the given cmd. }` Given that our protocol is async, we use the _id_ field to correlate commands with further data messages from the server. When the client includes an _id_ in a command, the server returns that _id_ value in messages related to that command, just so you could recognize them in the message stream. The _id_ is generated by the client and should be unique within a WS session. The simplest way to use it would be to start from 1 and then increment the value for every new command sent to the server. If the _id_ is set to 0, the server treats it the same way as if there was no _id_. Command "subscribe" [](https://trading-api.readme.io/reference/ws#command-subscribe) ---------------------------------------------------------------------------------------- Subscription to one or many channels. Example: JSON `{"id": 1,"cmd": "subscribe","params": {"channels": ["orderbook_delta", "ticker"], "market_ticker": "CPI-22DEC-TN0.1"}}` If the subscription is successful, the client will receive a separate "subscribed" message for each channel in the "channels" param field of the "subscribe" message. These are confirmation messages to indicate that the subscription was accepted successfully. The order of those messages is not guaranteed, as the protocol is async. Note that the ID will be the same in both message, as they "respond" to the same command. JSONJSON `{ "id": 1, "type": "subscribed", "msg": { "channel": "orderbook_delta", "sid": 1 } }` `{ "id": 1, "type": "subscribed", "msg": { "channel": "ticker", "sid": 2 } }` **Important notes:** * **You can only subscribe a single time to any channel.** * **Some channels support subscribing to all markets, which is indicated by not passing any market ticket (more details will be provided in next sections).** If you retry the subscription message in the beginning of this section, but using "id": 2. Then you should get the error below as a response: JSON `{"type":"error","id":2,"msg":{"code":6,"msg":"Already subscribed"}}` Each established subscription is identified by another ID (`sid`) returned by the server. This subscription ID can later be used by the client to cancel the subscription (equals to unsubscribe) or to update the subscription adding or removing markets. The subscription id (`sid`) is also used in messages sent by the server within each subscription so you can identify which message belong to which subscription when you receive them. One or both of the subscription attempts can fail. For every failure, the server returns an error message, the format of which is described later on this page. ### Subscription Modes [](https://trading-api.readme.io/reference/ws#subscription-modes) The [subscribe command](https://trading-api.readme.io/reference/ws#command-subscribe) allows for three different subscription modes: * **All markets: Do not pass "market\_ticker" or "market\_tickers". You will get all fills for you account.** * **List of markets: Pass the list of markets on "market\_tickers". You will get updates only for this list of markets.** * **Single market: Pass a single market ticker on "market\_ticker". You will get updates only for this market.** **Important notes:** * **Availability of the "All markets" mode will depend on the specific channel, this is disclosed in the specific channel sections latter on.** * **When the "All markets" mode is supported it will automatically track new markets that happen to open after your subscription was initiated.** Command "unsubscribe" [](https://trading-api.readme.io/reference/ws#command-unsubscribe) -------------------------------------------------------------------------------------------- The client can cancel more than one or more subscriptions at once: JSON `{"id": 124,"cmd": "unsubscribe","params": {"sids": [1, 2]}}` Confirmation messages are sent to the client independently, and, again, the order is not guaranteed: JSONJSON `{ "sid": 2, "type": "unsubscribed" }` `{ "sid": 1, "type": "unsubscribed" }` Command "update\_subscription" [](https://trading-api.readme.io/reference/ws#command-update_subscription) ------------------------------------------------------------------------------------------------------------- The client can update an existing subscription. The update action should be specified in params in the “action” field. All the channels (besides the "fill" channel) allow updates and supports two types of actions: `add_markets` and `delete_markets`. Updating a subscription to include new markets is preferred over starting new subscriptions. JSON `{ "id": 124, "cmd": "update_subscription", "params": { "sids": [456], // Exactly one sid is required, even though it is an array "market_tickers": ["", ..., ""], // market_ticker is also supported for a single market "action": "add_markets|delete_markets" } }` In case of success an "ok" message will be received containing the list of market tickers after the update: JSON `{ "id": 123, "sid": 456, "seq": 222, "type": "ok", "market_tickers": ["", ..., ""] // full list of market_tickers this subscription is tracking }` Client-Side Recovery [](https://trading-api.readme.io/reference/ws#client-side-recovery) ============================================================================================ The client should handle unexpected behavior in the following manner: * **Connection Closed:** Attempt to reconnect periodically. After successful reconnect, immediately resubscribe to all previously subscribed channels. Also, re-send all subscription commands from before the disconnection. * **Server-Forced Unsubscription** Immediately attempt to re-subscribe to channel. If response is an error, handle it . * **Subscribe Command Not Confirmed by Server** If the client does not receive a confirmation during a predefined window, it should close the connection and attempt to reconnect. * **Connection Health Deteriorates** At any indication of an unhealthy connection, the client will close the connection and attempt to reconnect as described above. Server messages [](https://trading-api.readme.io/reference/ws#server-messages) ================================================================================== All specific message types are described in detail below and later in the "Subscription Channels" section. Server message format [](https://trading-api.readme.io/reference/ws#server-message-format) ---------------------------------------------------------------------------------------------- This section describes the general structure of messages. The fields market as Required should be sent when responding to client commands or sending messages in subscription channels. JSON `{ "id": , // Optional command ID "sid": , // Optional subscription ID (described below) "seq": , // Optional sequence number (described below) "type": , // Required message type (described below) "msg": {...} // Required body of the message }` The `id` field is optional and only included in a server message if the client provided it in the corresponding command. When a channel subscription is established, messages within the channel will not have the `id` field. Instead, we use `sid` to identify the channel. Error messages [](https://trading-api.readme.io/reference/ws#error-messages) -------------------------------------------------------------------------------- Sometimes commands can't be executed on the server. For example, a client cannot subscribe to a channel if the client is already subscribed to that channel (besides the fill channel where that is allowed). Or, symmetrically, it's impossible to cancel a non-existent subscription. Here is an example error message that the server returns upon an attempt to open a second subscription to the same channel: JSON `{ "id": 123, "type": "error", "msg": { "code": 6, "msg": "Already subscribed" }, }` Subscription Channels [](https://trading-api.readme.io/reference/ws#subscription-channels) ============================================================================================== A subscription channel is a feed of logically related messages. It can include, for example, all trades on a specific market, or all orderbook offers on a specific market. We are free to define channels and their logic however we see fit. Though, it's easier to reason about a channel if its purpose is clearly defined. Below is a provisional list of channels. New channels will be added progressively. Channels for a signed in user: * `orderbook_delta`: price level updates on a market. * `ticker`: market price ticks. * `trade`: public trades. * `fill`: user fills. **Important observation: We standardize the channels with singular name form.** If you try to subscribe to an unexisting channel you should receive this message: JSON `{ "id": 123, "type": "error", "msg": { "code": 8, "msg": "Unknown channel name" }, }` Snapshot + Deltas [](https://trading-api.readme.io/reference/ws#snapshot--deltas) ------------------------------------------------------------------------------------- Some channels have to provide data in a highly reliable way so that the client could build a correct and consistent view from the received messages at any time. Take, for example, the `orderbook_delta` channel (which is going to be detailed in the next section). There are two types of messages that can be received from the server in an `orderbook_delta` subscription. * A "snapshot": a complete view of the order book. * A "delta": an update to be applied to the current view of the order book. Any missed "delta" message can result in a wrong state of the world on the client. To avoid the problem, we use sequential numbering for all snapshots and updates. The number is included as `seq` field in every message. The server ensures that, within a channel, messages are sent strictly sequentially. So the client would receive the snapshot in a message with `seq: 1`, then an update message with `seq: 2`, then all other updates with `seq` values 3, 4, 5, etc. When the client detects a gap in the numbering, it has to re-subscribe to the channel and start again from a snapshot. Otherwise, the client might see wrong info. If we don't need a snapshot for a particular channel and don't care if any message is accidentally lost, then you don't have to use the `seq` feature. Whether a channel is seq-enabled or not will be explicitly noted below. Order Book channel [](https://trading-api.readme.io/reference/ws#order-book-channel) ---------------------------------------------------------------------------------------- **Channel**: `orderbook_delta` **Purpose**: A complete view of the order book's aggregated price levels on a given market and all further updates to it. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["orderbook_delta"], // Required: Specifies the orderbook_delta channel. "market_tickers": ["", "", ...] // Required: Specifies the list of markets you wanna listen to. } }` **This channel does not support the "All Markets" mode, it only supports "List of Markets" mode. So you always have to pass the list of markets you are subscribing to.** Example: JSON `{"id": 23,"cmd": "subscribe","params": {"channels": ["orderbook_delta"], "market_tickers": ["FED-23DEC-T3.00", "CORIVER-2024-T1030"]}}` After the subscription is established, first, the client receives a snapshot. An example for the orderbook\_snapshot message is shown below: **Ordebook snapshot message (server => client)** Schema: JSON `{ "sid": , // Required: Id of the subscription. "type": "orderbook_snapshot", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "seq": 1, // Required: Sequential number, should be checked if you wanna guarantee you received all the messages. "msg": { "market_ticker": , // Required: Market_ticker string, what you use to differentiate updates for different markets. "yes": [ // Optional: This key will not exist if there is no Yes offers in the orderbook. // In case it exists there will be many price levels, so for compactness, every element in the list is // an array, with two integers not an object. [, ], // [Price in cents, Number of resting contracts] ... [, ] ], "no": [ ... // Optional. Same format as "yes" but for the NO side of the orderbook. ] } }` Example: JSON `{ "type": "orderbook_snapshot", "sid": 2, "seq": 2, "msg": { "market_ticker": "FED-23DEC-T3.00", "yes": [ [8, 300], [22, 333] ], "no": [ [54, 20], [56, 146] ] } }` The client is expected to store the orderbook\_snapshot and then keep listening for incoming "orderbook\_delta" messages. **Orderbook delta message (server => client)** Schema: JSON `{ "type": "orderbook_delta", // Required: Message identifier, what you use to recognize the message type for messages that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "seq": , // Required: Sequential number, should be checked if you wanna guarantee you received all the messages. "msg": { "market_ticker": , // Required: Market_ticker string, what you use to differentiate updates on different markets. "price": , // Required: Indicates the price level that is being changed in cents "delta": , // Required: Positive means increase, negative means decrease "side": // Required: "yes" or "no" to indicate the side of the orderbook that changed } }` Example: JSON `{ "type": "orderbook_delta", "sid": 2, "seq": 3, "msg": { "market_ticker": "FED-23DEC-T3.00", "price": 96, "delta": -54, "side": "yes" } }` The message above signals that the number of resting contracts at price 23 for Yes contracts on this market is now 88 contracts, which is 100 - 22. **Important note: You should still be tracking "orderbook\_snapshot" messages as the subscription can update the server can resend the full state of the orderbook in case there are multiple changes at the same avoid. It can pack multiple delta messages in a single "orderbook\_snapshot" message. In that case you should throw away whatever view of the orderbook you had and use the content of the message as the current state.** \[DEPRECATED\] Ticker channel [](https://trading-api.readme.io/reference/ws#deprecated-ticker-channel) ---------------------------------------------------------------------------------------------------------- **Channel**: `ticker` **Purpose**: The list price ticker for a given market. No snapshot is required. The server just sends the last price on the market when the price changes. On an active market, when the price changes a few times per second, only the most recent change is sent for that second. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["ticker"], // Required: Specifies the ticker channel. "market_tickers": ["", ..., ""] // Not required: If you do not pass this field it will subscribe to ticker updates on all markets. If you do it will only send updates for the list of markets provided. } }` **This channel supports two subscription modes:** List of markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["ticker"], "market_tickers": ["FED-23DEC-T3.00", "CORIVER-2024-T1030"] } }` All markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["ticker"] } }` **Ticker message (server => client)** A message with a ticker update from the server: Schema: JSON `{ "type": "ticker", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "market_ticker": , // Required: Market_ticker string, what you use to differentiate updates for different markets. "price": , // Between 1 and 99 (inclusive) "yes_bid": , // Between 1 and 99 (inclusive) "yes_ask": , // Between 1 and 99 (inclusive) "volume": , // Number of individual contracts traded on the market so far YES and NO count separately "open_interest": , // Number of active contracts in the market currently "dollar_volume": , // Number of dollars traded in the market so far "dollar_open_interest": , // Number of dollars positioned in the market currently "ts": // Unix timestamp for when the update happened (in seconds) } }` Example: JSON `{ "type": "ticker", "sid": 11, "msg": { "market_ticker": "FED-23DEC-T3.00", "price": 48, "yes_bid": 45, "yes_ask": 53, "volume": 33896, "open_interest": 20422, "dollar_volume": 16948, "dollar_open_interest": 10211, "ts": 1669149841 } }` A ticker message also will be sent whenever there is a new trade or the bid / ask values move on any of the markets tracked by the subscription. Ticker V2 channel [](https://trading-api.readme.io/reference/ws#ticker-v2-channel) -------------------------------------------------------------------------------------- **Channel**: `ticker_v2` **Purpose**: Update the client with the latest bid/ask, price, volume, open interest changes. The difference from the older version (`ticker`) is that it only emits fields that have changed and the trade based fields are delta-based. To initiatialize the state, you should call our REST API to retrieve it. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["ticker_v2"], // Required: Specifies the ticker_v2 channel. "market_tickers": ["", ..., ""] // Not required: If you do not pass this field it will subscribe to ticker updates on all markets. If you do it will only send updates for the list of markets provided. } }` **This channel supports two subscription modes:** List of markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["ticker_v2"], "market_tickers": ["FED-23DEC-T3.00", "CORIVER-2024-T1030"] } }` All markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["ticker_v2"] } }` **Ticker V2 message (server => client)** A message with a ticker\_v2 update from the server: Schema: JSON `{ "type": "ticker_v2", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "market_ticker": , // Required: Market_ticker string, what you use to differentiate updates for different markets. "price": , // Optional: Only emitted when there has been a trade since the last message. Between 1 and 99 (inclusive) "yes_bid": , // Optional: Only emitted when there has been a bid/ask change since the last message. Between 1 and 99 (inclusive) "yes_ask": , // Optional: Only emitted when there has been a bid/ask change since the last message. Between 1 and 99 (inclusive) "volume_delta": , // Optional: Only emitted when there has been a trade since the last message. Delta of individual contracts traded on the market so far YES and NO count separately "open_interest_delta": , // Optional: Only emitted when there has been a trade since the last message. Delta of active contracts in the market currently "dollar_volume_delta": , // Optional: Only emitted when there has been a trade since the last message. Delta of number of dollars traded in the market so far "dollar_open_interest_delta": , // Optional: Only emitted when there has been a trade since the last message. Delta of number of dollars positioned in the market currently "ts": // Unix timestamp for when the update happened (in seconds) } }` Example: JSON `{ "type": "ticker", "sid": 11, "msg": { "market_ticker": "FED-23DEC-T3.00", "price": 48, "yes_bid": 45, "yes_ask": 53, "volume_delta": 33896, "open_interest_delta": 20422, "dollar_volume_delta": 16948, "dollar_open_interest_delta": 10211, "ts": 1669149841 } }` Trade channel [](https://trading-api.readme.io/reference/ws#trade-channel) ------------------------------------------------------------------------------ **Channel**: `trade` **Purpose**: Update the client with the most recent trades that occur in the markets that the client is interested on. The subscription process is similar to the ticker channel, the client subscription specifying the market\_tickers he is interested on and the server will start sending trade data messages. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["trade"], // Required: Specifies the trade channel. "market_tickers": [, ..., ] // Not required: If you do not pass this field it will subscribe to trade updates on all markets. If you do it will only send updates for the list of markets provided. } }` **This channel supports two subscription modes:** List of markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["trade"], "market_tickers": ["FED-23DEC-T3.00", "HIGHNY-22DEC23-B53.5"] } }` All markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["trade"] } }` **Trade message (server => client)** A trade message will be sent for each trade that happens on the server for the markets included in the subscription. **Regardless of whether you participated in the trade or not, this channel exposes public trades.** For security reason, fields that could be used to potentially identify the users or orders involved in the trades like user, order or trade ids are intentionally removed from the response. Each trade message is equivalent to an entry in the [GetTrades endpoint from the trade api](https://trading-api.readme.io/reference/gettrades) . Schema: JSON `{ "type": "trade", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "market_ticker": , // Ticker for the market that this trade belongs to. This is what you use to differentiate updates for different markets. "yes_price": , // Price for the yes side. Between 1 and 99 (inclusive). "no_price": , // Price for the no side. Between 1 and 99 (inclusive). "count": , // Number of contracts traded. "taker_side": , // Side of the taker user on this trade. Either "yes" or "no". "ts": // Unix timestamp for when the update happened (in seconds). } }` Example: JSON `{ "type": "trade", "sid": 11, "msg": { "market_ticker": "HIGHNY-22DEC23-B53.5", "yes_price": 36, "no_price": 64, "count": 136, "taker_side": "no", "ts": 1669149841 } }` Fill channel [](https://trading-api.readme.io/reference/ws#fill-channel) ---------------------------------------------------------------------------- **Channel**: `fill` **Purpose**: Update the client with the most recent fills, that means trades in that occur in the markets that the client is interested on. The subscription process is similar to the ticker channel, the client subscription specifying the market\_tickers he is interested on and the server will start sending trade data messages. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["fill"], // Required: Specifies the fill channel. "market_ticker": , // Not required: If you do not pass this field it will. If you do it specifies a single market to be subscribed to. "market_tickers": // Not required: If you do not pass this field it will subscribe to ticker updates on all markets. If you do it will only send updates for the list of markets provided. } }` **This channel supports all subscription modes:** Single market mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["fill"], "market_ticker": "CPI-22DEC-TN0.1" } }` List of markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["fill"], "market_tickers": ["CPI-22DEC-TN0.1", "INXY-23DEC29-T2700"] } }` All markets mode: JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["fill"] } }` **Fill message (server => client)** A fill message will be sent for each trade that happens for your account on the server limited to the markets that are included in the subscription. Since this channel is private it will have all the identifiers so you can uniquely recognize each trade. Each fill message is equivalent to an entry in the [GetFills endpoint from the trade api](https://trading-api.readme.io/reference/getfills) . Schema: JSON `{ "type": "fill", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "trade_id": , // Unique identifier for fills. This is what you use to differentiate fills. "order_id": , // Unique identifier for orders. This is what you use to differentiate fills for different orders. "market_ticker": , // Unique identifier for markets. This is what you use to differentiate fills for different markets. "is_taker": , // If you were a taker on this fill. "side": , // Side of your fill. Either "yes" or "no". "yes_price": , // Price for the yes side of the fill. Between 1 and 99 (inclusive). "no_price": , // Price for the no side of the fill. Between 1 and 99 (inclusive). "count": , // Number of contracts filled. "action": , // Action that initiated the fill. Either "buy" or "sell". "ts": // Unix timestamp for when the update happened (in seconds). } }` Example: JSON `{ "type": "fill", "sid": 13, "msg": { "trade_id": "d91bc706-ee49-470d-82d8-11418bda6fed", "order_id": "ee587a1c-8b87-4dcf-b721-9f6f790619fa", "market_ticker": "HIGHNY-22DEC23-B53.5", "is_taker": true, "side": "yes", "yes_price": 75, "no_price": 25, "count": 278, "action": "buy", "ts": 1671899397 } }` Market Lifecycle V2 channel [](https://trading-api.readme.io/reference/ws#market-lifecycle-v2-channel) ---------------------------------------------------------------------------------------------------------- **Channel**: `market_lifecycle_v2` **Purpose**: Update the client with new market lifecycle events of the following types: open, (un-)pause, close, determination and settlement with corresponding details for each event. The difference from the older version (`market_lifecycle`) is that it only emits fields that correspond to the `event_type` and does not repeatedly remit fields that did not change for the market. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["market_lifecycle_v2"] // Required: Specifies the market_lifecycle_v2 channel. } }` **This channel only supports the All markets mode:** JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["market_lifecycle_v2"] } }` **`market_lifecycle_v2` message (server => client)** A `market_lifecycle_v2` message will be sent for every market on each of the following events: 1. (`event_type`: `created`) When a new market is created. For this case, an additional field named `additional_metadata` containing the market metadata will be emitted. The fields here directly map to the ones in They directly map to the fields on [https://trading-api.readme.io/reference/getmarket](https://trading-api.readme.io/reference/getmarket) 2. (`event_type`: `deactivated`) When a market's trading is paused 3. (`event_type`: `activated`) When a market's trading is un-paused 4. (`event_type`: `close_date_updated`) When a market's close date is updated (early close) 5. (`event_type`: `determined`) When a market is determined 6. (`event_type`: `settled`) When a market is settled Schema: JSON `{ "type": "market_lifecycle_v2", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "event_type": , // Field to annotate which of the event type this event is for "market_ticker": , // Unique identifier for markets. This is what you use to differentiate updates for different markets. "open_ts": , // Optional: This key will ONLY exist when the market is created. Unix timestamp for when the market opened (in seconds). "close_ts": , // Optional: This key will ONLY exist when the market is created OR when the close date is updated. Unix timestamp for when the market is scheduled to close (in seconds). Will be updated in case of early determination markets. "result": , // Optional: This key will ONLY exist when the market is determined. Result of the market. "determination_ts": , // Optional: This key will ONLY exist when the market is determined. Unix timestamp for when the market is determined (in seconds). "settled_ts": , // Optional: This key will ONLY exist when the market is settled. Unix timestamp for when the market is settled (in seconds). "is_deactivated": , // Optional: This key will ONLY exist when the market is paused/ unpaused. Boolean flag to indicate if trading is paused on an open market. This should only be interpreted for an open market. "additional_metadata": { // Optional: This key will only be emitted when the market is created. "name": , "title": , "yes_sub_title": , "no_sub_title": , "rules_primary": , "rules_secondary": , "can_close_early": , "expected_expiration_ts": , "strike_type": , "floor_strike": , "cap_strike": , "custom_strike": , } } }` Example: JSON `{ "type": "market_lifecycle_v2", "sid": 13, "msg": { "market_ticker": "INXD-23SEP14-B4487", "event_type": "created", "open_ts": 1694635200, "close_ts": 1694721600 } }` **`event_lifecycle` message (server => client)** An `event_lifecycle` message will be sent for when the event is created. Schema: JSON `{ "type": "event_lifecycle", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "event_ticker": , // Unique identifier for the event being created. "title": , // Title of event "sub_title": , // Subtitle of event "collateral_return_type": , // Collateral return type, MECNET or DIRECNET of the event. Empty if there is no collateral return scheme for the event. "series_ticker": , // Series ticker for the event. "strike_date": // Optional: String to indicate the strike period of the event if there is one. "strike_period": // Optional: String to indicate the strike period of the event if there is one. } }` Example: JSON `{ "type": "event_lifecycle", "sid": 5, "msg": { "event_ticker": "INXD-23SEP14", "title": "INX title", "sub_title": "INX subtitle", "collateral_return_type": "DIRECNET", "series_ticker": "INXD", "strike_date": 1694721600 } }` \[DEPRECATED\] Market Lifecycle channel [](https://trading-api.readme.io/reference/ws#deprecated-market-lifecycle-channel) ------------------------------------------------------------------------------------------------------------------------------ **Channel**: `market_lifecycle` **Purpose**: Update the client with new market lifecycle events of the following types: open, pause, close, determination and settlement with corresponding details for each event. **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["market_lifecycle"] // Required: Specifies the market lifecycle channel. } }` **This channel only supports the All markets mode:** JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["market_lifecycle"] } }` **`market_lifecycle` message (server => client)** A `market_lifecycle` message will be sent for every market on each of the following events: 1. When a new market is created. For this case, an additional field named `additional_metadata` containing the market metadata will be emitted. The fields here directly map to the ones in They directly map to the fields on [https://trading-api.readme.io/reference/getmarket](https://trading-api.readme.io/reference/getmarket) 2. When a market's trading is paused 3. When a market's close date is updated (early close) 4. When a market is determined 5. When a market is settled Schema: JSON `{ "type": "market_lifecycle", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "market_ticker": , // Unique identifier for markets. This is what you use to differentiate updates for different markets. "open_ts": , // Unix timestamp for when the market opened (in seconds). "close_ts": , // Unix timestamp for when the market is scheduled to close (in seconds). Will be updated in case of early determination markets. "determination_ts": , // Optional: This key will not exist before the market is determined. Unix timestamp for when the market is determined (in seconds). "settled_ts": , // Optional: This key will not exist before the market is settled. Unix timestamp for when the market is settled (in seconds). "result": , // Optional: This key will not exist before the market is determined. Result of the market. "is_deactivated": , // Boolean flag to indicate if trading is paused on an open market. This should only be interpreted for an open market. "additional_metadata": { // Optional: This key will only be emitted when the market is created. "name": , "title": , "yes_sub_title": , "no_sub_title": , "rules_primary": , "rules_secondary": , "can_close_early": , "expected_expiration_ts": , "strike_type": , "floor_strike": , "cap_strike": , "custom_strike": , } } }` Example: JSON `{ "type": "market_lifecycle", "sid": 13, "msg": { "market_ticker": "INXD-23SEP14-B4487", "open_ts": 1694635200, "close_ts": 1694721600, "determination_ts": 1694722100, "settled_ts": 0, "result": "no", "is_deactivated": false } }` **`event_lifecycle` message (server => client)** An `event_lifecycle` message will be sent for when the event is created. Schema: JSON `{ "type": "event_lifecycle", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "event_ticker": , // Unique identifier for the event being created. "title": , // Title of event "sub_title": , // Subtitle of event "collateral_return_type": , // Collateral return type, MECNET or DIRECNET of the event. Empty if there is no collateral return scheme for the event. "series_ticker": , // Series ticker for the event. "strike_date": // Optional: String to indicate the strike period of the event if there is one. "strike_period": // Optional: String to indicate the strike period of the event if there is one. } }` Example: JSON `{ "type": "event_lifecycle", "sid": 5, "msg": { "event_ticker": "INXD-23SEP14", "title": "INX title", "sub_title": "INX subtitle", "collateral_return_type": "DIRECNET", "series_ticker": "INXD", "strike_date": 1694721600 } }` Multivariate channel [](https://trading-api.readme.io/reference/ws#multivariate-channel) -------------------------------------------------------------------------------------------- **Channel**: `multivariate` **Purpose**: Update the client with new multivariate collection lookups **Subscription command (client => server)** Schema: JSON `{ "id": , // Required: Sequential command id maintained by the client. "cmd": "subscribe", // Required: Specifies the subscription operation. "params": { "channels": ["multivariate"] // Required: Specifies the multivariate channel. } }` **This channel only supports the All markets mode:** JSON `{ "id": 2, "cmd": "subscribe", "params": { "channels": ["multivariate"] } }` **`multivariate_lookup` message (server => client)** A `multivariate_lookup` message will be sent whenever there is a lookup on a multivariate market. Note that this channel is eventually consistent with the market\_lifecycle channel. The first time a lookup is recorded, you might receive the lookup message before the `market_lifecycle` message that corresponds to the market creation. Schema: JSON `{ "type": "multivariate_lookup", // Required: Message identifier, what you use to recognize this message type that arrive in your websocket connection. "sid": , // Required: Id of the subscription. "msg": { "collection_ticker": , "event_ticker": , "market_ticker": , "selected_markets": [ { "event_ticker": , "event_ticker": , "side": , } ] } }` Example: JSON `{ "type": "multivariate_lookup", "sid": 13, "msg": { "collection_ticker": "KXOSCARWINNERS-25", "event_ticker": "KXOSCARWINNERS-25C0CE5", "market_ticker": "KXOSCARWINNERS-25C0CE5-36353", "selected_markets": [ { "event_ticker": "KXOSCARACTO-25", "market_ticker": "KXOSCARACTO-25-AB", "side": "yes" }, { "event_ticker": "KXOSCARACTR-25", "market_ticker": "KXOSCARACTR-25-DM", "side": "yes" }, { "event_ticker": "KXOSCARANIMATED-25", "market_ticker": "KXOSCARANIMATED-25-TWR", "side": "yes" } ] } }` Heartbeats [](https://trading-api.readme.io/reference/ws#heartbeats) ======================================================================== We need a way to detect broken connections both on the client and the server sides. The WS protocol has standard ping/pong frames specifically for this purpose. **Server-side:** The server will send PING messages every 10 seconds to check for the connectivity with your client. Your client should respond with a PONG message or else the connection will be dropped on the server side. **Client-side:** The client should also send PING messages every 10 seconds to avoid trusting a stale connection in the client side. The programming languages usually support enabling heartbeat in the client, in such a way that you don't have to write the heartbeat messages yourself, if your programming language supports this we recommend that you enable it in order to have a reliable connection. For reference [](https://trading-api.readme.io/reference/ws#for-reference) ============================================================================== * [The Websocket Protocol (RFC 6455)](https://tools.ietf.org/html/rfc6455) * [Websocat CLI Tool](https://github.com/vi/websocat) --- # CreateQuote ShellNodeRubyPHPPython --- # Rate Limits and Tiers ### Access tiers: [](https://trading-api.readme.io/reference/tiers-and-rate-limits-1#access-tiers) | Tier | Read | Write | | --- | --- | --- | | Basic | 10 per second | 5 per second | | Advanced | 30 per second | 30 per second | | Premier | 100 per second | 100 per second | | Prime | 100 per second | 400 per second | * Qualification for tiers * Basic: Completing signup * Advanced: Completing [https://forms.gle/iMhGvPZ1yU173jk2A](https://forms.gle/iMhGvPZ1yU173jk2A) * Premier: 3.75% of exchange traded volume in a given month * Prime: 7.5% of exchange traded volume in a given month * In addition to the volume targets, technical competency is a requirement for Premier/Prime access. Before providing access to the Premier/Prime tiers, the Exchange will establish that the trader/trading entity has the following requirements met: * Knowledge of common security practices for API usage. * Proficiency in setting up monitoring for API usage, and ability to monitor API usage in near real-time. * Understanding and implementation of rate limiting and throttling mechanisms imposed by the API, and the ability to self-limit load. * Awareness of legal and compliance aspects related to API usage. * Only the following APIs fall under the write limit, for the batch APIs, each item in the batch is considered 1 transaction with the sole exception of BatchCancelOrders, where each cancel counts as 0.2 transactions. * [BatchCreateOrders](https://trading-api.readme.io/reference/batchcreateorders) * [BatchCancelOrders](https://trading-api.readme.io/reference/batchcancelorders) * [CreateOrder](https://trading-api.readme.io/reference/createorder) * [CancelOrder](https://trading-api.readme.io/reference/cancelorder) * [AmendOrder](https://trading-api.readme.io/reference/amendorder) * [DecreaseOrder](https://trading-api.readme.io/reference/decreaseorder) * We reserve the right to downgrade your API rate limit tier from Prime and Premier when you have shown lack of activity in the previous period --- # GetExchangeAnnouncements ShellNodeRubyPHPPython --- # GetExchangeSchedule ShellNodeRubyPHPPython --- # GetExchangeStatus ShellNodeRubyPHPPython --- # GetUserDataTimestamp ShellNodeRubyPHPPython --- # GetMilestone ShellNodeRubyPHPPython --- # GetMilestones ShellNodeRubyPHPPython --- # GetMultivariateEventCollections ShellNodeRubyPHPPython --- # GetMultivariateEventCollection ShellNodeRubyPHPPython --- # CreateMarketInMultivariateEventCollection ShellNodeRubyPHPPython --- # GetMultivariateEventCollectionLookupHistory ShellNodeRubyPHPPython --- # GetBalance ShellNodeRubyPHPPython --- # LookupTickersForMarketInMultivariateEventCollection ShellNodeRubyPHPPython --- # GetFills ShellNodeRubyPHPPython --- # BatchCreateOrders ShellNodeRubyPHPPython --- # CreateOrder ShellNodeRubyPHPPython --- # GetOrders ShellNodeRubyPHPPython --- # BatchCancelOrders ShellNodeRubyPHPPython --- # CancelOrder ShellNodeRubyPHPPython --- # AmendOrder ShellNodeRubyPHPPython --- # GetOrder ShellNodeRubyPHPPython --- # DecreaseOrder ShellNodeRubyPHPPython --- # GetPositions ShellNodeRubyPHPPython --- # GetOrderQueuePosition ShellNodeRubyPHPPython --- # GetStructuredTarget ShellNodeRubyPHPPython --- # GetPortfolioRestingOrderTotalValue ShellNodeRubyPHPPython --- # GetSettlements ShellNodeRubyPHPPython --- # GetOrderQueuePosition Endpoint Added [Back to All](https://trading-api.readme.io/changelog) GetOrderQueuePosition Endpoint Added [](https://trading-api.readme.io/changelog/00012_order_queue_position#getorderqueueposition-endpoint-added) ==================================================================================================================================================== We've added a new endpoint `GET /portfolio/orders/{order_id}/queue` that allows you to check the queue position of your resting orders. What's New [](https://trading-api.readme.io/changelog/00012_order_queue_position#whats-new) ----------------------------------------------------------------------------------------------- The `GetOrderQueuePosition` endpoint provides information about where your order sits in the order book queue. This is particularly useful for understanding: * How many contracts are ahead of your order at the same price level * Your order's priority for execution * Better visibility into order book dynamics Response Format [](https://trading-api.readme.io/changelog/00012_order_queue_position#response-format) ---------------------------------------------------------------------------------------------------------- The endpoint returns: * `queue_position`: The number of contracts ahead of your order at the same price level * `order_id`: The ID of the order queried Usage Example [](https://trading-api.readme.io/changelog/00012_order_queue_position#usage-example) ------------------------------------------------------------------------------------------------------ `GET /portfolio/orders/{order_id}/queue` This endpoint helps traders better understand their order's likelihood of execution and make more informed decisions about order management. --- # Breaking Changes to Order Struct [Back to All](https://trading-api.readme.io/changelog) removed This is a **breaking change** to the Order struct that is returned several places in the API. The following fields are being deprecated: `taker_fill_count`, `place_count`, `amend_count`, `amend_taker_fill_count`, `decrease_count`, `maker_fill_count`, `fcc_cancel_count`, `close_cancel_count`, `taker_self_trade_cancel_count`, `maker_self_trade_cancel_count`. Instead, the following three fields will be populated: * `remaining_count` already exists * `initial_count` represents the quantity the order was originally submitted with. * `fill_count` represents the quantity that has been filled. Users can still determine how much of their fill count was maker or taker by using the GetFills endpoint. #### API Version [](https://trading-api.readme.io/changelog/breaking-order-struct#api-version) 2.0.5 --- # Breaking Changes to Max Order Cost [Back to All](https://trading-api.readme.io/changelog) fixed This is a **breaking change** to the Max Order Cost field in CreateOrder. From now on, Max Order Cost is only accepted on orders with a Time-in-force of Fill-or-Kill. Setting max order cost with a different TiF will automatically convert the order to Fill-Or-Kill. #### API Version [](https://trading-api.readme.io/changelog/breaking-max-order-cost#api-version) 2.0.5 --- # Websocket Upgrades [Back to All](https://trading-api.readme.io/changelog) added new channels are added - `ticker_v2` and `market_lifecycle_v2` that are slightly different from their previous iterations and preparing the older versions to be retired soon (~1-2 weeks) with a new version release #### API Version [](https://trading-api.readme.io/changelog/websocket-upgrades-20250506#api-version) 2.0.4 (note that 2.0.5 has been announced but this is simply being added to the currently deployed 2.0.4 version) --- # Websocket Upgrades [Back to All](https://trading-api.readme.io/changelog) added delta messages in `orderbook_delta` will now "updated\_ts" and, when the update is caused by your order, a "client\_order\_id" field be populated as well. `no_price` is being removed from `fills` channel as it can be calculated from 1 - `yes_price`. #### API Version [](https://trading-api.readme.io/changelog/websocket-upgrades#api-version) 2.0.4 --- # Adding GetUserDataTimestamp [Back to All](https://trading-api.readme.io/changelog) added Adding GetUserDataTimestamp endpoint. There is typically a short delay before exchange events are reflected in the API endpoints. Whenever possible, combine API responses to PUT/POST/DELETE requests with websocket data to obtain the most accurate view of the exchange state. This endpoint provides an approximate indication of when the data from the following endpoints was last validated. GetBalance, GetOrder(s), GetFills, GetPositions #### API Version [](https://trading-api.readme.io/changelog/add-api-user-clock#api-version) 2.0.3 --- # GetMilestone PageSize -> Limit [Back to All](https://trading-api.readme.io/changelog) improved Consistent with our API conventions, GetMilestone now returns `limit` instead of `page_size` #### API Version [](https://trading-api.readme.io/changelog/get-milestone-limit#api-version) 2.0.1 --- # Undo Certain 2.0.1 Changes [Back to All](https://trading-api.readme.io/changelog) improved Due to the api log being new, some users were not able to prepare for the upcoming changes. We are releasing API version 2.0.2 on Friday March 7th 2025 to undo the changes in * [api field removals](https://trading-api.readme.io/changelog/removed-fields) All removed fields will be re-added. * [ws fills precision granularity](https://trading-api.readme.io/changelog/millisecond-precision) . GetFills will continue to returning millisecond precision. #### API Version [](https://trading-api.readme.io/changelog/undo-version-201-changes#api-version) 2.0.2 --- # https://trading-api.readme.io/ RSS for Node Sun, 13 Jul 2025 15:27:00 GMT https://trading-api.readme.io/v2.0.6/changelog/00012\_order\_queue\_position 0e5443be-d1f0-300f-9fd8-e92960fc1337 Tue, 24 Jun 2025 19:42:28 GMT https://trading-api.readme.io/v2.0.6/changelog/breaking-order-struct f340147c-7c8c-31b4-a8f3-f8bee9b36ca2 Mon, 09 Jun 2025 16:34:42 GMT removed https://trading-api.readme.io/v2.0.6/changelog/breaking-max-order-cost 6ffb60da-370b-34f5-ab2a-43ee0dcc01a6 Mon, 09 Jun 2025 16:29:31 GMT fixed https://trading-api.readme.io/v2.0.6/changelog/websocket-upgrades-20250506 2f5f6c99-3983-3a03-97d2-5ddc6d95cf3b Tue, 06 May 2025 21:36:10 GMT added https://trading-api.readme.io/v2.0.6/changelog/websocket-upgrades aae86f43-8671-368f-952f-dbb01c10467f Tue, 01 Apr 2025 21:09:18 GMT added https://trading-api.readme.io/v2.0.6/changelog/add-api-user-clock 6db4b23c-afe6-3faf-a248-93f928b05cc7 Tue, 18 Mar 2025 20:43:30 GMT added https://trading-api.readme.io/v2.0.6/changelog/undo-version-201-changes 10f0325f-fd6c-349a-b63e-55a8a179efef Thu, 06 Mar 2025 18:32:10 GMT improved Limit\]\]> https://trading-api.readme.io/v2.0.6/changelog/get-milestone-limit d86d87df-4582-356c-a6a6-9b7eebea02ae Sun, 02 Mar 2025 17:58:24 GMT improved https://trading-api.readme.io/v2.0.6/changelog/removed-fields b02217d2-096a-3f11-b064-39e13a589f5b Fri, 21 Feb 2025 16:14:39 GMT removed https://trading-api.readme.io/v2.0.6/changelog/version-endpoint cccf895e-32f2-3366-b1c2-c1e027820444 Wed, 19 Feb 2025 18:24:44 GMT added https://trading-api.readme.io/v2.0.6/changelog/rfq-cursor-response 067854dd-2138-3a01-bf2e-e1bf0c272d0d Tue, 18 Feb 2025 20:32:07 GMT fixed https://trading-api.readme.io/v2.0.6/changelog/millisecond-precision 778566be-7191-3260-92b6-a652aa5a5dc6 Tue, 18 Feb 2025 20:31:38 GMT fixed --- # Removed Fields From GetMarket(s) [Back to All](https://trading-api.readme.io/changelog) removed GetMarket(s) will no longer return fields `Title`, `Subtitle`, `NoSubTitle`, `FeeWaiverExpirationTime`, `RiskLimitCents` Orders will no longer contain `QueuePosition` OrderConfirmations, returned on create endpoints, will no longer contain `SelfTradePreventionType` #### API Version [](https://trading-api.readme.io/changelog/removed-fields#api-version) 2.0.1 --- # GetApiVersion [Back to All](https://trading-api.readme.io/changelog) added Added an endpoint that will give the current API version. This can be used to synchronize with changelog updates. #### API Version [](https://trading-api.readme.io/changelog/version-endpoint#api-version) 2.0.1 --- # Changelog fixed [GetRFQ Cursor Response](https://trading-api.readme.io/changelog/rfq-cursor-response) ====================================================================================== 5 months ago by ReadMe API In order to be consistent with pagination conventions, GetRFQs response will now be `cursor` instead of `next_cursor` fixed [GetFills Millisecond Precision](https://trading-api.readme.io/changelog/millisecond-precision) ================================================================================================ 5 months ago by ReadMe API GetFills `created_time` will now be returned in second precision to be consistent with websockets --- # GetFills Millisecond Precision [Back to All](https://trading-api.readme.io/changelog) fixed GetFills `created_time` will now be returned in second precision to be consistent with websockets #### API Version [](https://trading-api.readme.io/changelog/millisecond-precision#api-version) 2.0.1 --- # GetRFQ Cursor Response [Back to All](https://trading-api.readme.io/changelog) fixed In order to be consistent with pagination conventions, GetRFQs response will now be `cursor` instead of `next_cursor` #### API Version [](https://trading-api.readme.io/changelog/rfq-cursor-response#api-version) 2.0.1 --- # Changelog [GetOrderQueuePosition Endpoint Added](https://trading-api.readme.io/changelog/00012_order_queue_position) =========================================================================================================== 19 days ago by ReadMe API GetOrderQueuePosition Endpoint Added [](https://trading-api.readme.io/changelog?page=1#getorderqueueposition-endpoint-added) ================================================================================================================================ removed [Breaking Changes to Order Struct](https://trading-api.readme.io/changelog/breaking-order-struct) ================================================================================================== about 1 month ago by ReadMe API This is a **breaking change** to the Order struct that is returned several places in the API. The following fields are being deprecated: fixed [Breaking Changes to Max Order Cost](https://trading-api.readme.io/changelog/breaking-max-order-cost) ====================================================================================================== about 1 month ago by ReadMe API This is a **breaking change** to the Max Order Cost field in CreateOrder. added [Websocket Upgrades](https://trading-api.readme.io/changelog/websocket-upgrades-20250506) ========================================================================================== 2 months ago by ReadMe API new channels are added - `ticker_v2` and `market_lifecycle_v2` that are slightly different from their previous iterations and preparing the older versions to be retired soon (~1-2 weeks) with a new version release added [Websocket Upgrades](https://trading-api.readme.io/changelog/websocket-upgrades) ================================================================================= 3 months ago by ReadMe API delta messages in `orderbook_delta` will now "updated\_ts" and, when the update is caused by your order, a "client\_order\_id" field be populated as well. added [Adding GetUserDataTimestamp](https://trading-api.readme.io/changelog/add-api-user-clock) ========================================================================================== 4 months ago by ReadMe API Adding GetUserDataTimestamp endpoint. improved [Undo Certain 2.0.1 Changes](https://trading-api.readme.io/changelog/undo-version-201-changes) =============================================================================================== 4 months ago by ReadMe API Due to the api log being new, some users were not able to prepare for the upcoming changes. We are releasing API version 2.0.2 on Friday March 7th 2025 to undo the changes in improved [GetMilestone PageSize -> Limit](https://trading-api.readme.io/changelog/get-milestone-limit) ============================================================================================== 4 months ago by ReadMe API Consistent with our API conventions, GetMilestone now returns `limit` instead of `page_size` removed [Removed Fields From GetMarket(s)](https://trading-api.readme.io/changelog/removed-fields) =========================================================================================== 5 months ago by ReadMe API GetMarket(s) will no longer return fields `Title`, `Subtitle`, `NoSubTitle`, `FeeWaiverExpirationTime`, `RiskLimitCents` Orders will no longer contain `QueuePosition` OrderConfirmations, returned on create endpoints, will no longer contain `SelfTradePreventionType` added [GetApiVersion](https://trading-api.readme.io/changelog/version-endpoint) ========================================================================== 5 months ago by ReadMe API Added an endpoint that will give the current API version. This can be used to synchronize with changelog updates. ---