Quickstart
Everything on this page was run against https://demo.stxapp.io before publishing.
1. Market data needs no key
Section titled “1. Market data needs no key”Prices and markets are public. You can start reading before you have credentials:
curl -s -X POST https://demo.stxapp.io/api/graphql \ -H 'Content-Type: application/json' \ -d '{"query":"{ marketInfosWithCount(input:{status:[OPEN]}) { count marketInfos { marketId title status trading } } }"}'2. Get an API key
Section titled “2. Get an API key”Log in, go to Account → API Keys, and create one. You get a key id and a private key PEM, shown once. The same key authenticates REST, GraphQL and the private WebSocket channels.
3. Sign a request
Section titled “3. Sign a request”The message is three values concatenated with no separator:
timestamp_ms + HTTP_METHOD_UPPERCASE + path_including_queryimport base64, time, requestsfrom cryptography.hazmat.primitives.serialization import load_pem_private_key
key_id = "your-key-id"private_key = load_pem_private_key(open("stx.pem", "rb").read(), password=None)
def signed(method, path, host="https://demo.stxapp.io"): ts = str(int(time.time() * 1000)) sig = private_key.sign((ts + method.upper() + path).encode()) return { "STX-ACCESS-KEY": key_id, "STX-ACCESS-TIMESTAMP": ts, "STX-ACCESS-SIGNATURE": base64.b64encode(sig).decode(), }
path = "/api/v1/me"print(requests.get("https://demo.stxapp.io" + path, headers=signed("GET", path)).json())Three rules that account for most failed signatures:
| Rule | Why it bites |
|---|---|
| The path includes the query string | Signing /api/v1/markets and sending ?status=open fails |
| Timestamp within 30 seconds | Generate it per request; never cache a signature |
| The body is not signed | Only timestamp, method and path |
Full scheme with a test vector: Request signing.
4. Place and cancel an order
Section titled “4. Place and cancel an order”Every /api/v1 route requires a signature — there are no unauthenticated REST
endpoints.
POST /api/v1/orders{ "market_id": "2bc3d8d8-fca3-432d-8540-e01e11835fae", "order_type": "limit", "action": "buy", "price": 42, "quantity": 5}Returns 200 with {"order": {...}}. Cancel it with
DELETE /api/v1/orders/{id}, which returns {"status":"cancelled","order_id":"..."}.
5. Pagination
Section titled “5. Pagination”List endpoints return an opaque cursor and a collection named after the resource
— not data:
{ "cursor": "g2gDbQAAABBTLYKhlqfKqbmNFZpfd6g1...", "orders": [ ... ] }Pass the cursor back to fetch the next page. cursor is null on the last page.
Postman
Section titled “Postman”Download the collection — all 16
endpoints with the Ed25519 signing script already wired into the pre-request hook.
Set stx_access_key and stx_private_key as environment variables and
server_url to https://demo.stxapp.io.
Known issues
Section titled “Known issues”Being fixed; noted here so you do not lose time to them.
| Issue | Workaround |
|---|---|
GET /api/v1/markets?status=open returns markets whose status is suspended, and trading=true is ignored |
Use the GraphQL query in step 1 to find genuinely open markets |
?status=OPEN returns 400 |
Lowercase the value |

