Skip to content

Orders & OMS

Orders are intents. You submit what you want; the platform composes, signs, and dispatches it to the venue, then reports the outcome over /ws/risk. One endpoint set covers every wired venue.

Every write on this page needs a non-readonly credential. cancel, cancel-all, and flatten accept liquidation; everything else — place, modify, reverse, chase, and the bracket calls — needs fullTrading. The rule is that liquidation may reduce exposure, never add it. A readonly credential is refused with 403 tier_readonly, a liquidation credential on a fullTrading route with 403 tier_insufficient. See Scopes & tiers.

POST /api/v1/oms/intents

Terminal window
curl -s https://api.troncharts.xyz/api/v1/oms/intents \
-H "authorization: Bearer $TOKEN" \
-H "x-tenant-slug: $TC_TENANT_SLUG" \
-H 'content-type: application/json' \
-H "idempotency-key: $(uuidgen)" \
-d '{
"venue": "hyperliquid",
"symbol": "BTC.HL",
"side": "buy",
"type": "limit",
"qty": "0.01",
"price": "60000",
"timeInForce": "Gtc"
}'
Field Notes
venue Required. One of hyperliquid, aster, polymarket, kalshi, paper.
symbol Required, venue-suffixed (BTC.HL). From GET /api/v1/symbols/{venue}.
side buy / sell.
type market, limit, stop, stop_limit, take_profit.
qty Required. Decimal string preferred.
price Required for limit.
triggerPrice Required for stop, stop_limit, take_profit.
stopLimitPrice Required for stop_limit — the resting limit price, alongside triggerPrice. Omitting it is a 400 stopLimitPrice_required.
reduceOnly Never increases exposure.
timeInForce Gtc / Ioc / Alo.
leverage Checked at compose time against the effective per-venue cap.
accountId Optional — defaults to the credential’s active account. Set it to place on a specific owned account.
clientOrderId Your own correlation id, echoed back on the response and on the WS frames.

Sandbox orders go in as venue: "paper" against a paper account. GET /api/v1/venues is capability discovery — the adapters wired in this deploy and what each one supports. It is not this enum: b3 is listed there but compose rejects it (paper B3 orders go in as paper), and paper is never listed there.

The response carries the intent id. Subscribe to the Order-Intent-Changed topic on /ws/risk and match Order-Intent-Update frames by their intentId — they carry the venue order id, the last event, and the terminal state.

Endpoint Does
POST /api/v1/oms/cancel Cancel one working order by venueOrderId — the venue’s id, not the intent id. Read it from GET /api/v1/accounts/{id}/orders or the Open-Orders-Update frames.
POST /api/v1/oms/modify Replace a working order’s price, qty, or trigger by intentId. Resolves a new intent id.
POST /api/v1/oms/cancel-all Cancel every working order on the account.
POST /api/v1/oms/flatten Close every open position on the account.
POST /api/v1/oms/reverse Close a position and open the opposite side.
POST /api/v1/oms/chase Cancel-and-replace toward the touch.
Terminal window
curl -s https://api.troncharts.xyz/api/v1/oms/cancel \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-H "x-tenant-slug: $TC_TENANT_SLUG" \
-H "idempotency-key: $(uuidgen)" \
-d '{ "venueOrderId": "…" }'
await sdk.oms.modify({ intentId, newPrice: 59500 }, idempotencyKey)

Modify takes newPrice, newQty, newTriggerPrice, and newStopLimitPrice. Unlike compose, these are numbers only — a decimal string is rejected.

There is no inline bracket field on compose. Place the entry, then attach the OCO legs:

Endpoint Does
POST /api/v1/oms/brackets/attach Attach TP and/or SL to an entry by parentIntentId.
POST /api/v1/oms/brackets/attach-to-position Attach to an already-open position.
POST /api/v1/oms/brackets/modify Move an existing leg.
Terminal window
curl -s https://api.troncharts.xyz/api/v1/oms/brackets/attach \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-H "x-tenant-slug: $TC_TENANT_SLUG" \
-d '{ "parentIntentId": "…", "tpPrice": 64000, "slPrice": 58000 }'

At least one of tpPrice / slPrice must be set. When the parent is still unfilled the response carries staged: true — the legs arm on fill.

Some venues accept extras: asterTimeInForce, asterKind, clientId. They are ignored by venues that don’t use them, but read GET /api/v1/venues for what each adapter actually supports rather than sending them blind.

Pass leverage on the intent itself. It is validated at compose time against the effective per-venue cap, which comes from the account’s trading group — groups scope fee schedules, leverage caps, and venue/symbol allowlists. An intent above the cap is rejected at compose, before anything reaches the venue.