Order Manager (HTTP)
The matching engine’s HTTP surface, served by axum under /v1/.
Authenticated with SIWS; GET /health is the
only public route.
Base URL: CLOB_HTTP_ADDR, default http://127.0.0.1:8080.
Routes
Section titled “Routes”| Method | Path | Operation |
|---|---|---|
POST | /v1/orders | Insert an order |
GET | /v1/orders | Your resting orders (query: FilterParams) |
GET | /v1/orders/value-range | Resting orders above a notional threshold |
GET | /v1/orders/{id} | One order, book only |
POST | /v1/orders/cancel | Cancel one |
POST | /v1/orders/cancel-batch | Cancel several |
POST | /v1/orders/cancel-all | Cancel everything you own |
POST | /v1/orders/cancel-market | Cancel everything in a market/asset |
POST | /v1/orders/size-update | Internal — X-Internal-Token |
GET | /v1/trades | Trade history (query: TradeParams) |
GET | /v1/trades/last | Most recent trade |
GET | /v1/open-orders | Open orders from the ledger |
GET | /v1/open-orders/{id} | One open order |
GET | /v1/order-book-summary | Book summary (condition_id, token_id) |
GET | /v1/book | Aggregated book (token_id, optional condition_id) |
GET | /v1/markets | Condition ids of every book |
GET | /v1/tokens | Every known token id |
GET | /v1/markets/{condition_id} | Market metadata |
GET | /health | {"ready": bool} — public |
Query parameters are parsed with #[serde(default)], so optional filters may
be omitted entirely.
Authentication
Section titled “Authentication”Authorization: Bearer <SIWS JWT>The sub claim is the authenticated address. It is the owner of every
order you insert, the identity for cancels, and the required value of any
owner filter. Client-supplied owner fields are accepted but ignored.
GET /v1/orders and GET /v1/orders/value-range are always scoped to that
address — other users’ order hashes and owners are never published.
The raw signed order. Wire names are camelCase.
| Field | Type | Notes |
|---|---|---|
salt | i64 | |
maker | string | Base58 Solana address (hex accepted as a fallback) |
signer | string | Base58; must equal maker |
taker | string | Base58; must be the zero address |
tokenId | string | Asset id |
makerAmount | string | Raw token units, decimal string |
takerAmount | string | Raw token units, decimal string |
side | string | "BUY" / "SELL" |
expiration | string | GTD unix seconds; "0" for GTC/FOK |
nonce | string | Must be "0" |
feeRateBps | string | |
signatureType | u32 | 0 = EOA. 1/2 legacy wallet types are rejected |
signature | string | 64-byte ed25519 over the order hash, hex or base58 |
The order hash
Section titled “The order hash”sha256( b"CTF_EXCHANGE_ORDER_V1" ‖ salt:u64LE ‖ maker:32B ‖ signer:32B ‖ taker:32B ‖ token_id_len:u64LE ‖ token_id:UTF8 ‖ maker_amount:u64LE ‖ taker_amount:u64LE ‖ expiration:u64LE ‖ nonce:u64LE ‖ fee_rate_bps:u16LE ‖ side:u8 ‖ signature_type:u8 )
side: BUY=0, SELL=1 signature_type: EOA=0The signature is not part of the hash. This digest is the orderID, the
de-dup key, and the value verified on-chain.
POST /v1/orders
Section titled “POST /v1/orders”Request — NewOrder
Section titled “Request — NewOrder”{ "order": { /* Order */ }, "owner": "7xKX…", // accepted, ignored "orderType": "GTC" // "GTC" | "FOK" | "GTD"}Response — OrderResponse
Section titled “Response — OrderResponse”| Field | Type | Notes |
|---|---|---|
success | bool | |
errorMsg | string | Empty on success |
orderID | string | The order hash; empty on failure |
transactionsHashes | string[] | On-chain signatures for executed fills |
status | string | See below |
status | Meaning |
|---|---|
live | Rested in the book, no match |
matched | Matched and executed |
delayed | Scheduled on the pending service (game-start window) |
unmatched | Could not match — e.g. a killed FOK |
success: true with status: "live" is a normal, unfilled outcome.
Cancel routes
Section titled “Cancel routes”All four return CancelOrdersResponse:
| Field | Type | Notes |
|---|---|---|
canceled | string[] | Order hashes cancelled |
not_canceled | map<string,string> | Order hash → reason |
Cancels are not atomic across a batch — read both fields.
OrderMarketCancelParams
Section titled “OrderMarketCancelParams”{ "market": "0xdemo-condition", "asset_id": "100" }POST /v1/orders/size-update (internal)
Section titled “POST /v1/orders/size-update (internal)”Not user-facing. The Executor reports on-chain partial fills and cancels for any owner, so this route is authorized by a shared secret rather than SIWS:
X-Internal-Token: <CLOB_INTERNAL_TOKEN>The comparison is constant-time and the route fails closed when no token is configured.
UpdateOrderSize
Section titled “UpdateOrderSize”| Field | Type |
|---|---|
orderID | string |
isFilledOrCanceled | bool |
remainingSize | u64 |
Query parameters
Section titled “Query parameters”FilterParams
Section titled “FilterParams”All optional.
| Field | Type | Notes |
|---|---|---|
owner | string | Must equal your authenticated address |
max | u32 | Max items, default 100 |
market | string | Condition id / asset filter |
side | string | "buy" / "sell" |
start_ts / end_ts | i64 | Unix-second bounds |
min_value | string | Min normalized value (size × price) |
fidelity | u32 | History accuracy, seconds |
TradeParams
Section titled “TradeParams”| Field | Type |
|---|---|
id, owner, taker, maker | string |
market, asset_id | string |
limit | u32 |
before, after | string |
OpenOrderParams
Section titled “OpenOrderParams”id, owner, market, asset_id.
Response shapes
Section titled “Response shapes”TradeSummary
Section titled “TradeSummary”| Field | Type |
|---|---|
id | string |
taker_order | string |
market | string (condition id) |
asset_id | string |
side | string |
size | string |
fee_rate_bps | string |
price | string |
status | string |
match_time / last_update | string |
outcome | string |
bucket_index | u32 |
owner | string |
maker_address | string |
transaction_hash | string |
maker_orders | MakerOrderSummary[] |
MakerOrderSummary: order_id, owner, maker_address, matched_amount,
price, fee_rate_bps, asset_id, outcome.
One taker sweeping four price levels produces one trade with four maker
legs — reconcile against maker_orders, not the trade count.
OpenOrder
Section titled “OpenOrder”| Field | Type |
|---|---|
id | string |
status | string |
owner | string |
market | string |
asset_id | string |
side | string |
original_size | string |
size_matched | string |
price | string |
associate_trades | string[] |
outcome | string |
created_at | i64 |
expiration | string |
type | "GTC" / "FOK" / "GTD" |
OrderBookSummary
Section titled “OrderBookSummary”| Field | Type |
|---|---|
market | string (condition id) |
asset_id | string |
bids | OrderSummary[] — { price, size } |
asks | OrderSummary[] |
hash | SHA-256 over the canonical JSON of the other fields |
Conventions
Section titled “Conventions”- Amounts are decimal strings. Raw units are
u64with 1e6 scaling; normalized amounts areDecimal. Never floats on the wire. successvsstatus. Insert can succeed without filling —statusdisambiguates.- Ownership. Cancels require the authenticated address to match the order owner, case-insensitively.
- Book vs ledger.
GET /v1/orders/{id}is book-only; a fully matched order won’t be found there. Use the open-order and trade routes for history.
Configuration
Section titled “Configuration”| Variable | Default | Meaning |
|---|---|---|
CLOB_HTTP_ADDR | 127.0.0.1:8080 | HTTP listen address |
CLOB_GRPC_ADDR | 127.0.0.1:50051 | gRPC listen address |
CLOB_RPC_URL | http://localhost:8899 | Solana JSON-RPC |
CLOB_SIWS_AUD | GoMarket API | SIWS aud claim |
CLOB_SIWS_ISS | (empty) | Expected issuer; empty = unchecked |
CLOB_SIWS_MAX_AGE_SECONDS | 300 | Max token age |
CLOB_INTERNAL_TOKEN | (empty) | Internal-route secret; empty = disabled |
CLOB_MARKET_UPDATES_INTERVAL_MS | 10000 | Catalogue pull interval |
CLOB_LEDGER_BACKEND | grpc | grpc or in_memory |
CLOB_LEDGER_URL | http://localhost:5000 | |
CLOB_EXECUTION_BACKEND | grpc | grpc or in_memory |
CLOB_EXECUTION_URL | http://localhost:6000 | |
CLOB_RISK_BACKEND | on_chain | on_chain or in_memory |
CLOB_MARKETS_BACKEND | api | api or in_memory |
CLOB_MARKETS_API_URL | http://localhost:8081 | |
CLOB_ENABLE_MINT_MERGE_MATCHING | 1 | Same-side matching |
CLOB_ENABLE_SERVERS | 1 | Bind the network transports |
LOG_LEVEL | info | RUST_LOG overrides |
On SIGINT the binary shuts down gracefully: listen threads are flagged,
timer threads stop, all threads are joined.