From d8827974b7385d1333d8e083e490109d72e2d42f Mon Sep 17 00:00:00 2001 From: Samuel Tinnerholm Date: Tue, 2 Jun 2026 11:38:41 +0000 Subject: [PATCH 1/5] docs: clarify historical fetch order book usage --- docs/api-reference/fetch-order-book.mdx | 95 +++++++++++++++++-------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/docs/api-reference/fetch-order-book.mdx b/docs/api-reference/fetch-order-book.mdx index 1aea6e43..55b0cb4d 100644 --- a/docs/api-reference/fetch-order-book.mdx +++ b/docs/api-reference/fetch-order-book.mdx @@ -7,7 +7,11 @@ openapi: GET /api/{exchange}/fetchOrderBook ### Live order book -Fetch the current L2 order book for an outcome. If you already have an outcome token ID, pass it directly: +Fetch the current L2 order book for an outcome from the exchange's live order book endpoint. For Polymarket this is a live CLOB call: pass the outcome token ID directly and omit historical params. + + +`poly.fetch_order_book(token_id)` without `params.since` or `params.until` is live-only. It does not read PMXT Archive data and may fail for closed, resolved, or otherwise inactive Polymarket markets with an error such as `No orderbook exists`. + ```python Python @@ -28,15 +32,15 @@ console.log(`${book.bids.length} bids, ${book.asks.length} asks`); ```bash curl curl "https://api.pmxt.dev/api/polymarket/fetchOrderBook?outcomeId=104932610032177696635191871147557737718087870958469629338467406422339967452218" \ - -H "Authorization: Bearer $PMXT_API_KEY" + -H "Authorization: Bearer ***" ``` ### Historical snapshot -Get the order book at a specific point in time. Pass `since` as a Unix timestamp in milliseconds — returns the nearest snapshot at or before that time. +Get the order book at a specific point in time by passing `since` as a Unix timestamp in milliseconds. Historical Polymarket queries are served from the PMXT Archive and return the nearest reconstructed snapshot at or before that time. -For binary markets, you can pass the market ID and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID: +For binary markets, you can pass the Polymarket condition ID as the first argument and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID. ```python Python @@ -44,12 +48,9 @@ import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -market = poly.fetch_market( - slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" -) - +# Historical lookup against PMXT Archive, not the live CLOB. book = poly.fetch_order_book( - market.market_id, + "0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", params={"since": 1779487200000, "outcome": "yes"}, ) @@ -63,12 +64,9 @@ import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -const market = await poly.fetchMarket({ - slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", -}); - +// Historical lookup against PMXT Archive, not the live CLOB. const book = await poly.fetchOrderBook( - market.marketId, + "0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", undefined, { since: 1779487200000, outcome: "yes" } ); @@ -79,9 +77,51 @@ console.log(` best ask: ${Math.min(...book.asks.map((a) => a.price)).toFixed(3) ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer $PMXT_API_KEY" \ + -H "Authorization: Bearer ***" \ + -H "Content-Type: application/json" \ + -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779487200000, "outcome": "yes"}]}' +``` + + +### Historical crypto 5m events + +Polymarket crypto 5-minute slugs such as `btc-updown-5m-1779481500` are event slugs. Use `fetch_event(slug=...)`, then select the nested market you want. Do not use `fetch_market(slug=...)` for these event-level slugs. + + +```python Python +import pmxt + +poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") +event = poly.fetch_event(slug="btc-updown-5m-1779481500") +market = event.markets[0] + +book = poly.fetch_order_book( + market.market_id, + params={"since": 1779487200000, "outcome": "yes"}, +) +print(f"{market.title}: {book.dt}") +``` + +```javascript JavaScript +import { Polymarket } from "pmxtjs"; + +const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); +const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); +const market = event.markets[0]; + +const book = await poly.fetchOrderBook( + market.marketId, + undefined, + { since: 1779487200000, outcome: "yes" } +); +console.log(`${market.title}: ${book.datetime}`); +``` + +```bash curl +curl -X POST "https://api.pmxt.dev/api/polymarket/fetchEvent" \ + -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ - -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779487200000, "outcome": "yes"}]}' + -d '{"kwargs":{"slug":"btc-updown-5m-1779481500"}}' ``` @@ -89,17 +129,15 @@ curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ Pass both `since` and `until` to get an array of fully reconstructed L2 order book snapshots. Each snapshot is a complete book at that moment in time — not deltas. -Default 100 snapshots per request, max 1000. +The API returns up to `limit` snapshots from the PMXT Archive. Defaults to 100 snapshots per request, max 1000. For raw bulk downloads, use the Parquet files in the [PMXT Archive](https://archive.pmxt.dev) instead of trying to stream bulk data through the live order book endpoint. ```python Python import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") - -market = poly.fetch_market( - slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" -) +event = poly.fetch_event(slug="btc-updown-5m-1779481500") +market = event.markets[0] books = poly.fetch_order_book( market.market_id, @@ -107,6 +145,7 @@ books = poly.fetch_order_book( "since": 1779480000000, "until": 1779487200000, "outcome": "yes", + "limit": 100, } ) print(f"{len(books)} snapshots") @@ -118,15 +157,13 @@ for ob in books[:3]: import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); - -const market = await poly.fetchMarket({ - slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", -}); +const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); +const market = event.markets[0]; const books = await poly.fetchOrderBook( market.marketId, undefined, - { since: 1779480000000, until: 1779487200000, outcome: "yes" } + { since: 1779480000000, until: 1779487200000, outcome: "yes", limit: 100 } ); console.log(`${books.length} snapshots`); books.slice(0, 3).forEach((ob) => @@ -136,12 +173,12 @@ books.slice(0, 3).forEach((ob) => ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer $PMXT_API_KEY" \ + -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ - -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes"}]}' + -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes", "limit": 100}]}' ``` -Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Supports Polymarket, Kalshi, Limitless, and Opinion. +Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Historical `fetchOrderBook` supports Polymarket, Kalshi, Limitless, and Opinion. From 66218e79ada553281c9e39cab3b2083582e90a65 Mon Sep 17 00:00:00 2001 From: Samuel Tinnerholm Date: Tue, 2 Jun 2026 11:41:32 +0000 Subject: [PATCH 2/5] docs: sync generated API docs --- core/src/server/openapi.yaml | 296 +++-------------------------------- docs/llms-full.txt | 96 ++++++++---- 2 files changed, 85 insertions(+), 307 deletions(-) diff --git a/core/src/server/openapi.yaml b/core/src/server/openapi.yaml index 6c1789f8..c91cfce5 100644 --- a/core/src/server/openapi.yaml +++ b/core/src/server/openapi.yaml @@ -72,26 +72,7 @@ paths: summary: Fetch Markets operationId: fetchMarkets parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - - metaculus - - smarkets - - polymarket_us - - suibets - - router - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: limit required: false @@ -277,26 +258,7 @@ paths: summary: Fetch Events operationId: fetchEvents parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - - metaculus - - smarkets - - polymarket_us - - suibets - - router - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: query required: false @@ -421,19 +383,7 @@ paths: summary: Fetch Series operationId: fetchSeries parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - opinion - - polymarket_us - - router - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' responses: '200': description: Fetch Series response @@ -687,21 +637,7 @@ paths: summary: Fetch OHLCV operationId: fetchOHLCV parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: outcomeId required: true @@ -753,25 +689,7 @@ paths: summary: Fetch Order Book operationId: fetchOrderBook parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - - smarkets - - polymarket_us - - suibets - - router - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: outcomeId required: true @@ -839,16 +757,7 @@ paths: summary: Fetch Order Books operationId: fetchOrderBooks parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' requestBody: content: application/json: @@ -890,21 +799,7 @@ paths: summary: Fetch Trades operationId: fetchTrades parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - smarkets - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: outcomeId required: true @@ -950,24 +845,7 @@ paths: summary: Create Order operationId: createOrder parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - - metaculus - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' requestBody: content: application/json: @@ -1003,19 +881,7 @@ paths: summary: Build Order operationId: buildOrder parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - opinion - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' requestBody: content: application/json: @@ -1053,19 +919,7 @@ paths: summary: Submit Order operationId: submitOrder parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - opinion - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' requestBody: content: application/json: @@ -1101,22 +955,7 @@ paths: summary: Cancel Order operationId: cancelOrder parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - opinion - - metaculus - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' requestBody: content: application/json: @@ -1152,21 +991,7 @@ paths: summary: Fetch Order operationId: fetchOrder parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - probable - - baozi - - opinion - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: orderId required: true @@ -1190,23 +1015,7 @@ paths: summary: Fetch Open Orders operationId: fetchOpenOrders parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: marketId required: false @@ -1232,22 +1041,7 @@ paths: summary: Fetch My Trades operationId: fetchMyTrades parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - myriad - - opinion - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: outcomeId required: false @@ -1305,18 +1099,7 @@ paths: summary: Fetch Closed Orders operationId: fetchClosedOrders parameters: - - in: path - name: exchange - schema: - type: string - enum: - - kalshi - - kalshi-demo - - limitless - - opinion - - smarkets - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: marketId required: false @@ -1368,18 +1151,7 @@ paths: summary: Fetch All Orders operationId: fetchAllOrders parameters: - - in: path - name: exchange - schema: - type: string - enum: - - kalshi - - kalshi-demo - - limitless - - opinion - - smarkets - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: marketId required: false @@ -1431,24 +1203,7 @@ paths: summary: Fetch Positions operationId: fetchPositions parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - opinion - - smarkets - - polymarket_us - - suibets - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: address required: false @@ -1474,22 +1229,7 @@ paths: summary: Fetch Balance operationId: fetchBalance parameters: - - in: path - name: exchange - schema: - type: string - enum: - - polymarket - - kalshi - - kalshi-demo - - limitless - - probable - - baozi - - myriad - - smarkets - - polymarket_us - required: true - description: The prediction market exchange to target. + - $ref: '#/components/parameters/ExchangeParam' - in: query name: address required: false diff --git a/docs/llms-full.txt b/docs/llms-full.txt index 55c492dc..bbf82c1f 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -3274,7 +3274,12 @@ Source: https://pmxt.dev/docs/api-reference/fetch-order-book ##### Live order book -Fetch the current L2 order book for an outcome. If you already have an outcome token ID, pass it directly: +Fetch the current L2 order book for an outcome from the exchange's live order book endpoint. For Polymarket this is a live CLOB call: pass the outcome token ID directly and omit historical params. + + +> **Warning:** +`poly.fetch_order_book(token_id)` without `params.since` or `params.until` is live-only. It does not read PMXT Archive data and may fail for closed, resolved, or otherwise inactive Polymarket markets with an error such as `No orderbook exists`. + ```python Python @@ -3295,15 +3300,15 @@ console.log(`${book.bids.length} bids, ${book.asks.length} asks`); ```bash curl curl "https://api.pmxt.dev/api/polymarket/fetchOrderBook?outcomeId=104932610032177696635191871147557737718087870958469629338467406422339967452218" \ - -H "Authorization: Bearer $PMXT_API_KEY" + -H "Authorization: Bearer ***" ``` ##### Historical snapshot -Get the order book at a specific point in time. Pass `since` as a Unix timestamp in milliseconds — returns the nearest snapshot at or before that time. +Get the order book at a specific point in time by passing `since` as a Unix timestamp in milliseconds. Historical Polymarket queries are served from the PMXT Archive and return the nearest reconstructed snapshot at or before that time. -For binary markets, you can pass the market ID and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID: +For binary markets, you can pass the Polymarket condition ID as the first argument and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID. ```python Python @@ -3311,12 +3316,9 @@ import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -market = poly.fetch_market( -slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" -) - +# Historical lookup against PMXT Archive, not the live CLOB. book = poly.fetch_order_book( -market.market_id, +"0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", params={"since": 1779487200000, "outcome": "yes"}, ) @@ -3330,12 +3332,9 @@ import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -const market = await poly.fetchMarket({ - slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", -}); - +// Historical lookup against PMXT Archive, not the live CLOB. const book = await poly.fetchOrderBook( - market.marketId, + "0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", undefined, { since: 1779487200000, outcome: "yes" } ); @@ -3346,9 +3345,51 @@ console.log(` best ask: ${Math.min(...book.asks.map((a) => a.price)).toFixed(3) ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer $PMXT_API_KEY" \ + -H "Authorization: Bearer ***" \ + -H "Content-Type: application/json" \ + -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779487200000, "outcome": "yes"}]}' +``` + + +##### Historical crypto 5m events + +Polymarket crypto 5-minute slugs such as `btc-updown-5m-1779481500` are event slugs. Use `fetch_event(slug=...)`, then select the nested market you want. Do not use `fetch_market(slug=...)` for these event-level slugs. + + +```python Python +import pmxt + +poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") +event = poly.fetch_event(slug="btc-updown-5m-1779481500") +market = event.markets[0] + +book = poly.fetch_order_book( +market.market_id, +params={"since": 1779487200000, "outcome": "yes"}, +) +print(f"{market.title}: {book.dt}") +``` + +```javascript JavaScript +import { Polymarket } from "pmxtjs"; + +const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); +const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); +const market = event.markets[0]; + +const book = await poly.fetchOrderBook( + market.marketId, + undefined, + { since: 1779487200000, outcome: "yes" } +); +console.log(`${market.title}: ${book.datetime}`); +``` + +```bash curl +curl -X POST "https://api.pmxt.dev/api/polymarket/fetchEvent" \ + -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ - -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779487200000, "outcome": "yes"}]}' + -d '{"kwargs":{"slug":"btc-updown-5m-1779481500"}}' ``` @@ -3356,17 +3397,15 @@ curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ Pass both `since` and `until` to get an array of fully reconstructed L2 order book snapshots. Each snapshot is a complete book at that moment in time — not deltas. -Default 100 snapshots per request, max 1000. +The API returns up to `limit` snapshots from the PMXT Archive. Defaults to 100 snapshots per request, max 1000. For raw bulk downloads, use the Parquet files in the [PMXT Archive](https://archive.pmxt.dev) instead of trying to stream bulk data through the live order book endpoint. ```python Python import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") - -market = poly.fetch_market( -slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" -) +event = poly.fetch_event(slug="btc-updown-5m-1779481500") +market = event.markets[0] books = poly.fetch_order_book( market.market_id, @@ -3374,6 +3413,7 @@ params={ "since": 1779480000000, "until": 1779487200000, "outcome": "yes", + "limit": 100, } ) print(f"{len(books)} snapshots") @@ -3385,15 +3425,13 @@ print(f" {ob.dt} bid={ob.bids[0].price} ask={ob.asks[0].price}") import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); - -const market = await poly.fetchMarket({ - slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", -}); +const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); +const market = event.markets[0]; const books = await poly.fetchOrderBook( market.marketId, undefined, - { since: 1779480000000, until: 1779487200000, outcome: "yes" } + { since: 1779480000000, until: 1779487200000, outcome: "yes", limit: 100 } ); console.log(`${books.length} snapshots`); books.slice(0, 3).forEach((ob) => @@ -3403,15 +3441,15 @@ books.slice(0, 3).forEach((ob) => ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer $PMXT_API_KEY" \ + -H "Authorization: Bearer ***" \ -H "Content-Type: application/json" \ - -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes"}]}' + -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes", "limit": 100}]}' ``` > **Note:** -Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Supports Polymarket, Kalshi, Limitless, and Opinion. +Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Historical `fetchOrderBook` supports Polymarket, Kalshi, Limitless, and Opinion. ### Fetch Order Books From 266b702d99573dfbee4c1d28c12c94029314543d Mon Sep 17 00:00:00 2001 From: Samuel Tinnerholm Date: Fri, 5 Jun 2026 13:28:25 +0000 Subject: [PATCH 3/5] fix(python): tighten SDK type annotations --- core/scripts/generate-python-exchanges.js | 4 +- sdks/python/pmxt/__init__.py | 2 +- sdks/python/pmxt/_exchanges.py | 34 +++++----- sdks/python/pmxt/client.py | 82 +++++++++++------------ sdks/python/pmxt/errors.py | 6 +- sdks/python/pmxt/router.py | 8 +-- sdks/python/pmxt/server_manager.py | 2 +- sdks/python/pmxt/ws_client.py | 4 +- 8 files changed, 71 insertions(+), 71 deletions(-) diff --git a/core/scripts/generate-python-exchanges.js b/core/scripts/generate-python-exchanges.js index c20458a4..ee0739d9 100644 --- a/core/scripts/generate-python-exchanges.js +++ b/core/scripts/generate-python-exchanges.js @@ -167,7 +167,7 @@ function generateClass(exchange) { } if (creds.signatureType) { const defaultVal = defaults['signature_type'] || 'None'; - constructorParams.push(`signature_type: Optional[Any] = ${defaultVal}`); + constructorParams.push(`signature_type: Optional[str] = ${defaultVal}`); superArgs.push('signature_type=signature_type'); } constructorParams.push('base_url: Optional[str] = None'); @@ -204,7 +204,7 @@ function generateClass(exchange) { indent4('def __init__('), indent8('self,'), ...constructorParams.map(p => indent8(`${p},`)), - indent4('):'), + indent4(') -> None:'), indent8('"""'), indent8(`Initialize ${className} client.`), '', diff --git a/sdks/python/pmxt/__init__.py b/sdks/python/pmxt/__init__.py index 171a6ca8..8382be5f 100644 --- a/sdks/python/pmxt/__init__.py +++ b/sdks/python/pmxt/__init__.py @@ -100,7 +100,7 @@ class _ServerNamespace: __slots__ = ("_manager",) - def __init__(self, manager: ServerManager): + def __init__(self, manager: ServerManager) -> None: self._manager = manager def status(self) -> Dict[str, Any]: diff --git a/sdks/python/pmxt/_exchanges.py b/sdks/python/pmxt/_exchanges.py index 5368bc6f..ac27bf3c 100644 --- a/sdks/python/pmxt/_exchanges.py +++ b/sdks/python/pmxt/_exchanges.py @@ -17,11 +17,11 @@ def __init__( passphrase: Optional[str] = None, private_key: Optional[str] = None, proxy_address: Optional[str] = None, - signature_type: Optional[Any] = "gnosis-safe", + signature_type: Optional[str] = "gnosis-safe", base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Polymarket client. @@ -76,7 +76,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Limitless client. @@ -120,7 +120,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Kalshi client. @@ -151,7 +151,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize KalshiDemo client. @@ -184,7 +184,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Probable client. @@ -227,7 +227,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Baozi client. @@ -256,7 +256,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Myriad client. @@ -288,7 +288,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Opinion client. @@ -320,7 +320,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Metaculus client. @@ -349,7 +349,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Smarkets client. @@ -380,7 +380,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize PolymarketUS client. @@ -411,7 +411,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Hyperliquid client. @@ -442,7 +442,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize GeminiTitan client. @@ -478,7 +478,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize SuiBets client. @@ -503,7 +503,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Mock client. @@ -528,7 +528,7 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize Router client. diff --git a/sdks/python/pmxt/client.py b/sdks/python/pmxt/client.py index 741a8d92..2a29507f 100644 --- a/sdks/python/pmxt/client.py +++ b/sdks/python/pmxt/client.py @@ -13,7 +13,7 @@ import uuid from abc import ABC from datetime import datetime -from typing import Callable, List, Optional, Dict, Any, Literal, Union +from typing import Callable, List, Optional, Dict, Any, Literal, Union, Type # Add generated client to path _GENERATED_PATH = os.path.join(os.path.dirname(__file__), "..", "generated") @@ -88,7 +88,7 @@ def _convert_params_to_camel(params: Dict[str, Any]) -> Dict[str, Any]: return {_snake_to_camel(k): v for k, v in params.items()} -def _auto_convert(cls, raw: Dict[str, Any], **overrides): +def _auto_convert(cls: Type[Any], raw: Dict[str, Any], **overrides: Any) -> Any: """Auto-map camelCase raw dict to snake_case dataclass fields. Iterates over the dataclass fields, looks up the camelCase key in ``raw``, @@ -292,9 +292,9 @@ def __init__( base_url: Optional[str] = None, auto_start_server: Optional[bool] = None, proxy_address: Optional[str] = None, - signature_type: Optional[Any] = None, + signature_type: Optional[str] = None, pmxt_api_key: Optional[str] = None, - ): + ) -> None: """ Initialize an exchange client. @@ -773,7 +773,7 @@ def fetch_markets(self, params: Optional[dict] = None, **kwargs) -> List[Unified params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -796,7 +796,7 @@ def fetch_markets_paginated(self, params: Optional[dict] = None, **kwargs) -> Pa params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -823,7 +823,7 @@ def fetch_events(self, params: Optional[dict] = None, **kwargs) -> List[UnifiedE params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -846,7 +846,7 @@ def fetch_series(self, params: Optional[dict] = None, **kwargs) -> List[UnifiedS params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -869,7 +869,7 @@ def fetch_market(self, params: Optional[dict] = None, **kwargs) -> UnifiedMarket params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -892,7 +892,7 @@ def fetch_event(self, params: Optional[dict] = None, **kwargs) -> UnifiedEvent: params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -921,7 +921,7 @@ def fetch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, lim if limit is None: args.append(None) args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -943,7 +943,7 @@ def fetch_order_books(self, outcome_ids: List[Union[str, "MarketOutcome"]]) -> D try: args = [] args.append([_resolve_outcome_id(x) for x in outcome_ids]) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -963,7 +963,7 @@ def cancel_order(self, order_id: str) -> Order: try: args = [] args.append(order_id) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -983,7 +983,7 @@ def fetch_order(self, order_id: str) -> Order: try: args = [] args.append(order_id) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1004,7 +1004,7 @@ def fetch_open_orders(self, market_id: Optional[str] = None) -> List[Order]: args = [] if market_id is not None: args.append(market_id) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1027,7 +1027,7 @@ def fetch_my_trades(self, params: Optional[dict] = None, **kwargs) -> List[UserT params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1050,7 +1050,7 @@ def fetch_closed_orders(self, params: Optional[dict] = None, **kwargs) -> List[O params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1073,7 +1073,7 @@ def fetch_all_orders(self, params: Optional[dict] = None, **kwargs) -> List[Orde params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1094,7 +1094,7 @@ def fetch_positions(self, address: Optional[str] = None) -> List[Position]: args = [] if address is not None: args.append(address) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1115,7 +1115,7 @@ def fetch_balance(self, address: Optional[str] = None) -> List[Balance]: args = [] if address is not None: args.append(address) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1136,7 +1136,7 @@ def unwatch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, * args = [] outcome_id = _compat_id(outcome_id, _compat_kwargs) args.append(_resolve_outcome_id(outcome_id)) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1155,7 +1155,7 @@ def unwatch_address(self, address: str) -> None: try: args = [] args.append(address) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1173,7 +1173,7 @@ def unwatch_address(self, address: str) -> None: def close(self) -> None: try: args = [] - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1195,7 +1195,7 @@ def fetch_market_matches(self, params: Optional[dict] = None, **kwargs) -> List[ params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1211,13 +1211,13 @@ def fetch_market_matches(self, params: Optional[dict] = None, **kwargs) -> List[ except ApiException as e: raise self._parse_api_exception(e) from None - def fetch_matches(self, params: dict, **kwargs) -> List[Any]: + def fetch_matches(self, params: Dict[str, Any], **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1240,7 +1240,7 @@ def fetch_event_matches(self, params: Optional[dict] = None, **kwargs) -> List[A params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1256,13 +1256,13 @@ def fetch_event_matches(self, params: Optional[dict] = None, **kwargs) -> List[A except ApiException as e: raise self._parse_api_exception(e) from None - def compare_market_prices(self, params: dict, **kwargs) -> List[Any]: + def compare_market_prices(self, params: Dict[str, Any], **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1278,13 +1278,13 @@ def compare_market_prices(self, params: dict, **kwargs) -> List[Any]: except ApiException as e: raise self._parse_api_exception(e) from None - def fetch_related_markets(self, params: dict, **kwargs) -> List[Any]: + def fetch_related_markets(self, params: Dict[str, Any], **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1307,7 +1307,7 @@ def fetch_matched_markets(self, params: Optional[dict] = None, **kwargs) -> List params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1330,7 +1330,7 @@ def fetch_matched_prices(self, params: Optional[dict] = None, **kwargs) -> List[ params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1346,13 +1346,13 @@ def fetch_matched_prices(self, params: Optional[dict] = None, **kwargs) -> List[ except ApiException as e: raise self._parse_api_exception(e) from None - def fetch_hedges(self, params: dict, **kwargs) -> List[Any]: + def fetch_hedges(self, params: Dict[str, Any], **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1375,7 +1375,7 @@ def fetch_arbitrage(self, params: Optional[dict] = None, **kwargs) -> List[Any]: params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1798,7 +1798,7 @@ def _watch_via_ws( def _ws_required_error(self, method_name: str) -> PmxtError: return PmxtError(f"{method_name}() requires WebSocket transport — connection failed") - def _require_ws_transport(self, method_name: str): + def _require_ws_transport(self, method_name: str) -> "SidecarWsClient": ws = self._get_or_create_ws() if ws is None: raise self._ws_required_error(method_name) @@ -2021,7 +2021,7 @@ def watch_all_order_books( raise PmxtError("watch_all_order_books() requires hosted mode (set pmxt_api_key)") effective_venues = venues if venues is not None else self._default_watch_all_order_book_venues() - args: list = [effective_venues] if effective_venues else [] + args: List[Any] = [effective_venues] if effective_venues else [] data = self._watch_via_ws("watchAllOrderBooks", args) if data is not None: return FirehoseEvent( @@ -2114,11 +2114,11 @@ def watch_address( ... print(f"Trade: {snapshot.trades}") """ try: - args: list = [address] + args: List[Any] = [address] if types is not None: args.append(types) - body: dict = {"args": args} + body: Dict[str, Any] = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -2155,7 +2155,7 @@ def unwatch_address( None """ try: - body: dict = {"args": [address]} + body: Dict[str, Any] = {"args": [address]} creds = self._get_credentials_dict() if creds: body["credentials"] = creds diff --git a/sdks/python/pmxt/errors.py b/sdks/python/pmxt/errors.py index 16d999c2..59f08869 100644 --- a/sdks/python/pmxt/errors.py +++ b/sdks/python/pmxt/errors.py @@ -13,7 +13,7 @@ class PmxtError(Exception): """Base error class for all pmxt errors.""" - def __init__(self, message: str, code: str = "UNKNOWN_ERROR", retryable: bool = False, exchange: str | None = None): + def __init__(self, message: str, code: str = "UNKNOWN_ERROR", retryable: bool = False, exchange: str | None = None) -> None: super().__init__(message) self.message = message self.code = code @@ -67,7 +67,7 @@ class EventNotFound(NotFoundError): class RateLimitExceeded(PmxtError): """429 Too Many Requests - Rate limit exceeded.""" - def __init__(self, message: str, retry_after: int | None = None, **kwargs): + def __init__(self, message: str, retry_after: int | None = None, **kwargs) -> None: super().__init__(message, **kwargs) self.retry_after = retry_after @@ -85,7 +85,7 @@ class InsufficientFunds(PmxtError): class ValidationError(PmxtError): """400 Bad Request - Input validation failed.""" - def __init__(self, message: str, field: str | None = None, **kwargs): + def __init__(self, message: str, field: str | None = None, **kwargs) -> None: super().__init__(message, **kwargs) self.field = field diff --git a/sdks/python/pmxt/router.py b/sdks/python/pmxt/router.py index da2cc666..edd735e1 100644 --- a/sdks/python/pmxt/router.py +++ b/sdks/python/pmxt/router.py @@ -25,7 +25,7 @@ from pmxt_internal.exceptions import ApiException -def _parse_market(raw: Any) -> UnifiedMarket: +def _parse_market(raw: Any) -> Any: """Best-effort parse of a raw market dict into UnifiedMarket.""" if isinstance(raw, UnifiedMarket): return raw @@ -34,7 +34,7 @@ def _parse_market(raw: Any) -> UnifiedMarket: return raw -def _parse_event(raw: Any) -> UnifiedEvent: +def _parse_event(raw: Any) -> Any: """Best-effort parse of a raw event dict into UnifiedEvent.""" if isinstance(raw, UnifiedEvent): return raw @@ -124,7 +124,7 @@ def __init__( pmxt_api_key: Optional[str] = None, base_url: Optional[str] = None, auto_start_server: bool = False, - ): + ) -> None: """ Initialize the Router. @@ -303,7 +303,7 @@ def fetch_event_matches( results.append(EventMatchResult(event=event, market_matches=market_matches)) return results - def _get_catalog_path(self, path: str, params: Dict[str, Any]) -> Any: + def _get_catalog_path(self, path: str, params: Dict[str, Any]) -> Dict[str, Any]: """GET a hosted catalog /v0 path and return its raw JSON body.""" qs = self._build_sidecar_query_string(params) url = f"{self._resolve_sidecar_host()}{path}{'?' + qs if qs else ''}" diff --git a/sdks/python/pmxt/server_manager.py b/sdks/python/pmxt/server_manager.py index 008939be..9613652d 100644 --- a/sdks/python/pmxt/server_manager.py +++ b/sdks/python/pmxt/server_manager.py @@ -53,7 +53,7 @@ class ServerManager: # must share the same critical section. _ensure_lock = threading.Lock() - def __init__(self, base_url: str = "http://localhost:3847"): + def __init__(self, base_url: str = "http://localhost:3847") -> None: """ Initialize the server manager. diff --git a/sdks/python/pmxt/ws_client.py b/sdks/python/pmxt/ws_client.py index 329dd680..808aef27 100644 --- a/sdks/python/pmxt/ws_client.py +++ b/sdks/python/pmxt/ws_client.py @@ -50,7 +50,7 @@ class _WsSubscription: __slots__ = ("request_id", "method", "symbols", "event") - def __init__(self, request_id: str, method: str, symbols: List[str]): + def __init__(self, request_id: str, method: str, symbols: List[str]) -> None: self.request_id = request_id self.method = method self.symbols = symbols @@ -66,7 +66,7 @@ class SidecarWsClient: may invoke subscribe/receive from any thread. """ - def __init__(self, host: str, access_token: Optional[str] = None, api_key: Optional[str] = None): + def __init__(self, host: str, access_token: Optional[str] = None, api_key: Optional[str] = None) -> None: self._host = host self._access_token = access_token self._api_key = api_key From bae2ff5d68db5064a00d6301cde038e1d4f03fde Mon Sep 17 00:00:00 2001 From: Samuel Tinnerholm Date: Fri, 5 Jun 2026 14:22:07 +0000 Subject: [PATCH 4/5] chore: sync generated outputs for type annotation PR --- core/api-doc-config.generated.json | 36 +-- core/src/server/openapi.yaml | 296 ++++++++++++++++++++++-- docs/api-reference/fetch-order-book.mdx | 95 +++----- docs/llms-full.txt | 96 +++----- sdks/python/API_REFERENCE.md | 2 +- sdks/python/pmxt/client.py | 64 ++--- sdks/typescript/API_REFERENCE.md | 2 +- 7 files changed, 388 insertions(+), 203 deletions(-) diff --git a/core/api-doc-config.generated.json b/core/api-doc-config.generated.json index 3e176c67..7929ab04 100644 --- a/core/api-doc-config.generated.json +++ b/core/api-doc-config.generated.json @@ -1,5 +1,5 @@ { - "_generated": "Auto-generated by extract-jsdoc.js on 2026-06-02T00:34:44.916Z. Do not edit manually.", + "_generated": "Auto-generated by extract-jsdoc.js on 2026-06-05T14:21:50.064Z. Do not edit manually.", "methods": { "has": { "summary": "HTTP verb for the endpoint (e.g. GET, POST). */", @@ -566,7 +566,7 @@ "type": "UnifiedEvent[]", "description": "Filtered array of events" }, - "source": "BaseExchange.ts:1317" + "source": "BaseExchange.ts:1318" }, "watchOrderBook": { "summary": "Watch order book updates in real-time via WebSocket.", @@ -595,7 +595,7 @@ "type": "OrderBook", "description": "Promise that resolves with the current orderbook state" }, - "source": "BaseExchange.ts:1413" + "source": "BaseExchange.ts:1414" }, "watchOrderBooks": { "summary": "Watch multiple order books simultaneously via WebSocket.", @@ -624,7 +624,7 @@ "type": "Record", "description": "Promise that resolves with order books keyed by ID" }, - "source": "BaseExchange.ts:1426" + "source": "BaseExchange.ts:1427" }, "unwatchOrderBook": { "summary": "Unsubscribe from a previously watched order book stream.", @@ -641,7 +641,7 @@ "type": "void", "description": "Result" }, - "source": "BaseExchange.ts:1454" + "source": "BaseExchange.ts:1455" }, "watchTrades": { "summary": "Watch trade executions in real-time via WebSocket.", @@ -676,7 +676,7 @@ "type": "Trade[]", "description": "Promise that resolves with recent trades" }, - "source": "BaseExchange.ts:1467" + "source": "BaseExchange.ts:1468" }, "watchAddress": { "summary": "Stream activity for a public wallet address", @@ -699,7 +699,7 @@ "type": "SubscribedAddressSnapshot", "description": "Promise that resolves with the latest SubscribedAddressSnapshot snapshot" }, - "source": "BaseExchange.ts:1481" + "source": "BaseExchange.ts:1482" }, "unwatchAddress": { "summary": "Stop watching a previously registered wallet address and release its resource updates.", @@ -716,7 +716,7 @@ "type": "void", "description": "Result" }, - "source": "BaseExchange.ts:1494" + "source": "BaseExchange.ts:1495" }, "close": { "summary": "Close all WebSocket connections and clean up resources.", @@ -726,7 +726,7 @@ "type": "void", "description": "Result" }, - "source": "BaseExchange.ts:1503" + "source": "BaseExchange.ts:1504" }, "fetchMarketMatches": { "summary": "Find the same or related market on other venues. Two modes:", @@ -743,7 +743,7 @@ "type": "MatchResult[]", "description": "Array of matched markets with relation and confidence" }, - "source": "BaseExchange.ts:1517" + "source": "BaseExchange.ts:1518" }, "fetchMatches": { "summary": "fetchMatches", @@ -760,7 +760,7 @@ "type": "MatchResult[]", "description": "Result" }, - "source": "BaseExchange.ts:1533" + "source": "BaseExchange.ts:1534" }, "fetchEventMatches": { "summary": "Find the same or related event on other venues. Two modes:", @@ -777,7 +777,7 @@ "type": "EventMatchResult[]", "description": "Array of matched events with market-level match details" }, - "source": "BaseExchange.ts:1541" + "source": "BaseExchange.ts:1542" }, "compareMarketPrices": { "summary": "Compare live prices for the same market across venues. Finds identity matches and returns side-by-side best bid/ask prices so you can spot price differences at a glance.", @@ -794,7 +794,7 @@ "type": "PriceComparison[]", "description": "Array of price comparisons across venues" }, - "source": "BaseExchange.ts:1557" + "source": "BaseExchange.ts:1558" }, "fetchRelatedMarkets": { "summary": "Find related markets across venues. Discovers subset/superset market relationships", @@ -811,7 +811,7 @@ "type": "PriceComparison[]", "description": "Array of subset/superset matches with live prices" }, - "source": "BaseExchange.ts:1567" + "source": "BaseExchange.ts:1568" }, "fetchMatchedMarkets": { "summary": "fetchMatchedMarkets", @@ -828,7 +828,7 @@ "type": "MatchedMarketPair[]", "description": "Result" }, - "source": "BaseExchange.ts:1578" + "source": "BaseExchange.ts:1579" }, "fetchMatchedPrices": { "summary": "fetchMatchedPrices", @@ -845,7 +845,7 @@ "type": "MatchedPricePair[]", "description": "Array of matched market pairs with prices from each venue" }, - "source": "BaseExchange.ts:1586" + "source": "BaseExchange.ts:1587" }, "fetchHedges": { "summary": "fetchHedges", @@ -862,7 +862,7 @@ "type": "PriceComparison[]", "description": "Array of subset/superset matches with live prices" }, - "source": "BaseExchange.ts:1597" + "source": "BaseExchange.ts:1598" }, "fetchArbitrage": { "summary": "fetchArbitrage", @@ -879,7 +879,7 @@ "type": "ArbitrageOpportunity[]", "description": "Array of arbitrage opportunities sorted by spread" }, - "source": "BaseExchange.ts:1607" + "source": "BaseExchange.ts:1608" }, "watchPrices": { "summary": "Watch AMM price updates for a market address (Limitless only).", diff --git a/core/src/server/openapi.yaml b/core/src/server/openapi.yaml index c91cfce5..6c1789f8 100644 --- a/core/src/server/openapi.yaml +++ b/core/src/server/openapi.yaml @@ -72,7 +72,26 @@ paths: summary: Fetch Markets operationId: fetchMarkets parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + - metaculus + - smarkets + - polymarket_us + - suibets + - router + required: true + description: The prediction market exchange to target. - in: query name: limit required: false @@ -258,7 +277,26 @@ paths: summary: Fetch Events operationId: fetchEvents parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + - metaculus + - smarkets + - polymarket_us + - suibets + - router + required: true + description: The prediction market exchange to target. - in: query name: query required: false @@ -383,7 +421,19 @@ paths: summary: Fetch Series operationId: fetchSeries parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - opinion + - polymarket_us + - router + required: true + description: The prediction market exchange to target. responses: '200': description: Fetch Series response @@ -637,7 +687,21 @@ paths: summary: Fetch OHLCV operationId: fetchOHLCV parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + required: true + description: The prediction market exchange to target. - in: query name: outcomeId required: true @@ -689,7 +753,25 @@ paths: summary: Fetch Order Book operationId: fetchOrderBook parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + - smarkets + - polymarket_us + - suibets + - router + required: true + description: The prediction market exchange to target. - in: query name: outcomeId required: true @@ -757,7 +839,16 @@ paths: summary: Fetch Order Books operationId: fetchOrderBooks parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + required: true + description: The prediction market exchange to target. requestBody: content: application/json: @@ -799,7 +890,21 @@ paths: summary: Fetch Trades operationId: fetchTrades parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - smarkets + required: true + description: The prediction market exchange to target. - in: query name: outcomeId required: true @@ -845,7 +950,24 @@ paths: summary: Create Order operationId: createOrder parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + - metaculus + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. requestBody: content: application/json: @@ -881,7 +1003,19 @@ paths: summary: Build Order operationId: buildOrder parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - opinion + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. requestBody: content: application/json: @@ -919,7 +1053,19 @@ paths: summary: Submit Order operationId: submitOrder parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - opinion + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. requestBody: content: application/json: @@ -955,7 +1101,22 @@ paths: summary: Cancel Order operationId: cancelOrder parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - opinion + - metaculus + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. requestBody: content: application/json: @@ -991,7 +1152,21 @@ paths: summary: Fetch Order operationId: fetchOrder parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - probable + - baozi + - opinion + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. - in: query name: orderId required: true @@ -1015,7 +1190,23 @@ paths: summary: Fetch Open Orders operationId: fetchOpenOrders parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. - in: query name: marketId required: false @@ -1041,7 +1232,22 @@ paths: summary: Fetch My Trades operationId: fetchMyTrades parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - myriad + - opinion + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. - in: query name: outcomeId required: false @@ -1099,7 +1305,18 @@ paths: summary: Fetch Closed Orders operationId: fetchClosedOrders parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - kalshi + - kalshi-demo + - limitless + - opinion + - smarkets + required: true + description: The prediction market exchange to target. - in: query name: marketId required: false @@ -1151,7 +1368,18 @@ paths: summary: Fetch All Orders operationId: fetchAllOrders parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - kalshi + - kalshi-demo + - limitless + - opinion + - smarkets + required: true + description: The prediction market exchange to target. - in: query name: marketId required: false @@ -1203,7 +1431,24 @@ paths: summary: Fetch Positions operationId: fetchPositions parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - opinion + - smarkets + - polymarket_us + - suibets + required: true + description: The prediction market exchange to target. - in: query name: address required: false @@ -1229,7 +1474,22 @@ paths: summary: Fetch Balance operationId: fetchBalance parameters: - - $ref: '#/components/parameters/ExchangeParam' + - in: path + name: exchange + schema: + type: string + enum: + - polymarket + - kalshi + - kalshi-demo + - limitless + - probable + - baozi + - myriad + - smarkets + - polymarket_us + required: true + description: The prediction market exchange to target. - in: query name: address required: false diff --git a/docs/api-reference/fetch-order-book.mdx b/docs/api-reference/fetch-order-book.mdx index 55b0cb4d..1aea6e43 100644 --- a/docs/api-reference/fetch-order-book.mdx +++ b/docs/api-reference/fetch-order-book.mdx @@ -7,11 +7,7 @@ openapi: GET /api/{exchange}/fetchOrderBook ### Live order book -Fetch the current L2 order book for an outcome from the exchange's live order book endpoint. For Polymarket this is a live CLOB call: pass the outcome token ID directly and omit historical params. - - -`poly.fetch_order_book(token_id)` without `params.since` or `params.until` is live-only. It does not read PMXT Archive data and may fail for closed, resolved, or otherwise inactive Polymarket markets with an error such as `No orderbook exists`. - +Fetch the current L2 order book for an outcome. If you already have an outcome token ID, pass it directly: ```python Python @@ -32,15 +28,15 @@ console.log(`${book.bids.length} bids, ${book.asks.length} asks`); ```bash curl curl "https://api.pmxt.dev/api/polymarket/fetchOrderBook?outcomeId=104932610032177696635191871147557737718087870958469629338467406422339967452218" \ - -H "Authorization: Bearer ***" + -H "Authorization: Bearer $PMXT_API_KEY" ``` ### Historical snapshot -Get the order book at a specific point in time by passing `since` as a Unix timestamp in milliseconds. Historical Polymarket queries are served from the PMXT Archive and return the nearest reconstructed snapshot at or before that time. +Get the order book at a specific point in time. Pass `since` as a Unix timestamp in milliseconds — returns the nearest snapshot at or before that time. -For binary markets, you can pass the Polymarket condition ID as the first argument and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID. +For binary markets, you can pass the market ID and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID: ```python Python @@ -48,9 +44,12 @@ import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -# Historical lookup against PMXT Archive, not the live CLOB. +market = poly.fetch_market( + slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" +) + book = poly.fetch_order_book( - "0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", + market.market_id, params={"since": 1779487200000, "outcome": "yes"}, ) @@ -64,9 +63,12 @@ import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -// Historical lookup against PMXT Archive, not the live CLOB. +const market = await poly.fetchMarket({ + slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", +}); + const book = await poly.fetchOrderBook( - "0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", + market.marketId, undefined, { since: 1779487200000, outcome: "yes" } ); @@ -77,51 +79,9 @@ console.log(` best ask: ${Math.min(...book.asks.map((a) => a.price)).toFixed(3) ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer ***" \ - -H "Content-Type: application/json" \ - -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779487200000, "outcome": "yes"}]}' -``` - - -### Historical crypto 5m events - -Polymarket crypto 5-minute slugs such as `btc-updown-5m-1779481500` are event slugs. Use `fetch_event(slug=...)`, then select the nested market you want. Do not use `fetch_market(slug=...)` for these event-level slugs. - - -```python Python -import pmxt - -poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -event = poly.fetch_event(slug="btc-updown-5m-1779481500") -market = event.markets[0] - -book = poly.fetch_order_book( - market.market_id, - params={"since": 1779487200000, "outcome": "yes"}, -) -print(f"{market.title}: {book.dt}") -``` - -```javascript JavaScript -import { Polymarket } from "pmxtjs"; - -const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); -const market = event.markets[0]; - -const book = await poly.fetchOrderBook( - market.marketId, - undefined, - { since: 1779487200000, outcome: "yes" } -); -console.log(`${market.title}: ${book.datetime}`); -``` - -```bash curl -curl -X POST "https://api.pmxt.dev/api/polymarket/fetchEvent" \ - -H "Authorization: Bearer ***" \ + -H "Authorization: Bearer $PMXT_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"kwargs":{"slug":"btc-updown-5m-1779481500"}}' + -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779487200000, "outcome": "yes"}]}' ``` @@ -129,15 +89,17 @@ curl -X POST "https://api.pmxt.dev/api/polymarket/fetchEvent" \ Pass both `since` and `until` to get an array of fully reconstructed L2 order book snapshots. Each snapshot is a complete book at that moment in time — not deltas. -The API returns up to `limit` snapshots from the PMXT Archive. Defaults to 100 snapshots per request, max 1000. For raw bulk downloads, use the Parquet files in the [PMXT Archive](https://archive.pmxt.dev) instead of trying to stream bulk data through the live order book endpoint. +Default 100 snapshots per request, max 1000. ```python Python import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -event = poly.fetch_event(slug="btc-updown-5m-1779481500") -market = event.markets[0] + +market = poly.fetch_market( + slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" +) books = poly.fetch_order_book( market.market_id, @@ -145,7 +107,6 @@ books = poly.fetch_order_book( "since": 1779480000000, "until": 1779487200000, "outcome": "yes", - "limit": 100, } ) print(f"{len(books)} snapshots") @@ -157,13 +118,15 @@ for ob in books[:3]: import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); -const market = event.markets[0]; + +const market = await poly.fetchMarket({ + slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", +}); const books = await poly.fetchOrderBook( market.marketId, undefined, - { since: 1779480000000, until: 1779487200000, outcome: "yes", limit: 100 } + { since: 1779480000000, until: 1779487200000, outcome: "yes" } ); console.log(`${books.length} snapshots`); books.slice(0, 3).forEach((ob) => @@ -173,12 +136,12 @@ books.slice(0, 3).forEach((ob) => ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer ***" \ + -H "Authorization: Bearer $PMXT_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes", "limit": 100}]}' + -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes"}]}' ``` -Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Historical `fetchOrderBook` supports Polymarket, Kalshi, Limitless, and Opinion. +Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Supports Polymarket, Kalshi, Limitless, and Opinion. diff --git a/docs/llms-full.txt b/docs/llms-full.txt index bbf82c1f..55c492dc 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -3274,12 +3274,7 @@ Source: https://pmxt.dev/docs/api-reference/fetch-order-book ##### Live order book -Fetch the current L2 order book for an outcome from the exchange's live order book endpoint. For Polymarket this is a live CLOB call: pass the outcome token ID directly and omit historical params. - - -> **Warning:** -`poly.fetch_order_book(token_id)` without `params.since` or `params.until` is live-only. It does not read PMXT Archive data and may fail for closed, resolved, or otherwise inactive Polymarket markets with an error such as `No orderbook exists`. - +Fetch the current L2 order book for an outcome. If you already have an outcome token ID, pass it directly: ```python Python @@ -3300,15 +3295,15 @@ console.log(`${book.bids.length} bids, ${book.asks.length} asks`); ```bash curl curl "https://api.pmxt.dev/api/polymarket/fetchOrderBook?outcomeId=104932610032177696635191871147557737718087870958469629338467406422339967452218" \ - -H "Authorization: Bearer ***" + -H "Authorization: Bearer $PMXT_API_KEY" ``` ##### Historical snapshot -Get the order book at a specific point in time by passing `since` as a Unix timestamp in milliseconds. Historical Polymarket queries are served from the PMXT Archive and return the nearest reconstructed snapshot at or before that time. +Get the order book at a specific point in time. Pass `since` as a Unix timestamp in milliseconds — returns the nearest snapshot at or before that time. -For binary markets, you can pass the Polymarket condition ID as the first argument and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID. +For binary markets, you can pass the market ID and choose the side with `params.outcome`. Use `"yes"` or `"no"` instead of copying the long outcome token ID: ```python Python @@ -3316,9 +3311,12 @@ import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -# Historical lookup against PMXT Archive, not the live CLOB. +market = poly.fetch_market( +slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" +) + book = poly.fetch_order_book( -"0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", +market.market_id, params={"since": 1779487200000, "outcome": "yes"}, ) @@ -3332,9 +3330,12 @@ import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -// Historical lookup against PMXT Archive, not the live CLOB. +const market = await poly.fetchMarket({ + slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", +}); + const book = await poly.fetchOrderBook( - "0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", + market.marketId, undefined, { since: 1779487200000, outcome: "yes" } ); @@ -3345,51 +3346,9 @@ console.log(` best ask: ${Math.min(...book.asks.map((a) => a.price)).toFixed(3) ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer ***" \ - -H "Content-Type: application/json" \ - -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779487200000, "outcome": "yes"}]}' -``` - - -##### Historical crypto 5m events - -Polymarket crypto 5-minute slugs such as `btc-updown-5m-1779481500` are event slugs. Use `fetch_event(slug=...)`, then select the nested market you want. Do not use `fetch_market(slug=...)` for these event-level slugs. - - -```python Python -import pmxt - -poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -event = poly.fetch_event(slug="btc-updown-5m-1779481500") -market = event.markets[0] - -book = poly.fetch_order_book( -market.market_id, -params={"since": 1779487200000, "outcome": "yes"}, -) -print(f"{market.title}: {book.dt}") -``` - -```javascript JavaScript -import { Polymarket } from "pmxtjs"; - -const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); -const market = event.markets[0]; - -const book = await poly.fetchOrderBook( - market.marketId, - undefined, - { since: 1779487200000, outcome: "yes" } -); -console.log(`${market.title}: ${book.datetime}`); -``` - -```bash curl -curl -X POST "https://api.pmxt.dev/api/polymarket/fetchEvent" \ - -H "Authorization: Bearer ***" \ + -H "Authorization: Bearer $PMXT_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"kwargs":{"slug":"btc-updown-5m-1779481500"}}' + -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779487200000, "outcome": "yes"}]}' ``` @@ -3397,15 +3356,17 @@ curl -X POST "https://api.pmxt.dev/api/polymarket/fetchEvent" \ Pass both `since` and `until` to get an array of fully reconstructed L2 order book snapshots. Each snapshot is a complete book at that moment in time — not deltas. -The API returns up to `limit` snapshots from the PMXT Archive. Defaults to 100 snapshots per request, max 1000. For raw bulk downloads, use the Parquet files in the [PMXT Archive](https://archive.pmxt.dev) instead of trying to stream bulk data through the live order book endpoint. +Default 100 snapshots per request, max 1000. ```python Python import pmxt poly = pmxt.Polymarket(pmxt_api_key="pmxt_...") -event = poly.fetch_event(slug="btc-updown-5m-1779481500") -market = event.markets[0] + +market = poly.fetch_market( +slug="will-spacex-starship-flight-test-12-launch-by-may-22-354-721" +) books = poly.fetch_order_book( market.market_id, @@ -3413,7 +3374,6 @@ params={ "since": 1779480000000, "until": 1779487200000, "outcome": "yes", - "limit": 100, } ) print(f"{len(books)} snapshots") @@ -3425,13 +3385,15 @@ print(f" {ob.dt} bid={ob.bids[0].price} ask={ob.asks[0].price}") import { Polymarket } from "pmxtjs"; const poly = new Polymarket({ pmxtApiKey: "pmxt_..." }); -const event = await poly.fetchEvent({ slug: "btc-updown-5m-1779481500" }); -const market = event.markets[0]; + +const market = await poly.fetchMarket({ + slug: "will-spacex-starship-flight-test-12-launch-by-may-22-354-721", +}); const books = await poly.fetchOrderBook( market.marketId, undefined, - { since: 1779480000000, until: 1779487200000, outcome: "yes", limit: 100 } + { since: 1779480000000, until: 1779487200000, outcome: "yes" } ); console.log(`${books.length} snapshots`); books.slice(0, 3).forEach((ob) => @@ -3441,15 +3403,15 @@ books.slice(0, 3).forEach((ob) => ```bash curl curl -X POST "https://api.pmxt.dev/api/polymarket/fetchOrderBook" \ - -H "Authorization: Bearer ***" \ + -H "Authorization: Bearer $PMXT_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"args":["0xc704f74e2f9dfae70f770cb253ffadde10768eeab41233098bf5ac67995a94b5", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes", "limit": 100}]}' + -d '{"args":["61b0ed20-7f42-41fd-af15-7b86153f6bb7", null, {"since": 1779480000000, "until": 1779487200000, "outcome": "yes"}]}' ``` > **Note:** -Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Historical `fetchOrderBook` supports Polymarket, Kalshi, Limitless, and Opinion. +Historical order book data is backed by the [PMXT Archive](https://archive.pmxt.dev) — the same tick-level data available as Parquet files, but queryable directly from the API without downloading or parsing files. Supports Polymarket, Kalshi, Limitless, and Opinion. ### Fetch Order Books diff --git a/sdks/python/API_REFERENCE.md b/sdks/python/API_REFERENCE.md index dac681ce..b20f3aa2 100644 --- a/sdks/python/API_REFERENCE.md +++ b/sdks/python/API_REFERENCE.md @@ -1456,7 +1456,7 @@ title: str # The market title (e.g., "Will BTC close above $100k on Dec 31?"). description: str # Long-form market description or resolution criteria. slug: str # URL-friendly slug for the market. outcomes: List[MarketOutcome] # The possible outcomes for this market. -resolution_date: str # When the market is scheduled to resolve. +resolution_date: str # When the market is scheduled to resolve. Optional because some venues do not publish a cutoff for every market (e.g. Opinion categorical children) — emit `undefined` rather than coercing to epoch. volume24h: float # Trading volume over the past 24 hours (USD). volume: float # Total / Lifetime volume liquidity: float # Current market liquidity (USD). diff --git a/sdks/python/pmxt/client.py b/sdks/python/pmxt/client.py index 2a29507f..3b89b83c 100644 --- a/sdks/python/pmxt/client.py +++ b/sdks/python/pmxt/client.py @@ -773,7 +773,7 @@ def fetch_markets(self, params: Optional[dict] = None, **kwargs) -> List[Unified params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -796,7 +796,7 @@ def fetch_markets_paginated(self, params: Optional[dict] = None, **kwargs) -> Pa params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -823,7 +823,7 @@ def fetch_events(self, params: Optional[dict] = None, **kwargs) -> List[UnifiedE params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -846,7 +846,7 @@ def fetch_series(self, params: Optional[dict] = None, **kwargs) -> List[UnifiedS params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -869,7 +869,7 @@ def fetch_market(self, params: Optional[dict] = None, **kwargs) -> UnifiedMarket params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -892,7 +892,7 @@ def fetch_event(self, params: Optional[dict] = None, **kwargs) -> UnifiedEvent: params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -921,7 +921,7 @@ def fetch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, lim if limit is None: args.append(None) args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -943,7 +943,7 @@ def fetch_order_books(self, outcome_ids: List[Union[str, "MarketOutcome"]]) -> D try: args = [] args.append([_resolve_outcome_id(x) for x in outcome_ids]) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -963,7 +963,7 @@ def cancel_order(self, order_id: str) -> Order: try: args = [] args.append(order_id) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -983,7 +983,7 @@ def fetch_order(self, order_id: str) -> Order: try: args = [] args.append(order_id) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1004,7 +1004,7 @@ def fetch_open_orders(self, market_id: Optional[str] = None) -> List[Order]: args = [] if market_id is not None: args.append(market_id) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1027,7 +1027,7 @@ def fetch_my_trades(self, params: Optional[dict] = None, **kwargs) -> List[UserT params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1050,7 +1050,7 @@ def fetch_closed_orders(self, params: Optional[dict] = None, **kwargs) -> List[O params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1073,7 +1073,7 @@ def fetch_all_orders(self, params: Optional[dict] = None, **kwargs) -> List[Orde params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1094,7 +1094,7 @@ def fetch_positions(self, address: Optional[str] = None) -> List[Position]: args = [] if address is not None: args.append(address) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1115,7 +1115,7 @@ def fetch_balance(self, address: Optional[str] = None) -> List[Balance]: args = [] if address is not None: args.append(address) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1136,7 +1136,7 @@ def unwatch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, * args = [] outcome_id = _compat_id(outcome_id, _compat_kwargs) args.append(_resolve_outcome_id(outcome_id)) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1155,7 +1155,7 @@ def unwatch_address(self, address: str) -> None: try: args = [] args.append(address) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1173,7 +1173,7 @@ def unwatch_address(self, address: str) -> None: def close(self) -> None: try: args = [] - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1195,7 +1195,7 @@ def fetch_market_matches(self, params: Optional[dict] = None, **kwargs) -> List[ params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1211,13 +1211,13 @@ def fetch_market_matches(self, params: Optional[dict] = None, **kwargs) -> List[ except ApiException as e: raise self._parse_api_exception(e) from None - def fetch_matches(self, params: Dict[str, Any], **kwargs) -> List[Any]: + def fetch_matches(self, params: dict, **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1240,7 +1240,7 @@ def fetch_event_matches(self, params: Optional[dict] = None, **kwargs) -> List[A params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1256,13 +1256,13 @@ def fetch_event_matches(self, params: Optional[dict] = None, **kwargs) -> List[A except ApiException as e: raise self._parse_api_exception(e) from None - def compare_market_prices(self, params: Dict[str, Any], **kwargs) -> List[Any]: + def compare_market_prices(self, params: dict, **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1278,13 +1278,13 @@ def compare_market_prices(self, params: Dict[str, Any], **kwargs) -> List[Any]: except ApiException as e: raise self._parse_api_exception(e) from None - def fetch_related_markets(self, params: Dict[str, Any], **kwargs) -> List[Any]: + def fetch_related_markets(self, params: dict, **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1307,7 +1307,7 @@ def fetch_matched_markets(self, params: Optional[dict] = None, **kwargs) -> List params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1330,7 +1330,7 @@ def fetch_matched_prices(self, params: Optional[dict] = None, **kwargs) -> List[ params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1346,13 +1346,13 @@ def fetch_matched_prices(self, params: Optional[dict] = None, **kwargs) -> List[ except ApiException as e: raise self._parse_api_exception(e) from None - def fetch_hedges(self, params: Dict[str, Any], **kwargs) -> List[Any]: + def fetch_hedges(self, params: dict, **kwargs) -> List[Any]: try: args = [] if kwargs: params = {**(params or {}), **kwargs} args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds @@ -1375,7 +1375,7 @@ def fetch_arbitrage(self, params: Optional[dict] = None, **kwargs) -> List[Any]: params = {**(params or {}), **kwargs} if params is not None: args.append(params) - body: Dict[str, Any] = {"args": args} + body: dict = {"args": args} creds = self._get_credentials_dict() if creds: body["credentials"] = creds diff --git a/sdks/typescript/API_REFERENCE.md b/sdks/typescript/API_REFERENCE.md index f8504e0a..ec2f3280 100644 --- a/sdks/typescript/API_REFERENCE.md +++ b/sdks/typescript/API_REFERENCE.md @@ -1456,7 +1456,7 @@ title: string; // The market title (e.g., "Will BTC close above $100k on Dec 31? description: string; // Long-form market description or resolution criteria. slug: string; // URL-friendly slug for the market. outcomes: MarketOutcome[]; // The possible outcomes for this market. -resolutionDate: string; // When the market is scheduled to resolve. +resolutionDate: string; // When the market is scheduled to resolve. Optional because some venues do not publish a cutoff for every market (e.g. Opinion categorical children) — emit `undefined` rather than coercing to epoch. volume24h: number; // Trading volume over the past 24 hours (USD). volume: number; // Total / Lifetime volume liquidity: number; // Current market liquidity (USD). From 284615baf94a626d1df261dee0295490df8a215b Mon Sep 17 00:00:00 2001 From: Samuel Tinnerholm Date: Fri, 5 Jun 2026 14:23:49 +0000 Subject: [PATCH 5/5] ci: retrigger checks after generator sync