Skip to content

Quickstart

Everything on this page was run against https://demo.stxapp.io before publishing.

Prices and markets are public. You can start reading before you have credentials:

Terminal window
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 } } }"}'

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.

The message is three values concatenated with no separator:

timestamp_ms + HTTP_METHOD_UPPERCASE + path_including_query
import base64, time, requests
from 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.

Every /api/v1 route requires a signature — there are no unauthenticated REST endpoints.

Terminal window
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":"..."}.

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.

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.

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