Orders Channel
User-specific order updates and trade matches
Overview
The orders channel provides real-time updates about your orders and trade executions. You'll receive notifications when orders are created, filled, partially filled, cancelled, or when any state changes occur.
Channel: orders
Authentication: Required
Product: Not applicable (all products included)
Subscribe
You must authenticate before subscribing to the orders channel. See Authentication for details.
Request:
{
"op": "sub",
"channel": "orders"
}Friendly format:
sub ordersParameters:
op(string, required) - Must be"sub"channel(string, required) - Must be"orders"
Note: No product parameter needed. You'll receive updates for all your orders across all products.
Responses
Subscription Confirmation
Upon successful subscription:
{
"channel": "orders",
"type": "subscribed"
}Snapshot Message
Immediately after subscription, you'll receive a snapshot of all your non-done orders:
{
"channel": "orders",
"type": "snapshot",
"data": [
{
"id": "0x01234...",
"client_order_id": "my-order-123",
"user_id": "1000004",
"product_id": "BTC-VND",
"side": "buy",
"type": "limit",
"time_in_force": "GTC",
"post_only": false,
"price": "3100000000",
"size": "0.1",
"filled_size": "0.05",
"status": "open",
"created_at": "1698765432000000000",
"updated_at": "1698765433000000000",
"trades": []
}
],
"timestamp": "1698765434000000000",
"gsn": 12345678
}Update Messages
After the snapshot, you'll receive updates when your orders change:
{
"channel": "orders",
"type": "update",
"data": [
{
"id": "0x01234...",
"client_order_id": "my-order-123",
"user_id": "1000004",
"product_id": "BTC-VND",
"side": "buy",
"type": "limit",
"time_in_force": "GTC",
"post_only": false,
"price": "3100000000",
"size": "0.1",
"filled_size": "0.075",
"status": "open",
"created_at": "1698765432000000000",
"updated_at": "1698765435000000000",
"trades": [
{
"id": "0xabc...",
"price": "3100000000",
"size": "0.025",
"liquidity_indicator": "MAKER",
"time": "1698765435000000000",
"fee_asset": "VND",
"fee_amount": "7750"
}
]
}
],
"timestamp": "1698765435000000000",
"gsn": 12345679
}Data Structure
Order Object
interface Order {
id: string; // Unique order identifier
client_order_id?: string; // Your custom order ID
user_id: string; // Your user ID
product_id: string; // Trading pair
side: "buy" | "sell"; // Order side
type: "limit" | "market"; // Order type
time_in_force: "GTC" | "IOC" | "FOK"; // Time in force
post_only: boolean; // Post-only flag
price: string; // Order price
size: string; // Order size
filled_size: string; // Amount filled
status: OrderStatus; // Current status
created_at: string; // Creation timestamp (nanoseconds)
updated_at: string; // Last update timestamp (nanoseconds)
cancel_requested_at?: string; // Cancel request timestamp
trades: Trade[]; // Associated trades
}
type OrderStatus =
| "pending" // Order received, not yet processed
| "accepted" // Order accepted by matching engine
| "open" // Active order on orderbook
| "filled" // Completely filled
| "cancelled" // Cancelled
| "rejected"; // Rejected
interface Trade {
id: string; // Trade (match) ID
price: string; // Execution price
size: string; // Execution size
liquidity_indicator: "MAKER" | "TAKER"; // Your role
time: string; // Execution time (nanoseconds)
fee_asset: string; // Fee currency
fee_amount: string; // Fee charged
}Order Lifecycle Events
1. Order Created
When you create a new order:
{
"channel": "orders",
"type": "update",
"data": [{
"id": "0x01234...",
"status": "pending",
"filled_size": "0",
"trades": []
}],
"gsn": 12345680
}2. Order Accepted
When the matching engine accepts your order:
{
"channel": "orders",
"type": "update",
"data": [{
"id": "0x01234...",
"status": "open",
"filled_size": "0",
"trades": []
}],
"gsn": 12345681
}3. Partial Fill
When your order is partially filled:
{
"channel": "orders",
"type": "update",
"data": [{
"id": "0x01234...",
"status": "open",
"size": "0.1",
"filled_size": "0.03",
"trades": [
{
"id": "0xabc...",
"price": "3100000000",
"size": "0.03",
"liquidity_indicator": "MAKER",
"time": "1698765435000000000",
"fee_asset": "VND",
"fee_amount": "9300"
}
]
}],
"gsn": 12345682
}4. Complete Fill
When your order is completely filled:
{
"channel": "orders",
"type": "update",
"data": [{
"id": "0x01234...",
"status": "filled",
"size": "0.1",
"filled_size": "0.1",
"trades": [...]
}],
"gsn": 12345683
}5. Order Cancelled
When your order is cancelled:
{
"channel": "orders",
"type": "update",
"data": [{
"id": "0x01234...",
"status": "cancelled",
"cancel_requested_at": "1698765440000000000"
}],
"gsn": 12345684
}Example: Order Tracker
const WebSocket = require('ws');
class OrderTracker {
constructor() {
this.orders = new Map();
}
handleMessage(message) {
if (message.type === 'snapshot') {
// Initialize with snapshot
message.data.forEach(order => {
this.orders.set(order.id, order);
});
console.log(`Loaded ${this.orders.size} active orders`);
} else if (message.type === 'update') {
// Process updates
message.data.forEach(order => {
const existing = this.orders.get(order.id);
if (order.status === 'filled' || order.status === 'cancelled') {
// Remove done orders
this.orders.delete(order.id);
this.logOrderComplete(order);
} else {
// Update or add order
this.orders.set(order.id, order);
if (existing) {
this.logOrderUpdate(existing, order);
} else {
this.logOrderCreated(order);
}
}
});
}
}
logOrderCreated(order) {
console.log(`📝 New Order: ${order.side.toUpperCase()} ${order.size} ${order.product_id} @ ${order.price}`);
console.log(` ID: ${order.id}`);
}
logOrderUpdate(oldOrder, newOrder) {
if (newOrder.filled_size !== oldOrder.filled_size) {
const fillSize = parseFloat(newOrder.filled_size) - parseFloat(oldOrder.filled_size);
console.log(`✅ Fill: ${fillSize} ${newOrder.product_id} @ ${newOrder.trades[newOrder.trades.length - 1].price}`);
console.log(` Order ID: ${newOrder.id}`);
console.log(` Progress: ${newOrder.filled_size}/${newOrder.size}`);
}
}
logOrderComplete(order) {
if (order.status === 'filled') {
console.log(`✅ Order Filled: ${order.id}`);
console.log(` ${order.side.toUpperCase()} ${order.filled_size} ${order.product_id}`);
// Calculate total fees
const totalFees = order.trades.reduce((sum, trade) => {
return sum + parseFloat(trade.fee_amount);
}, 0);
console.log(` Total Fees: ${totalFees} ${order.trades[0]?.fee_asset || 'VND'}`);
} else if (order.status === 'cancelled') {
console.log(`❌ Order Cancelled: ${order.id}`);
console.log(` Filled: ${order.filled_size}/${order.size}`);
}
}
getActiveOrders() {
return Array.from(this.orders.values());
}
getOrdersByProduct(productId) {
return this.getActiveOrders().filter(o => o.product_id === productId);
}
}
// Usage
const tracker = new OrderTracker();
ws.on('open', async () => {
// Authenticate first
await authenticate(ws);
// Subscribe to orders
ws.send(JSON.stringify({
op: 'sub',
channel: 'orders'
}));
});
ws.on('message', (data) => {
const message = JSON.parse(data);
if (message.channel === 'orders') {
tracker.handleMessage(message);
// Display active orders
const active = tracker.getActiveOrders();
console.log(`\nActive Orders: ${active.length}`);
}
});Unsubscribe
To stop receiving order updates:
Request:
{
"op": "unsub",
"channel": "orders"
}Response:
{
"type": "unsubscribed",
"channel": "orders"
}Important Notes
- Authentication Required - You must authenticate before subscribing
- All Products - The channel includes orders from all trading pairs
- Done Orders Excluded - Snapshot only includes non-done orders (pending, accepted, open)
- GSN Tracking - Use Global Sequence Number (GSN) to ensure message ordering
- Trades Array - Only includes trades from the current update, not all historical trades
- Nanosecond Timestamps - All timestamps are in nanoseconds since Unix epoch
Use Cases
- Order Management UI - Display user's active orders
- Trade Notifications - Alert users when orders are filled
- Position Tracking - Monitor order fills to track positions
- Execution Analytics - Analyze fill prices and fees
- Automated Trading - React to order state changes programmatically
Best Practices
- Maintain State - Keep a local map of active orders
- Handle Reconnections - Re-subscribe and process snapshot after reconnecting
- Use GSN - Track GSN to detect missed messages
- Filter by Product - Filter orders client-side if you only care about specific products
- Calculate PnL - Use trade data to calculate profit/loss and fees
Related Channels
- Portfolio Channel - Account balances affected by orders
- Trades Channel - Public trade feed
- Trading Operations - Create and cancel orders via WebSocket