Titandocs

REST reference

Every /v1 route, grouped by what it reads from.

All decimals are strings (10 dp). Party-scoped routes are guarded by authenticate + requireOwnParty.

Vault (on-chain)

MethodRouteDescription
GET/v1/vaultCurrent vault (mono-operator)
GET/v1/vaultsAll vaults
GET/v1/vaults/:operatorOne operator's vault

Collateral (on-chain)

MethodRouteDescription
GET/v1/deposits?user&before&limitdeposit_receipts, paginated
GET/v1/withdrawals?user&status&limitwithdrawal_requests
GET/v1/users/:party/deposits?before&limitScoped
GET/v1/users/:party/withdrawals?status&limitScoped
GET/v1/users/:party/withdrawal-counterCurrent nonce

Batches & commitments (on-chain)

MethodRouteDescription
GET/v1/batches?limitbatch_manifests, newest first
GET/v1/batches/:batchNumOne manifest
GET/v1/user-batches?limitAll user batches
GET/v1/users/:party/user-batches?limitOne user's chain, oldest first

Engine projection (off-chain mirror)

MethodRouteDescription
GET/v1/orders?user&market&status&limitengine_orders, global
GET/v1/fills?user&market&before&limitengine_fills, global
GET/v1/users/:party/orders?market&status&limitScoped
GET/v1/users/:party/triggers?market&status&limitTP/SL lifecycle: armed | cancelled | fired
GET/v1/users/:party/fills?market&before&limitScoped
GET/v1/users/:party/positions?status&limitstatusopen (default) | closed | all
GET/v1/users/:party/balancenew_balance of the last fill
POST/v1/users/:party/faucetTestnet top-up (cooldown + ceiling, FAUCET_ENABLED)

status=closed returns archived epochs, not "positions you no longer hold" — a flip produces a closed epoch even though the market position is still open under a new positionId.

Verifications (audit)

MethodRouteDescription
GET/v1/verifications/user-batches?status&user&limitEngine ↔ on-chain, per user
GET/v1/verifications/manifests?status&limitEngine ↔ on-chain, manifests

Events firehose (REST)

MethodRouteDescription
GET/v1/events?since&type&user&limitMirror pagination by seq

Use this to backfill a gap after a WebSocket reconnect: take the last seq you saw, request ?since=, then resume the socket.

Trading (non-custodial proxy)

MethodRouteRequired headers
POST/v1/session-auth
POST/v1/ordersX-User, X-Session-Id, X-Session-Sig
DELETE/v1/orders/:orderIdX-User, X-Session-Id, X-Session-Sig
POST/v1/tpslX-User, X-Session-Id, X-Session-Sig
GET/v1/orderbook?depth— (public)
GET/v1/user/methe three headers + a signed JSON body

GET /v1/user/me is unusable from a browser. The engine wants a signed body on a GET, and fetch forbids GET bodies. This blocks armed-trigger display in the UI and needs an API-side change — there is no front-end workaround.

System

MethodRouteDescription
GET/healthzLiveness
GET/readyzDB + engine reachability + max engine seq
GET/metricsPrometheus (bff_engine_max_seq)
GET/docsSwagger UI
GET/docs/jsonOpenAPI JSON

Examples

# Open positions for a party
curl 'http://localhost:4000/v1/users/Alice::1220…/positions?status=open'

# Fill history, paginated backwards
curl 'http://localhost:4000/v1/users/Alice::1220…/fills?market=BTC-USDCX&limit=50'
curl 'http://localhost:4000/v1/users/Alice::1220…/fills?before=<oldest-seq>&limit=50'

# Armed TP/SL triggers
curl 'http://localhost:4000/v1/users/Alice::1220…/triggers?status=armed'

# Audit: any mismatch at all is an incident
curl 'http://localhost:4000/v1/verifications/manifests?status=mismatch'

On this page