Skip to main content

Overview

Exchange uses a simple, key-based authentication model. There are no passwords, no JWTs, and no OAuth flows. Two roles exist:
  • Trader — assigned an API key by an operator. Used for order entry, account queries, and WebSocket trading.
  • Admin — holds a static bearer token configured at server startup. Used for operator control-plane actions.
Traders cannot self-register. An operator must provision each trader account before they can authenticate.

Trader API keys

Each trader account has exactly one API key, generated at provisioning time. Keys have the format:
exch_1d4208be6fa84b8cb0a2e5cfa9508d5f
The prefix exch_ is followed by a 32-character hex string (a UUID without hyphens). Keys are permanent — there is no rotation mechanism or expiry.
Treat your API key like a password. Anyone who holds it can trade on your behalf, read your positions and fills, and cancel your open orders.

REST authentication

Authenticated trader routes require the x-api-key header:
x-api-key: exch_1d4208be6fa84b8cb0a2e5cfa9508d5f
Example — fetch your profile:
curl https://exchange.jamesxu.dev/api/v1/user \
  -H "x-api-key: exch_1d4208be6fa84b8cb0a2e5cfa9508d5f"
{
  "trader_id": "9d64e278-8b56-46e9-9cab-18c5b22f2fb9",
  "username": "team-alpha",
  "api_key": "exch_1d4208be6fa84b8cb0a2e5cfa9508d5f",
  "created_at": "2024-01-15T10:00:00Z"
}
The following endpoints require a valid x-api-key header:
MethodPathDescription
GET/api/v1/userAuthenticated user profile
GET/api/v1/positionsOpen positions
GET/api/v1/portfolioPortfolio snapshot with PnL
GET/api/v1/leaderboardLeaderboard
GET/api/v1/open-ordersResting orders
GET/api/v1/fillsFill history
POST/api/v1/ordersSubmit a limit order
PATCH/api/v1/orders/{order_id}Amend a resting order
DELETE/api/v1/orders/{order_id}Cancel a resting order
If the header is missing, the server returns 401 missing authentication. If the key is not recognized, it returns 401 invalid api key.

WebSocket authentication

Connect to the WebSocket endpoint:
wss://exchange.jamesxu.dev/ws
After connecting, send an authenticate message:
{"op": "authenticate", "api_key": "exch_1d4208be6fa84b8cb0a2e5cfa9508d5f"}
On success, the server responds:
{
  "type": "authenticated",
  "trader_id": "9d64e278-8b56-46e9-9cab-18c5b22f2fb9",
  "username": "team-alpha"
}
You can then submit orders and receive private user events over the same connection.

Market data without authentication

WebSocket market data subscriptions (orderbook snapshots and deltas) can be established before sending an authenticate message. You do not need an API key to observe public market data.
Only trading operations and user-scoped event streams require a successful authenticate message. A typical integration subscribes to market data immediately on connect, then authenticates in parallel or shortly after.

Security notes

  • There are no passwords. The API key is the only trader credential.
  • There is no JWT or OAuth flow. There is no token refresh.
  • API keys do not expire. If a key is compromised, an operator must re-provision the affected trader account.
  • Store your API key in an environment variable or secrets manager — never hardcode it in source code or commit it to version control.
  • Admin tokens are server-side configuration and should be rotated by redeploying the exchange with a new value.

Build docs developers (and LLMs) love