Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 75 additions & 65 deletions core/api-doc-config.generated.json

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions sdks/python/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,31 @@ exchange.fetch_events(query="Trump", limit=10, offset=0)
**Notes:**
Some exchanges (like Limitless) may only support status 'active' for search results.

---
### `fetch_series`

Fetch the recurring series (fourth tier above Event -> Market -> Outcome)


**Signature:**

```python
def fetch_series(params: Optional[SeriesFetchParams] = None) -> List[UnifiedSeries]:
```

**Parameters:**

- `params` (SeriesFetchParams) - **Optional**: params

**Returns:** List[[UnifiedSeries](#unifiedseries)] - Array of unified series. Always an array, including the singular-lookup case.

**Example:**

```python
exchange.fetch_series()
```


---
### `fetch_market`

Expand Down Expand Up @@ -1443,6 +1468,7 @@ tags: List[string] # Optional list of tags. More granular than category — e.g.
tick_size: float # Minimum price increment (e.g., 0.01, 0.001)
status: str # Venue-native lifecycle status (e.g. 'active', 'closed', 'archived').
contract_address: str # On-chain contract / condition identifier where applicable (Polymarket conditionId, etc.).
source_metadata: object # Raw venue-specific metadata not captured by first-class fields (e.g. Kalshi series_ticker / series_title from the parent event, Polymarket series). Passed through verbatim so downstream consumers can recover anything the unified shape omits. Each venue populates what it has.
source_exchange: str # The exchange/venue this market originates from (e.g. 'polymarket', 'kalshi'). Populated by the Router.
yes: Any # Convenience accessor for the YES outcome on a binary market.
no: Any # Convenience accessor for the NO outcome on a binary market.
Expand Down Expand Up @@ -1485,9 +1511,31 @@ url: str # Canonical URL to view the event on the venue.
image: str # Optional image URL for the event.
category: str # Optional category label. Venue-defined — common values include "Sports", "Politics", "Crypto", "Economics", "Science", "Culture". Polymarket uses finer-grained categories like "Bitcoin", "Soccer", "Economic Policy"; Kalshi uses broader ones like "Sports" or "Mentions".
tags: List[string] # Optional list of tags. More granular than category — e.g. ["Sports", "FIFA World Cup", "2026 FIFA World Cup"] or ["Politics", "Geopolitics", "Middle East"]. Tags vary by venue: Polymarket markets carry several, Kalshi typically one.
source_metadata: object # Raw venue-specific metadata not captured by first-class fields (e.g. Kalshi series_ticker / series_title, Polymarket series). Passed through verbatim so downstream consumers can recover anything the unified shape omits. Each venue populates what it has.
source_exchange: str # The exchange/venue this event originates from (e.g. 'polymarket', 'kalshi'). Populated by the Router.
```

---
### `UnifiedSeries`

A recurring grouping of events on a venue — the fourth tier above Event -> Market -> Outcome. Examples: Kalshi `KXATPMATCH` (every ATP tennis match), Polymarket `wta` (every WTA match), Opinion's daily `collection`. Series only exists where the venue exposes a recurring-event concept; venues without one return an empty array from `fetchSeries`.

```python
@dataclass
class UnifiedSeries:
id: str # Stable venue-native series identifier (e.g. "KXATPMATCH" on Kalshi, "atp" on Polymarket Gamma, numeric Gamma id).
ticker: str # Venue-native ticker, when distinct from `id`.
slug: str # Venue-native slug.
title: str # Human-readable series title (e.g. "ATP Match Winner", "WTA").
description: Any # Long-form series description.
recurrence: Any # Recurrence cadence the venue reports ('daily', 'weekly', 'annual', ...).
events: List[UnifiedEvent] # Child events. Populated when fetched by id; the list form usually omits this to keep payloads small.
url: Any # Canonical venue URL for the series.
image: Any # Venue-hosted image.
source_exchange: str # The exchange this series originates from. Populated by the Router.
source_metadata: object # Raw venue-specific fields not promoted to first-class columns.
```

---
### `PriceCandle`

Expand Down Expand Up @@ -1934,6 +1982,7 @@ status: str # Filter by event status (default: 'active', 'inactive' and 'closed'
search_in: str # Where to search (default: 'title')
event_id: str # Direct lookup by event ID
slug: str # Lookup by event slug
series: str # Filter events by their parent series. Accepts the venue-native series id / ticker / slug (e.g. Kalshi `"KXATPMATCH"`, Polymarket `"wta"`). Passed through to the vendor where supported, otherwise applied to `sourceMetadata` after fetch.
filter: Any # Optional client-side filter applied after fetching
category: str # Filter by category. Each event belongs to a venue-assigned category such as "Sports", "Politics", "Crypto", "Bitcoin", "Soccer", "Economic Policy" (Polymarket) or "Sports", "Mentions" (Kalshi).
tags: List[string] # Filter by tags. Returns events matching ANY of the provided tags. Tags are more specific than categories -- for example a "Politics" event might carry tags ["Politics", "Geopolitics", "Middle East", "Iran"]. Common tags include "Crypto", "Elections", "Fed Rates", "FIFA World Cup", "Trump".
Expand Down
2 changes: 2 additions & 0 deletions sdks/python/pmxt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from .client import Exchange
from ._exchanges import Polymarket, Limitless, Kalshi, KalshiDemo, Probable, Baozi, Myriad, Opinion, Metaculus, Smarkets, PolymarketUS, Polymarket_us, Hyperliquid, GeminiTitan, SuiBets, Suibets, Mock, Router
from .router import Router
from .feed_client import FeedClient
from .server_manager import ServerManager
from .errors import (
PmxtError,
Expand Down Expand Up @@ -168,6 +169,7 @@ def restart_server() -> None:
"Mock",
"Router",
"Exchange",
"FeedClient",
# Server Management
"ServerManager",
"server",
Expand Down
30 changes: 30 additions & 0 deletions sdks/python/tests/test_public_exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,36 @@ def test_legacy_polymarket_us_alias_stays_public():
assert aliases["Polymarket_us"] == "PolymarketUS"


def test_feed_client_is_top_level_public_export():
init_path = Path(__file__).resolve().parents[1] / "pmxt" / "__init__.py"
tree = ast.parse(init_path.read_text(encoding="utf-8"))

imported_modules = {
alias.name: node.module
for node in tree.body
if isinstance(node, ast.ImportFrom)
for alias in node.names
}
public_exports = set()

for node in tree.body:
if (
isinstance(node, ast.Assign)
and len(node.targets) == 1
and isinstance(node.targets[0], ast.Name)
and node.targets[0].id == "__all__"
and isinstance(node.value, ast.List)
):
public_exports.update(
item.value
for item in node.value.elts
if isinstance(item, ast.Constant) and isinstance(item.value, str)
)

assert imported_modules["FeedClient"] == "feed_client"
assert "FeedClient" in public_exports


def test_polymarket_init_auth_is_generated():
exchanges_path = Path(__file__).resolve().parents[1] / "pmxt" / "_exchanges.py"
tree = ast.parse(exchanges_path.read_text(encoding="utf-8"))
Expand Down
49 changes: 49 additions & 0 deletions sdks/typescript/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,31 @@ await exchange.fetchEvents({ query: "Trump", limit: 10, offset: 0 })
**Notes:**
Some exchanges (like Limitless) may only support status 'active' for search results.

---
### `fetchSeries`

Fetch the recurring series (fourth tier above Event -> Market -> Outcome)


**Signature:**

```typescript
async fetchSeries(params?: SeriesFetchParams): Promise<UnifiedSeries[]>
```

**Parameters:**

- `params` (SeriesFetchParams) - **Optional**: params

**Returns:** Promise<[UnifiedSeries](#unifiedseries)[]> - Array of unified series. Always an array, including the singular-lookup case.

**Example:**

```typescript
await exchange.fetchSeries()
```


---
### `fetchMarket`

Expand Down Expand Up @@ -1443,6 +1468,7 @@ tags: string[]; // Optional list of tags. More granular than category — e.g. [
tickSize: number; // Minimum price increment (e.g., 0.01, 0.001)
status: string; // Venue-native lifecycle status (e.g. 'active', 'closed', 'archived').
contractAddress: string; // On-chain contract / condition identifier where applicable (Polymarket conditionId, etc.).
sourceMetadata: object; // Raw venue-specific metadata not captured by first-class fields (e.g. Kalshi series_ticker / series_title from the parent event, Polymarket series). Passed through verbatim so downstream consumers can recover anything the unified shape omits. Each venue populates what it has.
sourceExchange: string; // The exchange/venue this market originates from (e.g. 'polymarket', 'kalshi'). Populated by the Router.
yes: any; // Convenience accessor for the YES outcome on a binary market.
no: any; // Convenience accessor for the NO outcome on a binary market.
Expand Down Expand Up @@ -1485,10 +1511,32 @@ url: string; // Canonical URL to view the event on the venue.
image: string; // Optional image URL for the event.
category: string; // Optional category label. Venue-defined — common values include "Sports", "Politics", "Crypto", "Economics", "Science", "Culture". Polymarket uses finer-grained categories like "Bitcoin", "Soccer", "Economic Policy"; Kalshi uses broader ones like "Sports" or "Mentions".
tags: string[]; // Optional list of tags. More granular than category — e.g. ["Sports", "FIFA World Cup", "2026 FIFA World Cup"] or ["Politics", "Geopolitics", "Middle East"]. Tags vary by venue: Polymarket markets carry several, Kalshi typically one.
sourceMetadata: object; // Raw venue-specific metadata not captured by first-class fields (e.g. Kalshi series_ticker / series_title, Polymarket series). Passed through verbatim so downstream consumers can recover anything the unified shape omits. Each venue populates what it has.
sourceExchange: string; // The exchange/venue this event originates from (e.g. 'polymarket', 'kalshi'). Populated by the Router.
}
```

---
### `UnifiedSeries`

A recurring grouping of events on a venue — the fourth tier above Event -> Market -> Outcome. Examples: Kalshi `KXATPMATCH` (every ATP tennis match), Polymarket `wta` (every WTA match), Opinion's daily `collection`. Series only exists where the venue exposes a recurring-event concept; venues without one return an empty array from `fetchSeries`.

```typescript
interface UnifiedSeries {
id: string; // Stable venue-native series identifier (e.g. "KXATPMATCH" on Kalshi, "atp" on Polymarket Gamma, numeric Gamma id).
ticker: string; // Venue-native ticker, when distinct from `id`.
slug: string; // Venue-native slug.
title: string; // Human-readable series title (e.g. "ATP Match Winner", "WTA").
description: any; // Long-form series description.
recurrence: any; // Recurrence cadence the venue reports ('daily', 'weekly', 'annual', ...).
events: UnifiedEvent[]; // Child events. Populated when fetched by id; the list form usually omits this to keep payloads small.
url: any; // Canonical venue URL for the series.
image: any; // Venue-hosted image.
sourceExchange: string; // The exchange this series originates from. Populated by the Router.
sourceMetadata: object; // Raw venue-specific fields not promoted to first-class columns.
}
```

---
### `PriceCandle`

Expand Down Expand Up @@ -1934,6 +1982,7 @@ status?: string; // Filter by event status (default: 'active', 'inactive' and 'c
searchIn?: string; // Where to search (default: 'title')
eventId?: string; // Direct lookup by event ID
slug?: string; // Lookup by event slug
series?: string; // Filter events by their parent series. Accepts the venue-native series id / ticker / slug (e.g. Kalshi `"KXATPMATCH"`, Polymarket `"wta"`). Passed through to the vendor where supported, otherwise applied to `sourceMetadata` after fetch.
filter?: any; // Optional client-side filter applied after fetching
category?: string; // Filter by category. Each event belongs to a venue-assigned category such as "Sports", "Politics", "Crypto", "Bitcoin", "Soccer", "Economic Policy" (Polymarket) or "Sports", "Mentions" (Kalshi).
tags?: string[]; // Filter by tags. Returns events matching ANY of the provided tags. Tags are more specific than categories -- for example a "Politics" event might carry tags ["Politics", "Geopolitics", "Middle East", "Iran"]. Common tags include "Crypto", "Elections", "Fed Rates", "FIFA World Cup", "Trump".
Expand Down
4 changes: 4 additions & 0 deletions sdks/typescript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
import { Exchange, Polymarket, Kalshi, KalshiDemo, Limitless, Myriad, Probable, Baozi, Opinion, Metaculus, Smarkets, PolymarketUS, GeminiTitan, Hyperliquid, SuiBets, Mock } from "./pmxt/client.js";
import { Router } from "./pmxt/router.js";
import { ServerManager } from "./pmxt/server-manager.js";
import { FeedClient } from "./pmxt/feed-client.js";
import * as models from "./pmxt/models.js";
import * as errors from "./pmxt/errors.js";

export { Exchange, Polymarket, Kalshi, KalshiDemo, Limitless, Myriad, Probable, Baozi, Opinion, Metaculus, Smarkets, PolymarketUS, GeminiTitan, Hyperliquid, SuiBets, Mock, PolymarketOptions } from "./pmxt/client.js";
export { FeedClient } from "./pmxt/feed-client.js";
export type { Ticker, Tickers, OHLCV, Market as FeedMarket, OracleRound, FeedClientOptions } from "./pmxt/feed-client.js";
export { Router } from "./pmxt/router.js";
export { ServerManager } from "./pmxt/server-manager.js";
export { HOSTED_URL, LOCAL_URL, ENV, resolvePmxtBaseUrl } from "./pmxt/constants.js";
Expand Down Expand Up @@ -87,6 +90,7 @@ const pmxt = {
Mock,
Router,
ServerManager,
FeedClient,
server,
stopServer,
restartServer,
Expand Down
19 changes: 19 additions & 0 deletions sdks/typescript/tests/public-exports.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as pmxt from '../index';
import { FeedClient as DirectFeedClient } from '../pmxt/feed-client';

describe('public exports', () => {
it('exports FeedClient as a top-level named export', () => {
expect(pmxt.FeedClient).toBeDefined();
expect(pmxt.FeedClient).toBe(DirectFeedClient);
});

it('exposes FeedClient on the default pmxt object', () => {
expect(pmxt.default.FeedClient).toBeDefined();
expect(pmxt.default.FeedClient).toBe(DirectFeedClient);
});

it('FeedClient is constructable from the top-level export', () => {
const client = new pmxt.FeedClient('chainlink');
expect(client).toBeInstanceOf(DirectFeedClient);
});
});
Loading