# 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. ### Subscribe to the order topics first

   On an authenticated socket — see [Stream account and position
   updates](https://docs.troncharts.xyz/docs/recipes/stream-account-updates/) for the handshake. Four topics cover the
   whole lifecycle, and subscribing before you place is what makes it real-time.

   ```json
   { "type": "Subscribe",
     "topics": ["Order-Intent-Changed", "Order-Changed", "Fill", "Trade-Changed"] }
   ```
   ```ts
   import type { RiskTopic } from '@tronchartsxyz/api-client'

   // 'Fill' is live on the server but has not landed in the SDK's RiskTopic union yet.
   const topics = ['Order-Intent-Changed', 'Order-Changed', 'Trade-Changed', 'Fill'] as RiskTopic[]
   ws.send({ type: 'Subscribe', topics })
   ```
2. ### Place the order

   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.

   ```bash
   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"'"}'
   ```
   ```ts
   const { intentId } = await sdk.oms.composeIntent(
     { venue: 'paper', symbol: 'BTC.HL', side: 'buy', type: 'limit',
       qty: '0.01', price: '60000', clientOrderId: 'my-order-1', accountId },
     crypto.randomUUID(),
   )
   ```
3. ### Read the lifecycle off the frames

   `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:

   ```json
   { "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.

   :::note[Live venues need more than a tier]
   A `fullTrading` credential is enough on paper. On `hyperliquid` or `aster` the bearer path
   also requires a linked agent wallet, or the call is rejected `credential_missing_agent_wallet`
   before any frame is emitted. See [Order lifecycle & signing](https://docs.troncharts.xyz/docs/trading/order-lifecycle/).
   :::

4. ### Reconcile over REST when you need to

   `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.

   ```bash
   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](https://docs.troncharts.xyz/docs/recipes/place-your-first-order/) · [Order lifecycle & signing](https://docs.troncharts.xyz/docs/trading/order-lifecycle/) · [Risk channel](https://docs.troncharts.xyz/docs/realtime/risk/)