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 report_type  →  Determine the event category (placement / fill / cancellation / expiry)
Step 2: Read order.is_close  →  Determine whether this is a terminal state with no further updates
report_typeDescriptionorder.is_close
1 (new_rpt.result=0)Order placement succeededfalse — order is still active
1 (new_rpt.result≠0)Order placement failedtrue — terminal state
4 (fill_rpt.fill_status=1)Partial fillfalse — remainder still open
4 (fill_rpt.fill_status=2)Full filltrue — terminal state
3 (cancel_rpt.result=0)Cancellation succeededtrue — terminal state
5Order expiredtrue — terminal state

Event Coverage

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

report_typeDescription
1Order placement report (success and failure)
3Order cancellation report
4Fill report (partial and full fills)
5Order expiry report

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


Scenario Details


Scenario 1: Order Placement Succeeded

Trigger: The system confirms the order has entered the order queue.

Identification: report_type=1, new_rpt.result=0

order characteristics:

  • 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: report_type=1, new_rpt.result≠0

order characteristics:

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

new_rpt characteristics:

  • result — non-zero error code
  • err_msg — failure reason

Recommended handling: Mark the order as failed, display new_rpt.err_msg, and close its lifecycle.


Scenario 3: Partial Fill

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

Identification: report_type=4, fill_rpt.fill_status=1

order characteristics:

  • 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_rpt characteristics:

  • last_qty — quantity filled in this event
  • last_px — fill price for this event
  • last_amount — fill amount for this event
  • leave_qty — remaining unfilled quantity

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


Scenario 4: Full Fill

Trigger: The order has been fully matched.

Identification: report_type=4, fill_rpt.fill_status=2

order characteristics:

  • 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: report_type=3, cancel_rpt.result=0

order characteristics:

  • 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 order.cum_qty > "0", it was a partial fill then cancel — retain the filled portion record.


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: report_type=5

order characteristics:

  • 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 order.cum_qty > "0", the IOC order had partial fills before expiry — retain the filled records.


Terminal State Quick Reference

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

Idempotency Recommendations

FieldPurpose
report_idMessage-level deduplication to prevent duplicate processing from network replays
fill_rpt.fill_idFill-level deduplication to prevent double-counting

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

Timing Examples

Limit buy 0.1 BTC, partial fill then cancel

t1: report_type=1, new_rpt.result=0
    → order.cum_qty="0", order.is_close=false
    → Order placement succeeded, order is live

t2: report_type=4, fill_rpt.fill_status=1
    → order.cum_qty="0.06", order.is_close=false
    → Partial fill 0.06 BTC, fill_rpt.leave_qty="0.04"

t3: report_type=3, cancel_rpt.result=0
    → order.cum_qty="0.06", order.is_close=true
    → Cancellation succeeded, final fill 0.06 BTC, remaining 0.04 BTC cancelled

Market order fully filled

t1: report_type=1, new_rpt.result=0
    → Order placement succeeded

t2: report_type=4, fill_rpt.fill_status=2
    → order.cum_qty=order.order_qty, order.is_close=true
    → Fully filled, order complete

Order placement failed

t1: report_type=1, new_rpt.result≠0
    → order.is_close=true, new_rpt.err_msg="<failure reason>"
    → Order placement failed, order complete

IOC order partial fill then expire

t1: report_type=1, new_rpt.result=0
    → order.is_close=false
    → Order placement succeeded

t2: report_type=4, fill_rpt.fill_status=1
    → order.cum_qty="0.03", order.is_close=false
    → Partial fill 0.03 BTC

t3: report_type=5
    → order.cum_qty="0.03", order.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