Skip to content

Follow an order from placement to fill

POST /api/v1/oms/intents answers 201 { intentId } and says nothing about execution — the verdict streams over /ws/risk. Subscribe before you place and you watch the order composed, dispatched, and filled without polling anything.

  1. On an authenticated socket — see Stream account and position updates for the handshake. Four topics cover the whole lifecycle, and subscribing before you place is what makes it real-time.

    { "type": "Subscribe",
    "topics": ["Order-Intent-Changed", "Order-Changed", "Fill", "Trade-Changed"] }
  2. Send clientOrderId — your own correlation id, echoed back on the 201 and on the Order-Intent-Update and Open-Orders-Update frames, so you can adopt the order before its intent id reaches you. Idempotency-Key (8–200 characters) makes a retry replay the cached response instead of placing twice.

    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":"paper","symbol":"BTC.HL","side":"buy","type":"limit","qty":"0.01",
    "price":"60000","clientOrderId":"my-order-1","accountId":"'"$ACCOUNT_ID"'"}'
  3. Order-Intent lands first, carrying the composed actionToSign. Order-Intent-Update follows on every transition — intent_pending, signed_pending_dispatch, dispatched, acknowledged, partially_filled, filled, and the terminal canceled / rejected / expired — and binds venueOrderId once the venue answers. Order-Update restates the same thing in the external vocabulary, keyed on the intent id:

    { "type": "Order-Update", "orderId": "3f2a…", "venueOrderId": "88214417",
    "venue": "paper", "symbol": "BTC.HL", "side": "long", "orderType": "limit",
    "status": "partially_filled", "qty": "0.01", "filledQty": "0.004",
    "price": "60000", "updatedAt": "2026-08-04T12:00:00.000Z" }

    Fill fires once per execution and is never coalesced, so its qty and price are that execution’s own and summing them is safe. Trade-Update fires only on a closed round trip — it never fires on an entry.

  4. GET /api/v1/oms/intents/{id} is the authoritative read, scoped to the credential’s own account — an intent belonging to another account is 404. That includes one you placed with an explicit accountId for a paper child, so read it back with the credential that owns that account. GET /api/v1/oms/intents returns the last 50.

    Discovery advertises GET /api/v1/orders/{id}. That path is not mounted; use the OMS one.

    Terminal window
    curl -s https://api.troncharts.xyz/api/v1/oms/intents/$INTENT_ID \
    -H "authorization: Bearer $TOKEN" \
    -H "x-tenant-slug: $TC_TENANT_SLUG"

Next: Place your first order · Order lifecycle & signing · Risk channel