Market data
Market data access lets your product read STX markets, prices and order-book depth in real time, with credentials of your own. It is for odds comparison sites, media, research and trading tools. It reads public market data only: it never touches a member’s account, so there is no consent screen and no member data.
Trading on your own account instead? You don’t need data credentials: a signed API key reads the same data and trades too.
What you can read
Section titled “What you can read”| Data | REST | WebSocket |
|---|---|---|
| Market catalogue: every listed market, its status, rules and details | GET /api/v1/markets |
markets, market_updates |
| Prices and depth: best bid and offer, the aggregated book, recent trades | bids, offers and recent_trades on each market |
orderbook, ticker and trades |
| Price history | market_stats |
|
| Events and competitions, the catalogue markets hang off | GET /api/v1/events |
events |
The market_data and events scopes cover all of it. The full list of what each scope opens is under App scopes.
Get data credentials
Section titled “Get data credentials”- Go to apps.stxapp.io/data and choose Get data access.
- Create your account and name your organization. You land on Market data access in STX Apps.
- Confirm your email: open the link STX Apps sends you. Until you do, the page shows Confirm your email to get demo keys. with a Send the link again link instead of the key form.
- Choose Get data access keys. You get an access key ID and a secret key for the US demo exchange. In OAuth terms they are your client ID and client secret.
- Copy the secret key: it is shown once. You can get a new one from STX Apps at any time, and the old one stops working.
No redirect URI or server IP list is needed for data keys.
Owners, admins and data developers manage data access and its keys. See STX Apps.
Data credentials are a Server-to-server OAuth client: they hold app scopes only and use the client_credentials grant, with no member involved.
Get a token
Section titled “Get a token”$STX is the exchange’s base URL. On the US demo exchange that is https://demo.stxapp.io; every host is on Environments.
Send the access key ID and secret key as HTTP Basic (-u). A secret in the form body is refused with invalid_client.
curl -s -u "$STX_CLIENT_ID:$STX_CLIENT_SECRET" "$STX/oauth/token" \ -d grant_type=client_credentials \ -d "scope=market_data events"{ "access_token": "stxapp_at_…", "token_type": "bearer", "expires_in": 3600, "scope": "market_data events" }scope is optional. Leave it out and the request still succeeds with 200: the token carries every app scope your client holds. Captured on US demo with a client that can also create markets:
curl -s -u "$STX_CLIENT_ID:$STX_CLIENT_SECRET" "$STX/oauth/token" \ -d grant_type=client_credentials{ "scope": "market_data events markets.write", "expires_in": 3600, "access_token": "stxapp_at_…", "token_type": "bearer" }Read scope in the response for what the token can do, and name the scopes you need when you want a narrower token. A scope your client does not hold is invalid_scope.
The token lasts an hour and has no refresh token: request a new one when it expires. Keep the secret and the token on your server. See App tokens and Tokens and security.
Read a snapshot over REST
Section titled “Read a snapshot over REST”Send the token as a bearer. This reads open markets that are taking orders:
curl -s -H "Authorization: Bearer $STX_APP_TOKEN" \ "$STX/api/v1/markets?status=open&trading=true&competitions=NBA"{ "cursor": "g2gDbQAAABCiuxfKlv2VBukIZG7zFzCAbgUB0pA2N4ZoA2EAbgcAANzktGFeBmIAAJzc", "markets": [ { "market_id": "1eb49edd-9bf0-4e86-8971-f8a19ff44b7d", "symbol": "STXNBA-26OCT211900ATLORL-PRAORLNALEXANDERWALKER493112-25.5", "title": "N. Alexander-Walker 25.5 PTS + REB + AST", "question": "Will Nickeil Alexander-Walker have more than 25.5 Points + Rebounds + Assists?", "status": "open", "trading": true, "price": "0.4850", "last_traded_price": null, "max_price": "1.0000", "bids": [ { "quantity": "652.00", "price": "0.4600" }, { "quantity": "1111.00", "price": "0.4500" }, { "quantity": "1704.00", "price": "0.4400" }, { "quantity": "2439.00", "price": "0.4100" }, { "quantity": "3076.00", "price": "0.3900" } ], "offers": [ { "quantity": "2926.00", "price": "0.5900" }, { "quantity": "2272.00", "price": "0.5600" }, { "quantity": "1630.00", "price": "0.5400" }, { "quantity": "1063.00", "price": "0.5300" }, { "quantity": "612.00", "price": "0.5100" } ], "recent_trades": [], "open_interest": "0.00", "event_id": "776f2c7f-afc8-43fa-8a90-3cf581294143", "event_title": "Atlanta Hawks at Orlando Magic", "event_start": "2026-10-21T23:00:00.000000Z", "competition": "NBA", "sport": "Basketball" } ]}The response is trimmed to one market and a few fields; List markets documents every field and filter. Pass cursor back to read the next page; it is null on the last one. Prices are dollar strings below the market’s max_price.
A token without the scope an endpoint needs gets 403, naming the missing scope in the challenge and the body. This is a token minted with events only, calling GET /api/v1/markets:
HTTP/2 403www-authenticate: Bearer error="insufficient_scope", scope="market_data"
{"error":"insufficient scope for this operation","scope":"market_data"}GET /api/v1/events with a market_data-only token is refused the same way, with scope="events".
Times: microseconds on events, ISO strings on markets
Section titled “Times: microseconds on events, ISO strings on markets”An event’s start and its markets’ copy of it arrive in different formats. The same game, read both ways on US demo:
| Where | Field | Value |
|---|---|---|
GET /api/v1/events |
start_time |
1792623600000000, an integer of Unix microseconds |
GET /api/v1/events |
start_time_iso |
"2026-10-21T23:00:00.000000Z", the same instant as an ISO 8601 string |
GET /api/v1/markets |
event_start |
"2026-10-21T23:00:00.000000Z", an ISO 8601 string |
market:<market_id> join reply and market_update |
event_start |
1792623600000000, Unix microseconds again |
Divide a microsecond value by 1,000,000 for Unix seconds, or by 1,000 for the milliseconds JavaScript’s Date takes. Read start_time_iso when you would rather not convert.
Stream over the WebSocket
Section titled “Stream over the WebSocket”Connect to /socket/websocket?vsn=2.0.0 with the token in the x-stx-oauth-token handshake header and a User-Agent, then join the topics you want. The socket runs Phoenix channels, so connecting subscribes you to nothing until you join; see WebSockets.
Join the book for the markets you show:
["1","1","orderbook","phx_join",{"market_ids":["0eae64df-90bb-48d6-92f1-37bebc90ddad"]}]["1","1","orderbook","phx_reply",{"status":"ok","response":{"selected_market_ids":["0eae64df-90bb-48d6-92f1-37bebc90ddad"]}}]What arrives next depends on whether the book has orders in it.
-
A market with resting orders sends one
bookpush straight after the join reply, carrying the current book. This is the first push from the join above, on the market from the REST example:["1",null,"orderbook","book",{"timestamp":"2026-10-21T06:12:18.095898Z","market_id":"1eb49edd-9bf0-4e86-8971-f8a19ff44b7d","timestamp_us":1792563138095898,"offers":[{"quantity":"612.00","price":"0.5100","total_liquidity":"312.1200","liquidity":"312.1200","total_quantity":"612.00"},{"quantity":"1063.00","price":"0.5300","total_liquidity":"875.5100","liquidity":"563.3900","total_quantity":"1675.00"},{"quantity":"1630.00","price":"0.5400","total_liquidity":"1755.7100","liquidity":"880.2000","total_quantity":"3305.00"},{"quantity":"2272.00","price":"0.5600","total_liquidity":"3028.0300","liquidity":"1272.3200","total_quantity":"5577.00"},{"quantity":"2926.00","price":"0.5900","total_liquidity":"4754.3700","liquidity":"1726.3400","total_quantity":"8503.00"}],"bids":[{"quantity":"652.00","price":"0.4600","total_liquidity":"299.9200","liquidity":"299.9200","total_quantity":"652.00"},{"quantity":"1111.00","price":"0.4500","total_liquidity":"799.8700","liquidity":"499.9500","total_quantity":"1763.00"},{"quantity":"1704.00","price":"0.4400","total_liquidity":"1549.6300","liquidity":"749.7600","total_quantity":"3467.00"},{"quantity":"2439.00","price":"0.4100","total_liquidity":"2549.6200","liquidity":"999.9900","total_quantity":"5906.00"},{"quantity":"3076.00","price":"0.3900","total_liquidity":"3749.2600","liquidity":"1199.6400","total_quantity":"8982.00"}]}]On the socket both sides are best first:
offersstarts at the lowest price, unlike REST. -
A market with an empty book sends nothing after the join reply. There is no empty snapshot: silence means no orders. The first
bookwith levels in it comes when an order rests. A push that arrives while the book is still empty has"bids": []and"offers": [].
After that, a market pushes when its book changes, at most once every 200 ms however many orders change in that time. It is not a timer. On US demo over five minutes, the live market above sent its join snapshot, one push at 32 seconds, then six pushes within three seconds while the house maker re-quoted; an empty market sent nothing in six minutes; four new crypto markets sent nothing for 23 seconds, then their first books as the maker quoted them. Each push is the whole book for that market and can repeat the levels you already hold, so replace what you hold rather than applying it as a change.
Join trades the same way for executed trades, and ticker for a price summary per market. The pushes and their fields are under Order book, ticker and trades.
Take a snapshot over REST when you start, then keep it current from the socket. A market that sent no book after your join has an empty book. Limits on both are under Rate limits.
Showing STX prices
Section titled “Showing STX prices”Live data terms, including how STX prices are shown and credited on your site, come with live access: STX shares them before you go live. Building and testing on demo credentials is free.
Pair it with the affiliate program
Section titled “Pair it with the affiliate program”Showing STX prices on your site? Link each price to STX with your own affiliate links, and earn on the players you send. Use to= to land them on the event you show, for example https://demo.stxapp.io/r/ip7owude?to=/events/06f19033-c427-4cef-9647-794204e4e2e9.
Ontario
Section titled “Ontario”STX is live for trading in Ontario. Market data access for Ontario is waitlisted in STX Apps for now: choose Ontario when you sign up, and STX emails you when Ontario demo access opens. In Ontario an app reads public market data only (market_data and events) and does not act for members.

