Skip to content

Subscription & Event Handling

The crypto trade event push uses a connect-to-subscribe model: once the client establishes a WebSocket connection and completes authentication, the server automatically pushes all crypto trade events for the authenticated user — no additional subscription request is required.

Message Identification

Upon receiving a push message, follow these two steps to determine the handling scenario:

Step 1: Read event_type  →  Determine the event category (order placed / filled / cancelled / expired)
Step 2: Read order_info.is_close  →  Determine whether this is a terminal state with no further updates
event_typeDescriptionorder_info.is_close
EVENT_NEWOrder placement succeededfalse — order is still active
EVENT_NEW_REJECTEDOrder placement failedtrue — terminal state
EVENT_FILL (partial fill)order_info.ord_status = PARTIAL_FILLEDfalse — remainder still open
EVENT_FILL (full fill)order_info.ord_status = FILLEDtrue — terminal state
EVENT_CANCELEDCancellation succeededtrue — terminal state
EVENT_EXPIREDOrder expiredtrue — terminal state

Event Coverage

After successful authentication, the client automatically receives all of the following event types with no ability to filter individual types:

Event TypeDescription
EVENT_NEWOrder placement succeeded
EVENT_NEW_REJECTEDOrder placement failed
EVENT_FILLFill event (partial and full fills)
EVENT_CANCELEDCancellation succeeded
EVENT_EXPIREDOrder expired

For the message structure and field descriptions of each event, see Data Format.

Account Scope

The server pushes events scoped to the authenticated user's accounts. The user_info.account_id field in each push message identifies the specific crypto account the event belongs to.


Scenario Details


Scenario 1: Order Placement Succeeded

Trigger: The system confirms the order has entered the order queue (status NEW).

Identification: event_type = EVENT_NEW

order_info characteristics:

  • ord_status = NEW
  • is_close = false — the order is still active; further fill or cancellation events will follow
  • cum_qty = "0" — no fills yet
  • avg_px = "0" — no fills yet

Recommended handling: Record the order as "pending fill" and display a waiting-for-fill UI.


Scenario 2: Order Placement Failed

Trigger: The order was rejected by the system (e.g. insufficient balance, invalid price, risk control block).

Identification: event_type = EVENT_NEW_REJECTED

order_info characteristics:

  • ord_status = REJECTED or FAILED
  • is_close = trueterminal state; this order has ended and no further events will be received
  • cum_qty = "0" — no fills

Recommended handling: Mark the order as failed and close its lifecycle.


Scenario 3: Partial Fill

Trigger: The order was partially matched; unfilled quantity remains.

Identification: event_type = EVENT_FILL, order_info.ord_status = PARTIAL_FILLED

order_info characteristics:

  • ord_status = PARTIAL_FILLED
  • is_close = falsenot terminal; further fill or cancellation events may follow
  • cum_qty — updated to the cumulative total fill quantity (including this fill)
  • avg_px — updated to the new average fill price

fill_infos[0] characteristics:

  • quantity — quantity filled in this event
  • price — fill price for this event
  • amount — fill amount for this event

Recommended handling: Accumulate fill details, update the order's filled quantity and average price, and display a "Partially Filled" status. Use fill_id for idempotency to avoid duplicate processing.


Scenario 4: Full Fill

Trigger: The order has been fully matched.

Identification: event_type = EVENT_FILL, order_info.ord_status = FILLED

order_info characteristics:

  • ord_status = FILLED
  • is_close = trueterminal state; the order is complete
  • cum_qty — equals the original order_qty (fully filled)
  • avg_px — final average fill price

Recommended handling: Record the last fill, mark the order as "Fully Filled", and close it — no further events expected.


Scenario 5: Cancellation Succeeded

Trigger: The system confirms the cancellation is complete (full cancel, or cancel after partial fill).

Identification: event_type = EVENT_CANCELED

order_info characteristics:

  • ord_status = CANCELED or CANCELLED_PART (cancelled after partial fill)
  • is_close = trueterminal state
  • cum_qty — cumulative filled quantity at the time of cancellation (greater than 0 if there were prior partial fills)
  • avg_px — average fill price at the time of cancellation

Recommended handling: Mark the order as "Cancelled". If cum_qty > "0", it was a partial fill then cancel — retain the filled portion record (ord_status = CANCELLED_PART).


Scenario 6: Order Expired

Trigger: The order exceeded its time in force (e.g. an IOC order that was not immediately fully filled, or an order that reached its expiry).

Identification: event_type = EVENT_EXPIRED

order_info characteristics:

  • ord_status = EXPIRED
  • is_close = trueterminal state
  • cum_qty — cumulative filled quantity at expiry (IOC orders may have had partial fills before expiry)
  • avg_px — average fill price at expiry

Recommended handling: Mark the order as "Expired". If cum_qty > "0", the IOC order had partial fills before expiry — retain the filled records.


Terminal State Quick Reference

order_info.is_close == true   →  Order has reached terminal state; no further events for this order
order_info.is_close == false  →  Order is still active; fill or cancellation events may follow
Scenariois_close
Order placement succeededfalse
Order placement failedtrue
Partial fillfalse
Full filltrue
Cancellation succeededtrue
Order expiredtrue

Idempotency Recommendations

FieldPurpose
event_idMessage-level deduplication to prevent duplicate processing from network replays
fill_infos[].fill_idFill-level deduplication to prevent double-counting

Consumers should use event_id or fill_id as a key for idempotency checks to avoid duplicate processing.

Timing Examples

Limit buy 0.1 BTC, partial fill then cancel

t1: event_type=EVENT_NEW
    → order_info.cum_qty="0", order_info.is_close=false
    → Order placement succeeded, order is live

t2: event_type=EVENT_FILL, order_info.ord_status=PARTIAL_FILLED
    → order_info.cum_qty="0.06", order_info.is_close=false
    → Partial fill 0.06 BTC, 0.04 BTC remaining

t3: event_type=EVENT_CANCELED, order_info.ord_status=CANCELLED_PART
    → order_info.cum_qty="0.06", order_info.is_close=true
    → Cancellation succeeded, final fill 0.06 BTC, remaining 0.04 BTC cancelled

Market order fully filled

t1: event_type=EVENT_NEW
    → Order placement succeeded

t2: event_type=EVENT_FILL, order_info.ord_status=FILLED
    → order_info.cum_qty=order_info.order_qty, order_info.is_close=true
    → Fully filled, order complete

Order placement failed

t1: event_type=EVENT_NEW_REJECTED
    → order_info.ord_status=REJECTED, order_info.is_close=true
    → Order placement failed, order complete

IOC order partial fill then expire

t1: event_type=EVENT_NEW
    → order_info.is_close=false
    → Order placement succeeded

t2: event_type=EVENT_FILL, order_info.ord_status=PARTIAL_FILLED
    → order_info.cum_qty="0.03", order_info.is_close=false
    → Partial fill 0.03 BTC

t3: event_type=EVENT_EXPIRED, order_info.ord_status=EXPIRED
    → order_info.cum_qty="0.03", order_info.is_close=true
    → Remaining quantity expired, final fill 0.03 BTC

Behavior Notes

No Replay of Historical Events

Trade events that occurred during a disconnection will not be replayed after reconnection. Use the following REST endpoints to retrieve historical orders or fills:

Recovery After Reconnection

After a disconnection and re-authentication, the server will automatically re-establish the push channel and resume pushing subsequent events.

Next Steps