Skip to main content
The Exchange client performs every state-changing operation. Each call is signed with your wallet key using EIP-712; the SDK builds the envelope, selects the signing path, manages the nonce, and checks every field before signing.
wallet may be a private-key hex string or an eth_account LocalAccount. Optional arguments:
Prices and sizes are raw integer strings, scaled by the contract’s priceScale / qtyScale from configs. In the samples below, asset, price, and size stand for values derived that way — see the quick start.

Register an account

On success account_id is captured on the client. The new account has no balance; deposit funds before trading. enroll_user_to_market_deployer(market_deployer_id) enrolls an existing account in another deployer.

Receipts: sync or async

order, cancel, cancel_by_cloid, cancel_all, and modify (and their bulk forms) take a sync argument that overrides the client default for one call:
  • sync=True — HTTP 200 once the action has executed, with response.data.statuses[] holding one entry per submitted item, in request order:
    • order / modify: {"resting": {"oid": ...}}, {"filled": {"totalSz": ..., "avgPx": ..., "oid": ...}}, or {"error": "..."}.
    • cancel / cancel_by_cloid: the string "success" or {"error": "..."}.
    • cancel_all: {"limitCancelled": n, "conditionalCancelled": m} instead of statuses[].
    A malformed request is refused with 400 INVALID_PARAM (ClientError). If the result is not ready in time the server answers 504 DOWNSTREAM_TIMEOUT — this does not mean the action failed; reconcile as for OutcomeUnknownError.
  • sync=False — HTTP 202 straight away with {"status": "accepted", "response": {"type": "accepted", "data": {"count": n}}}. The per-item outcome, including any rejection, arrives only on the orderUpdates channel, correlated by cloid, or by n (your nonce) and si (the item’s index in the batch).
  • Not set — the server default, which is currently the 202 form. Set sync explicitly if your code parses the response.
Every other action is always synchronous and does not take sync.

Orders

  • Client order ids (cloid) are positive int64 values; wrap them with Cloid.from_int(...) so you can find the order later with orders_by_cloids or cancel it with cancel_by_cloid.
  • Market orders need a price. price is the execution price you are willing to cross to; the server derives none. Compute it from the mark price and your account’s slippage cap: mark × (1 ± marketSlippageBps / 10000), read from user_account and set with update_slippage_setting. Market orders are not checked against the price band, so validate the price before sending.
  • Batches. In bulk_orders, only orders[0]’s builder_address / builder_fee apply to the whole batch. Trigger orders and inline TP/SL must be sent as single orders; the SDK refuses them inside a batch.

Inline TP/SL and trigger orders

trigger_order places a market IOC on trigger by default (is_market=False for a resting GTC limit); price is the execution price either way. With sync=True it answers with the TP/SL receipt {"type": "tpSl", "data": {"tpOrderId": n, "slOrderId": n}}. Cancel it with cancel_conditional.

Cancel and modify

modify changes only price, size, time in force, and client order id (new_cloid); pass just the fields you want to change. Side, asset, and reduce-only cannot change. size is the new total size including what has already filled, so it must exceed the filled amount. tif may only be Gtc or Alo.

Margin and leverage

  • update_margin_mode requires no open position or orders on the contract. Omit is_hedge to keep the current position mode. HEDGE position mode is currently unavailable and is_hedge=True is rejected. See Update Margin Mode.
  • update_slippage_setting sets the market-order slippage cap in basis points, per account and market deployer; the accepted range is above 0 up to 10000.

Position TP/SL

  • Set at least one leg. Each leg you set needs a trigger price (tp_price / sl_price), an order type (1 = limit, 2 = market), and a limit price above 0 — the resting price for a limit leg, the price to cross to for a market leg.
  • Size "0" (the default) closes the whole position.
  • Trigger type: 0 = mark price (default), 1 = oracle price.
  • The receipt carries tpOrderId / slOrderId (0 for a leg not set); pass either to cancel_conditional.
  • is_position_tpsl=False creates a standalone conditional order instead: it needs order_side ("B" or "S", the side placed on trigger) and exactly one leg. open_tp_* / open_sl_* attach a take-profit / stop-loss to the order it places when it fires.

Collateral transfers

Amounts are raw integer strings in the coin’s scale. These three actions use the Typed signing path and must be signed by the master key.

Portfolio margin

UNIFIED keeps each market deployer’s margin separate; PORTFOLIO pools margin across the contracts of a share group. Switching requires no position and no open order. Read the available groups with share_group_state.

Agent (API-wallet) delegation

Keep the master key offline and authorize a hot agent key to sign trades. The server routes an agent-signed action to the master account from the recovered signer, so the agent Exchange keeps account_id pointed at the master.
  • approve_agent and revoke_agent are master-only. valid_until is a Unix-ms expiry (0 = permanent).
  • An account holds one unnamed agent and up to three named ones. Approving with a name already in use — including the empty name — replaces that agent. Names are compared on their first 16 bytes.
See API Wallets for the delegation model.