Market data
Market data lives behind two services:
STXMarketService: individual markets and market countsSTXEventService: events (a match/game), with its markets attached
List markets
Section titled “List markets”var markets = serviceProvider.GetRequiredService<STXMarketService>();
var resp = await markets.GetMarketInfosWithCountAsync();
foreach (var m in resp.MarketInfos){ Console.WriteLine($"{m.MarketId} {m.Status} {m.Title}");}GetMarketInfosWithCountAsync returns STXMarketInfosWithCountResponse<STXMarketInfo>: the full market object, plus Count and Cursor for paging. For lightweight lookups by ID, use the Short variant:
var ids = new[] { "mkt_abc", "mkt_def" };var short_ = await markets.GetShortMarketInfosWithCountAsync(ids);Pagination & counts
Section titled “Pagination & counts”GetMarketInfosWithCountAsync returns one page plus Count (the total matching the filter before pagination) and Cursor, an opaque pointer to the next page:
var page = await markets.GetMarketInfosWithCountAsync(new STXMarketInfosFilter{ Status = [STXMarketInfosStatus.OPEN], Trading = STXMarketInfosTrading.TRUE, Pagination = new STXKeysetPagination { Limit = 100 },});
Console.WriteLine($"{page.MarketInfos.Count}/{page.Count}");Pass Cursor back to fetch the next page. The walk ends when the server stops returning a cursor, not when a page comes back short. A last page that exactly fills Limit still carries a cursor, and the request after it returns no markets and no cursor. Treat an empty cursor as the end too: sent back, it reads to the server as “no cursor” and restarts you at page one.
string cursor = null;
do{ var page = await markets.GetMarketInfosWithCountAsync(new STXMarketInfosFilter { Pagination = new STXKeysetPagination { Cursor = cursor, Limit = 100 }, });
foreach (var m in page.MarketInfos) { /* … */ }
cursor = page.Cursor;}while (!string.IsNullOrEmpty(cursor));Fetch every market
Section titled “Fetch every market”The paging helpers run that loop for you. GetAllOpenMarketInfosAsync fetches every market currently open:
var open = await markets.GetAllOpenMarketInfosAsync();
Console.WriteLine($"{open.Count} open markets");Status is overridden and, as in every paged call, Limit and Pagination are ignored. The rest of the filter is honoured, so the walk can be narrowed:
var openSoccer = await markets.GetAllOpenMarketInfosAsync(new STXMarketInfosFilter{ Sports = ["Soccer"],});Use GetAllMarketInfosAsync to walk any filter without forcing a status, and GetMarketInfoPagesAsync to stream page by page instead of buffering the whole result set. This is worth it for broad filters, which can run to tens of thousands of markets:
await foreach (var page in markets.GetMarketInfoPagesAsync<STXMarketInfo>(filter, pageSize: 500)){ foreach (var m in page) { /* … */ }}Cost, and how to cut it
Section titled “Cost, and how to cut it”A walk covers every matching market, so the projection you ask for decides what it costs. Asking for the complete STXMarketInfo across a large market set moves a great deal more data and takes correspondingly longer than asking for a handful of fields (on a mature environment the difference is about an order of magnitude in both), and it holds every fully-populated market object in memory at once.
The generic overload builds its GraphQL selection from T, so a type carrying only the fields you actually use is the largest saving available here:
public class MarketRow{ public Guid MarketId { get; set; } public string Symbol { get; set; } public string GroupingId { get; set; } public string Title { get; set; }}
var rows = await markets.GetAllMarketInfosAsync<MarketRow>();Before reaching for the full set, check whether you need it: the bulk of a mature environment is resulted history. If what you want is the live board, GetAllOpenMarketInfosAsync() returns a far smaller set for a fraction of the cost.
Filter
Section titled “Filter”STXMarketInfosFilter combines the common filter fields:
| Field | Type | |
|---|---|---|
Status |
IEnumerable<STXMarketInfosStatus> |
One or more statuses, e.g. [STXMarketInfosStatus.OPEN] |
Trading |
STXMarketInfosTrading? |
TRUE / FALSE |
Sports |
IEnumerable<string> |
Sport filter (["Basketball"], ["Baseball"], …) |
Competitions |
IEnumerable<string> |
Competition filter (["NBA"], ["MLB"], …) |
EventIds |
IEnumerable<string> |
Only markets for the given events |
MarketIds |
IEnumerable<string> |
Only the given markets |
Pagination |
STXKeysetPagination |
Cursor and page size (see above) |
Limit |
int? |
Caps a single response; not a substitute for paging |
KeywordRegex |
string |
Regex match on market keywords |
Featured |
STXFeatured? |
Featured markets |
SortBy |
STXMarketInfosSortBy |
Field and direction |
Stat |
STXPslStats? |
Player-stat markets |
Sports & competitions
Section titled “Sports & competitions”var catalog = await markets.GetSportAndCompetitionsAsync();
foreach (var sport in catalog){ Console.WriteLine($"{sport.Sport}"); foreach (var c in sport.Competitions) Console.WriteLine($" {c}");}Events
Section titled “Events”STXEventService bundles an event with its markets: one call instead of one-markets-per-event:
var events = serviceProvider.GetRequiredService<STXEventService>();
var resp = await events.GetEventInfosAsync(new STXEventInfosFilter{ Sport = "basketball", EventStatusFilter = new[] { STXEventStatus.scheduled, STXEventStatus.live, },});
foreach (var ev in resp.EventInfos){ Console.WriteLine($"{ev.EventId} {ev.Title} ({ev.MarketInfos.Count} markets)");}Real-time updates
Section titled “Real-time updates”For live price ticks on open markets, subscribe via the STXMarketChannel websocket wrapper (see WebSockets → Market updates). REST polling is fine for snapshots; channels are required for latency-sensitive use cases.
See also
Section titled “See also”- Reference → Market data: full method signatures
STX.Sdk.Enums: all filter values, listed by your IDE’s completion

