Skip to main content
This guide uses OMS for trading and account state. Market data comes from MDS; see Market data client.

Flow

  1. Authenticate: GET /nonce/{user_id}, sign the nonce value, POST /auth.
  2. Discover the market on OMS: GET /markets or GET /market/{asset_id} for book decimals and fees.
  3. Sign the action-specific object: order create signs order, replace signs request, cancel signs cancel.
  4. Submit over REST or the /control WebSocket.
  5. Treat the REST response as admission, not finality. Confirm over the orders and trades streams or by refetching orders.
Numeric examples use raw book units. With book_price_decimals = 2, 250000 means 2500.00. With book_quantity_decimals = 8, 125000000 means 1.25000000.

Raw REST

create-order.json contains the signed body from Signing. Replace:
Cancel:
Batch create wraps signed create requests:
Batch create is not all-or-nothing: accepted orders remain live even if a later item rejects. Cancel-all is unsigned at the action layer and authenticated by the session. OMS collects open orders with timestamp_ns < max_ts; if max_ts is omitted, it uses server time:
Use DELETE /orders/cancel-all/{asset_id} to scope to one market. Use DELETE /orders/cancel-batch with order IDs for a selected subset; IDs not owned by the caller are ignored.

tpluspy

Pass use_ws_control=True to OrderBookClient to send create, replace, and cancel over /control instead of REST. The control channel accepts v0 raw action wrappers or v1 envelopes with request_id.

Replace semantics

Replace preserves the order ID. The mutable fields are price, quantity, and trigger; the request also carries book decimals when price or quantity changes. Fill state of a partially filled enabled order is preserved. A replace with an older timestamp_ns than a newer applied replace is rejected by the orderbook. REST replace and REST cancel first look up the current OMS order and return not found if absent. The control channel forwards directly to the orderbook; a cancel that reaches the fast queue before its create can reject the later create.

Sub-accounts, transfers, and close-all

There is no standalone “create sub-account” call. Transfer spot balance into an unused target_index and include target_account_type. Raw transfer: Populate signature with the Ed25519 signature bytes over compact inner before sending.
tpluspy-assisted transfer, using the SDK user signer and the raw request path:
Use a client-generated, strictly increasing nonce per action domain and treat that nonce as the retry key: after a timeout, check /account/events/{user_id} and /inventory/user/{user_id} before sending a new nonce. The current request_transfer_to_subaccount SDK helper does not include the required signed nonce field; use the explicit signing path above until the helper exposes it. Close-position is available only after the base leg is zero. It folds the remaining quote credits into spot USD, or repays quote liabilities from spot USD, and emits PositionCleared; if a quote liability remains, the spot USD balance must cover it.
The current request_close_position SDK helper also omits the required signed nonce; use the explicit signing path above until the helper exposes it. Close-all is a preview loop:
  1. GET /positions/close-all/{user_id}/{sub_account} returns unsigned reduce-only close orders.
  2. Sign each suggested order.
  3. Submit with POST /orders/batch-create.
  4. Watch fills, then call close-position for each flattened asset.
  5. Re-run the preview after partial fills or price movement.