Skip to main content
The SDK exposes every query and mutation the GraphQL schema offers. Markets are the most common surface — here’s how to shape calls efficiently.
Every response is a typed Pydantic v2 model — you get attribute access, IDE autocomplete, and validation for free. Call .model_dump() on any model if you need a plain dict.

List markets

from stx import STX, Selection

client = STX(region="ontario", env="staging")

markets = client.marketInfos(
    selections=Selection("marketId", "status", "title"),
)
for market in markets:
    print(market.marketId, market.status)
markets is a list[MarketInfo]. Fields that weren’t selected are None.

Filter and paginate

marketInfos accepts filter params:
resp = client.marketInfos(
    params={"status": "open", "limit": 50, "offset": 0},
    selections=Selection("marketId", "title", "closeTime"),
)
Check the schema — client.get_operations() lists every operation with its arg shape:
for name, sig in client.get_operations().items():
    print(name, sig)

Get a single market

market = client.marketInfo(
    params={"marketId": "mkt_8f3..."},
    selections=Selection(
        "marketId", "title", "status",
        orderbook=Selection("bids", "asks"),
    ),
)
print(market.title, market.status)

Orderbooks

Pull an orderbook via the nested orderbook field on marketInfo:
market = client.marketInfo(
    params={"marketId": "mkt_8f3..."},
    selections=Selection(
        "marketId",
        orderbook=Selection("bids", "asks"),
    ),
)
book = market.orderbook
print("bids:", book.bids)   # [[price, size], ...]
print("asks:", book.asks)
For live updates, subscribe to the market channel — see WebSockets.

Shaping the response

GraphQL’s killer feature over REST: you ask only for the fields you’ll use. The SDK exposes this via Selection(...).
from stx import Selection

client.marketInfos(selections=Selection("marketId", "status"))
# ~1 KB per 100 markets
For list endpoints that return 100+ items, the narrow form is 10-30× smaller on the wire. The examples/list_markets.py demo shows 1.1 MB vs 27.3 MB for the same 500-market query.

Presets

Canned selections for common use cases — import from stx.presets:
from stx import STX
from stx.presets import PRESETS

client = STX(region="ontario", env="staging")

client.marketInfos(selections=PRESETS.MARKET_MINIMAL)     # marketId + status
client.marketInfos(selections=PRESETS.MARKET_BASIC)       # + title, closeTime, startTime
client.marketInfos(selections=PRESETS.MARKET_TRADING)     # + orderbook, lastTrade, volume
Presets are regular Selection objects — combine with your own fields:
from stx import Selection
from stx.presets import PRESETS

client.marketInfos(
    selections=PRESETS.MARKET_BASIC + Selection(tags=Selection("name")),
)

Paginating large result sets

def iter_all_markets(client, page_size=100):
    offset = 0
    while True:
        batch = client.marketInfos(
            params={"limit": page_size, "offset": offset},
            selections=Selection("marketId", "title", "status"),
        )
        if not batch:
            return
        yield from batch
        offset += page_size
        if len(batch) < page_size:
            return

client = STX(region="ontario", env="staging")
for market in iter_all_markets(client):
    ...
For very large bulk pulls, use AsyncSTX with asyncio.gather to parallelize pages — see Async.

Error handling

Market queries are mostly idempotent — the SDK’s default retry policy handles transient STXTransportException and STXRateLimitException automatically. See Errors & retries.

Next

Trading

Place orders, fetch positions, and manage fills.

WebSockets

Subscribe to live market updates over Phoenix channels.