Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jamxu88/exchange/llms.txt

Use this file to discover all available pages before exploring further.

Admin routes let operators provision traders, inspect exchange state, broadcast messages, and control trading globally. All admin endpoints require a bearer token configured at startup.

Environment configuration

The exchange process reads its configuration from environment variables at startup. All variables have defaults.
VariableDefaultDescription
BIND_ADDR0.0.0.0:8080TCP address to bind the HTTP server to
ADMIN_API_TOKENlocal-admin-tokenBearer token required for all admin endpoints. Change in production.
STORAGE_BACKENDin_memoryin_memory or postgres. Use postgres for durable persistence.
DATABASE_URLpostgres://exchange:exchange@localhost:5432/exchangePostgreSQL connection string. Only used when STORAGE_BACKEND=postgres.
WS_BROADCAST_BUFFER1024Number of in-flight broadcast messages per channel before receivers lag. Increase for high-throughput markets.
PER_USER_REQUESTS_PER_SECOND100Per-user rate limit for authenticated REST routes.
POSTGRES_WRITE_BATCH_SIZE128Maximum operations per PostgreSQL write batch.
POSTGRES_WRITE_FLUSH_INTERVAL_MS25How often (in ms) the background writer flushes pending operations.
POSTGRES_WRITE_QUEUE_CAPACITY4096Depth of the background writer queue. Writes block when the queue is full.
POSTGRES_WRITE_RETRY_BACKOFF_MS250Backoff (in ms) between retries after a flush failure.
RUST_LOGexchange=info,tower_http=infoLog filter. Use exchange=debug for verbose output.
Always set ADMIN_API_TOKEN to a strong secret before deploying to any shared or public environment. The default local-admin-token value grants full operator access.

Admin authentication

Every admin request must include the ADMIN_API_TOKEN value set at startup as a bearer token:
Authorization: Bearer ADMIN_API_TOKEN
The token is read from the ADMIN_API_TOKEN environment variable when the exchange process starts. There is no way to rotate it without restarting the process.

User provisioning

Provision a trader

Use POST /api/v1/admin/users to create a new competition trader. Each provisioned user receives a unique API key used for all subsequent trader-facing authentication.
1

Send the provision request

curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  -H "content-type: application/json" \
  https://exchange.jamesxu.dev/api/v1/admin/users \
  -d '{"username":"team-alpha"}'
2

Receive the trader profile

The response includes the trader_id, username, generated api_key, and created_at timestamp:
{
  "profile": {
    "trader_id": "9d64e278-8b56-46e9-9cab-18c5b22f2fb9",
    "username": "team-alpha",
    "api_key": "exch_1d4208be6fa84b8cb0a2e5cfa9508d5f",
    "created_at": "2026-03-18T15:27:42.159901Z"
  }
}
3

Distribute the API key to the trader

Share the api_key with the team. They use it in the x-api-key header for all REST requests and in the WebSocket authenticate message. Store it securely — it is not recoverable after provisioning.
Usernames must be unique. Attempting to provision a second user with the same username returns 409 Conflict.

Reset all users

POST /api/v1/admin/users/reset clears all user positions, open orders, and fills. User accounts and API keys are preserved — only trading state is erased.
This operation is irreversible. All positions, orders, and fill history are permanently deleted for every trader on the exchange. Use only in a controlled pre-competition reset or testing scenario.
curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  https://exchange.jamesxu.dev/api/v1/admin/users/reset
Example response:
{
  "cleared_orders": 12,
  "cleared_positions": 8,
  "cleared_fills": 34
}
Connected WebSocket clients receive a resync_required system event after the reset.

Exchange state inspection

GET /api/v1/admin/state returns a full snapshot of the exchange: current trading controls, all market definitions, recent admin messages, and persistence backend status.
curl \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  https://exchange.jamesxu.dev/api/v1/admin/state
Example response shape:
{
  "controls": {
    "trading_enabled": true,
    "updated_at": "2026-03-18T15:00:00.000000Z"
  },
  "markets": [
    {
      "market_id": "BTC-USD",
      "display_name": "Bitcoin",
      "base_asset": "BTC",
      "quote_asset": "USD",
      "tick_size": 1,
      "min_order_quantity": 1,
      "reference_price": 100,
      "settlement_price": null,
      "status": "enabled",
      "created_at": "2026-03-18T15:00:00.000000Z",
      "updated_at": "2026-03-18T15:00:00.000000Z"
    }
  ],
  "recent_messages": [],
  "persistence": {
    "backend": "postgres",
    "mode": "ok",
    "queue_depth": 0,
    "in_flight_ops": 0,
    "total_enqueued": 0,
    "total_flushes": 0,
    "last_error": null
  }
}

Trading control

Trading can be enabled or disabled globally. When trading is disabled, new order submissions are rejected. Orders that are already in-flight at the moment trading is stopped still process normally.

Start trading

curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  https://exchange.jamesxu.dev/api/v1/admin/trading/start

Stop trading

curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  https://exchange.jamesxu.dev/api/v1/admin/trading/stop
Both endpoints return the updated ExchangeControls object:
{
  "controls": {
    "trading_enabled": false,
    "updated_at": "2026-03-18T15:30:00.000000Z"
  }
}

Admin messages

Admin messages can be broadcast to all connected traders or targeted at a specific username. Delivered messages appear as admin_message events on connected WebSocket clients.

Send a message

POST /api/v1/admin/messages accepts the following fields:
FieldTypeDescription
target_usernamestring | nullTarget a specific trader by username, or null to broadcast to all.
marketstring | nullOptional market context (e.g. "BTC-USD").
levelstringSeverity: info, warning, or critical. Required.
titlestring | nullOptional short title for the message.
bodystringRequired message body.
Broadcast to all traders:
curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  -H "content-type: application/json" \
  https://exchange.jamesxu.dev/api/v1/admin/messages \
  -d '{
    "target_username": null,
    "market": "BTC-USD",
    "level": "info",
    "title": "Desk notice",
    "body": "Trading will stop in five minutes."
  }'
Target a specific trader:
curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  -H "content-type: application/json" \
  https://exchange.jamesxu.dev/api/v1/admin/messages \
  -d '{
    "target_username": "team-alpha",
    "market": null,
    "level": "warning",
    "title": "Risk alert",
    "body": "Your position in BTC-USD is approaching the limit."
  }'
Messages sent to a specific target_username are routed only to that trader’s WebSocket session. Broadcast messages (where target_username is null) are delivered to all connected clients.

Retrieve recent messages

curl \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  https://exchange.jamesxu.dev/api/v1/admin/messages
Returns a list of recent AdminMessageEntry objects in reverse-chronological order.

Bulk config load

POST /api/v1/admin/config/load applies a complete exchange configuration — trading controls and all market definitions — in a single call. This is the recommended way to initialise the exchange before a competition round.
curl \
  -X POST \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  -H "content-type: application/json" \
  https://exchange.jamesxu.dev/api/v1/admin/config/load \
  -d '{
    "trading_enabled": false,
    "markets": [
      {
        "market_id": "BTC-USD",
        "display_name": "Bitcoin",
        "base_asset": "BTC",
        "quote_asset": "USD",
        "tick_size": 1,
        "min_order_quantity": 1,
        "reference_price": 100,
        "enabled": true
      },
      {
        "market_id": "ETH-USD",
        "display_name": "Ethereum",
        "base_asset": "ETH",
        "quote_asset": "USD",
        "tick_size": 1,
        "min_order_quantity": 1,
        "reference_price": 50,
        "enabled": true
      }
    ]
  }'
The response includes the applied controls and the full list of resulting markets. If trading_enabled is omitted, the existing value is preserved.

Leaderboard

GET /api/v1/admin/leaderboard returns the full leaderboard ranked by marked net PnL. Unlike the trader-facing leaderboard, this endpoint has no rate limiting and returns all traders.
curl \
  -H "Authorization: Bearer ADMIN_API_TOKEN" \
  https://exchange.jamesxu.dev/api/v1/admin/leaderboard
Example response:
[
  {
    "rank": 1,
    "trader_id": "9d64e278-8b56-46e9-9cab-18c5b22f2fb9",
    "username": "team-alpha",
    "net_pnl": 420,
    "realized_pnl": 300,
    "unrealized_pnl": 120,
    "gross_exposure": 1000
  }
]
Net PnL is computed using settled prices for settled markets, mid-price of the best bid/ask when both sides are present, best available one-sided quote when only one side exists, or reference_price as a fallback.

Build docs developers (and LLMs) love