Skip to main content

REST error shape

All REST errors return a JSON body with a single error field:
{
  "error": "human readable message"
}

REST status codes

StatusExample causes
400 Bad RequestInvalid market symbol, invalid price, tick-size violation, invalid quantity, invalid amend, missing username
401 UnauthorizedMissing x-api-key, invalid API key, missing Authorization header, invalid admin token
403 ForbiddenOrder exists but belongs to a different trader
404 Not FoundOrder not found, market not configured, target user not found
409 ConflictProjected position limit breach, trading disabled, market disabled, market settled, username already exists
429 Too Many RequestsPer-user rate limit exceeded (100 ops/sec)
500 Internal Server ErrorNumeric overflow or other internal failure
A 409 Conflict on order submission means your projected net position would exceed the +/-1000 limit for that market. Check your open orders and current position before resubmitting.
Example error response:
{
  "error": "projected net position for BTC-USD would be 1005; limit is +/-1000"
}

WebSocket error messages

error messages indicate protocol or transport-level problems. They are not tied to a specific trading operation.
CodeMeaning
invalid_messageThe message could not be parsed or is missing required fields
unsupported_channelSubscription requested for an unsupported channel
invalid_api_keyThe API key provided during WebSocket authentication is invalid
Example:
{
  "type": "error",
  "code": "unsupported_channel",
  "message": "only the l3 channel is supported"
}

WebSocket reject messages

reject messages indicate a trading operation was refused. Each reject includes the original op, the request_id from your message, and a machine-readable code.
CodeMeaning
unauthenticatedOperation attempted before authenticating the WebSocket session
trading_disabledExchange-wide trading has been stopped by an admin
invalid_marketMarket symbol format is invalid (must be BASE-QUOTE)
market_not_configuredNo market definition exists for the requested symbol
market_disabledMarket exists but is currently disabled
market_settledMarket has been settled and no longer accepts orders
invalid_pricePrice is zero or otherwise invalid
tick_size_violationPrice is not a multiple of the market’s tick size
invalid_quantityQuantity is zero or otherwise invalid
quantity_below_minimumQuantity is below the market’s minimum order quantity
invalid_remainingAmend remaining is zero
invalid_amendAmend would increase remaining quantity, which is not allowed
order_not_foundOrder ID does not exist in the trader’s open orders
order_not_ownedOrder exists but belongs to a different trader
position_limit_exceededProjected net position after the order would exceed +/-1000
overflowNumeric overflow during position or PnL calculation
Example:
{
  "type": "reject",
  "op": "submit_order",
  "request_id": "req-1",
  "code": "position_limit_exceeded",
  "message": "projected net position for BTC-USD would be 1005; limit is +/-1000"
}

Health degradation

The GET /health endpoint reflects persistence state in the status field:
Persistence modestatus value
disabledok
okok
retryingdegraded
backpressureddegraded
stoppeddegraded
Example degraded response:
{
  "status": "degraded",
  "service": "exchange",
  "now": "2026-03-18T15:27:00.000000Z",
  "persistence": {
    "backend": "postgres",
    "mode": "retrying",
    "queue_depth": 412,
    "last_error": "connection refused"
  }
}
A degraded status means the persistence layer is not successfully writing. In-memory state is still live and the exchange continues to serve traffic, but data may not be durably stored.

Build docs developers (and LLMs) love