Integrate with STX
Go from nothing to a resting order on the book, with a socket streaming your own fills as they happen.
By the end you will have:
- an API key you created yourself, and a signed request the exchange accepts
- your
user_id, which your account channel topics are keyed on - an order placed and cancelled against a live market
- a WebSocket connection pushing your orders, fills and positions as they happen
Everything here runs against a demo environment: a real-time order book with other developers trading in it, and no real money at risk. You pick which one in the next step, and the interactive panels below follow that choice.
Authentication
Section titled “Authentication”1. The environment
Section titled “1. The environment”STX runs two exchanges, one in the US and one in Ontario. Pick the one you are integrating with. They sit under different regulators and accounts do not carry across, so a key from one will not work on the other. See United States and Canada if you are not sure which.
| Exchange | Demo | Production |
|---|---|---|
| United States | https://demo.stxapp.io |
not yet open for trading |
| Canada (Ontario) | https://demo.stxapp.ca | https://api.on.stxapp.ca |
These are the API hosts your requests go to. Demo environments carry no real money and are shared by every developer, so the order books have genuine activity in them.
2. Register and create an API key
Section titled “2. Register and create an API key”Keys are self-service. Register on the web app for the exchange you are integrating with, then mint a key from your profile.
| Exchange | Register at |
|---|---|
| United States | demo.stxapp.io |
| Ontario | demo.stxapp.ca |
| Ontario production | stxapp.ca |
Accounts do not carry across exchanges. Register on the one you are targeting, and see United States and Canada if you are not sure which.
- Register, and verify your email address
- Open the profile icon, top right → My Profile → API Keys
- Create key, and give it a nickname
- Choose Read only or Read/Write. Read/Write is required to place or
cancel orders; this is the value
GET /api/v1/mereturns asscope - Optionally paste your own Ed25519 public key. Leave it blank and STX generates the keypair for you
- Create
You get a key ID and, unless you supplied your own public key, a private key PEM:
Key ID: a1b2c3d4e5f60718293a4b5c6d7e8f90Private key: -----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIH... -----END PRIVATE KEY-----Optional: bring your own key, so the private half never leaves your infrastructure
Leaving the public key field blank is fine. STX generates the pair and shows you the private key once. If you would rather it never existed on someone else’s server, generate the pair yourself and paste the public half into step 5:
openssl genpkey -algorithm ed25519 -out stx.pemopenssl pkey -in stx.pem -pubout # paste this into the dialogWorth doing for a production trading system; unnecessary while you are trying the API out.
One key authenticates both surfaces: APIs and the WebSocket channels.
3. Deposit
Section titled “3. Deposit”Nothing to do. Demo accounts are credited with test funds automatically when you register, so you have a balance to trade against from the moment your key works. There is no deposit step and no funding request.
The money is not real and neither is the risk: demo environments settle
in test currency and are wiped independently of production. Read your available
balance and exposure with GET /api/v1/account/balance,
or stream them as they change on the balances
socket channel.
Placing an order reserves liability against that balance. If an order is rejected for insufficient funds on an account you have just created, check that you registered on the demo host in the table above rather than a production one.
Run the balance down and you can ask for a top-up in #dev on Discord, which is also where to bring anything else that comes up while you integrate. You will be talking to the engineers who build the exchange.
4. Send a request
Section titled “4. Send a request”Enter your demo key ID and private key below, pick any endpoint and send it for real. You see the signed headers, a copyable curl command and the actual response. Signing happens in your browser with WebCrypto, and your private key is never transmitted. It is saved in this browser’s local storage so the other widgets on this site can use it, until you clear it. Only demo hosts are offered, so use a demo key.
Try it
/api/v1/account/balanceGet account balance/api/v1/account/market_statsGet account market stats/api/v1/positionsList open positions/api/v1/tnc/acceptAccept terms and conditions/api/v1/eventsList events/api/v1/fillsList fills/api/v1/leaderboardGet a leaderboard/api/v1/leaderboard/meGet your own standing/api/v1/marketsList markets/api/v1/meGet the authenticated account/api/v1/me/profileUpdate your public profile/api/v1/ordersList orders/api/v1/ordersPlace an order/api/v1/orders/allCancel all open orders/api/v1/orders/batchedPlace several orders/api/v1/orders/batchedCancel several orders/api/v1/orders/{order_id}Get an order/api/v1/orders/{order_id}Cancel an order/api/v1/portfolio/adjustmentsList adjustments/api/v1/portfolio/depositsList deposits/api/v1/portfolio/feesList fees/api/v1/portfolio/loyaltyList loyalty entries/api/v1/portfolio/settlementsList settlements/api/v1/portfolio/withdrawalsList withdrawalsThis is a write: it changes real state on the demo exchange under your key.
As curl
A signature is valid for about 30 seconds. Sign again if you wait before using these.
Signing happens in your browser with WebCrypto. Your private key is never sent anywhere; Send request sends your key ID and the signature to the demo host above. Only demo hosts are offered. The key ID and private key are saved in this browser's local storage, per jurisdiction, until you click Clear saved key. Use a demo key here, never a production one.
WebSockets
Section titled “WebSockets”5. Connect over WebSocket
Section titled “5. Connect over WebSocket”The same key authenticates the WebSocket, but the handshake signs differently
from a REST call: always GET, and against the socket path only.
message = timestamp_ms + "GET" + "/socket/websocket"Note the path excludes the query string, even though you connect to
wss://<host>/socket/websocket?vsn=2.0.0 on whichever exchange you chose.
Send a User-Agent header on the WebSocket handshake. A handshake without one
is refused with 403. Browsers always send one; some WebSocket libraries, such
as Node’s ws, do not unless you set it.
Your user_id comes only from GET /api/v1/me. There is no other way to look it up.
Connect for real, right now. This joins the live market feed from your browser. A browser cannot add signed headers to a WebSocket handshake, so this connection is unsigned, which market-wide channels accept:
Try it
Not connected.
Join frame sent:
Latest response received:
Connects directly from your browser to the demo market feed, with no key: market-wide channels accept an unsigned connection. Account channels can't be tried here, because a browser WebSocket handshake cannot carry the signedX-STX-ACCESS-* headers they need. Use the signed command or script generator below for those, and sign every connection in your own client. SeeWebSocket channels.
Account channels
Section titled “Account channels”Your own channels, such as orders, fills, positions and balances, need a
signed connection, and a browser cannot sign a WebSocket handshake. Run one from
your machine instead:
- stx-api-examples:
watch_channel.pyandwatch_channel.mjsjoin any channel with your API key, for example--topic 'orders:<user_id>', and look up youruser_idfor you. - The SDKs sign the connection and keep it alive for you.
See WebSocket channels for the full channel list and frame format,
or watch it live on cancel_on_disconnect.
- Postman collection: every REST endpoint, with the signing script wired in
- REST API reference: every endpoint, request and response
- WebSocket channels: every channel, with its topic and payloads
- Runnable examples on GitHub: Python quickstart and a live watcher
- Rate limits
- Fees
- Account limits

