Get Open Orders (WebSocket)
Retrieve all currently open orders for the authenticated subaccount through the WebSocket connection. This method returns only active orders (not filled or cancelled), with optional filtering by symbol and pagination.
Request-Response vs Subscriptions
This method provides on-demand snapshots of open order data. For real-time updates when orders change, use SubAccount Updates Subscription.
| Method | Purpose | When to Use |
|---|---|---|
getOpenOrders | Active orders snapshot | Initial load, order management, UI refresh |
| Order Updates Subscription | Real-time notifications | Live UI updates, event handling |
Endpoint
ws.send() wss://api.synthetix.io/v1/ws/tradeRequest
Request Format
{
"id": "openorders-1",
"method": "post",
"params": {
"action": "getOpenOrders",
"subAccountId": "1867542890123456789",
"symbol": "BTC-USDT",
"limit": 50,
"offset": 0,
"expiresAfter": 1704067500,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}
}Parameters
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client-generated unique request identifier |
method | string | Yes | Must be "post" |
params | object | Yes | Contains all parameters for the request |
Params Object
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "getOpenOrders" |
subAccountId | string | Yes | Subaccount identifier |
symbol | string | No | Filter orders by specific market symbol (e.g., "BTC-USDT") |
limit | integer | No | Maximum number of orders to return (default: 50) |
offset | integer | No | Number of orders to skip for pagination (default: 0) |
expiresAfter | integer | No | Optional expiration timestamp in milliseconds |
signature | object | Yes | EIP-712 signature using SubAccountAction type |
- This endpoint uses
SubAccountActionEIP-712 type (no nonce required, onlyexpiresAfteris optional) - Returns only active orders (placed, partially filled)
- Does not include filled, cancelled, or rejected orders
EIP-712 Signature
const domain = {
name: "Synthetix",
version: "1",
chainId: 1,
verifyingContract: "0x0000000000000000000000000000000000000000"
};
const types = {
SubAccountAction: [
{ name: "subAccountId", type: "uint256" },
{ name: "action", type: "string" },
{ name: "expiresAfter", type: "uint256" }
]
};
const message = {
subAccountId: "1867542890123456789",
action: "getOpenOrders",
expiresAfter: 0
};
const signature = await signer._signTypedData(domain, types, message);Response Format
Success Response
{
"id": "openorders-1",
"status": 200,
"result": {
"status": "success",
"response": [
{
"order": {
"venueId": "1958787130134106112",
"clientId": "cli-1958787130134106112"
},
"orderId": "1958787130134106112",
"symbol": "BTC-USDT",
"side": "buy",
"type": "LIMIT",
"quantity": "0.1",
"price": "45000.00",
"triggerPrice": "",
"triggerPriceType": "",
"timeInForce": "GTC",
"reduceOnly": false,
"postOnly": false,
"closePosition": false,
"createdTime": 1755846234000,
"updatedTime": 1755846234000,
"filledQuantity": "0.0",
"takeProfitOrder": {
"venueId": "1958787130134106115",
"clientId": "cli-1958787130134106115"
},
"takeProfitOrderId": "1958787130134106115",
"stopLossOrder": {
"venueId": "1958787130134106116",
"clientId": "cli-1958787130134106116"
},
"stopLossOrderId": "1958787130134106116"
},
{
"order": {
"venueId": "1958787130134106113",
"clientId": "cli-1958787130134106113"
},
"orderId": "1958787130134106113",
"symbol": "ETH-USDT",
"side": "sell",
"type": "LIMIT",
"quantity": "2.0",
"price": "2800.00",
"triggerPrice": "",
"triggerPriceType": "",
"timeInForce": "GTC",
"reduceOnly": false,
"postOnly": true,
"closePosition": false,
"createdTime": 1755846235000,
"updatedTime": 1755846235000,
"filledQuantity": "0.5",
"takeProfitOrderId": "",
"stopLossOrderId": ""
}
]
}
}Empty Result
{
"id": "openorders-1",
"status": 200,
"result": {
"status": "success",
"response": []
}
}Error Response
{
"id": "openorders-1",
"status": 400,
"result": null,
"error": {
"code": 400,
"message": "Failed to get open orders"
}
}Order Object Fields
| Field | Type | Description |
|---|---|---|
order | object | Canonical order identifier object |
order.venueId | string | Canonical venue-generated order identifier |
order.clientId | string | Optional client-provided order identifier |
orderId | string | Deprecated legacy order identifier |
symbol | string | Trading pair symbol (e.g., "BTC-USDT") |
side | string | Order side: "buy" or "sell" |
type | string | Order type (e.g., "LIMIT", "MARKET") |
quantity | string | Total order quantity |
price | string | Order price (empty for market orders) |
triggerPrice | string | Trigger price for conditional orders |
triggerPriceType | string | Trigger price type: "mark", "last", or "index" |
timeInForce | string | Time in force: "GTC", "IOC", or "FOK" |
reduceOnly | boolean | Whether order can only reduce position |
postOnly | boolean | Whether order must be maker (no immediate match) |
closePosition | boolean | Whether order closes entire position |
createdTime | integer | Order creation timestamp (Unix milliseconds) |
updatedTime | integer | Last update timestamp (Unix milliseconds) |
filledQuantity | string | Quantity that has been filled |
takeProfitOrder | object | Canonical linked take-profit order identifier object |
takeProfitOrderId | string | Deprecated linked take-profit venue ID |
stopLossOrder | object | Canonical linked stop-loss order identifier object |
stopLossOrderId | string | Deprecated linked stop-loss venue ID |
Migration Note: Use order.venueId as canonical. orderId, takeProfitOrderId, and stopLossOrderId are deprecated compatibility fields.
Note on TP/SL Fields: When orders are placed with normalTpsl or positionTpsl grouping, the entry order will contain takeProfitOrder and stopLossOrder objects linking to associated TP/SL trigger orders.
Code Examples
Get All Open Orders
{
"id": "openorders-all",
"method": "post",
"params": {
"action": "getOpenOrders",
"subAccountId": "1867542890123456789",
"expiresAfter": 1704067500,
"signature": { "v": 28, "r": "0x...", "s": "0x..." }
}
}Get Open Orders for Specific Market
{
"id": "openorders-btc",
"method": "post",
"params": {
"action": "getOpenOrders",
"subAccountId": "1867542890123456789",
"symbol": "BTC-USDT",
"expiresAfter": 1704067500,
"signature": { "v": 28, "r": "0x...", "s": "0x..." }
}
}Get Open Orders with Pagination
{
"id": "openorders-paginated",
"method": "post",
"params": {
"action": "getOpenOrders",
"subAccountId": "1867542890123456789",
"limit": 100,
"offset": 0,
"expiresAfter": 1704067500,
"signature": { "v": 28, "r": "0x...", "s": "0x..." }
}
}Implementation Example
class OpenOrdersQuery {
constructor(ws) {
this.ws = ws;
this.pendingRequests = new Map();
}
async getOpenOrders(options = {}) {
const {
subAccountId,
symbol = null,
limit = 50,
offset = 0,
expiresAfter = 0,
signature
} = options;
const request = {
id: `openorders-${Date.now()}`,
method: "post",
params: {
action: "getOpenOrders",
subAccountId: subAccountId.toString(),
expiresAfter,
signature
}
};
// Add optional filters
if (symbol) request.params.symbol = symbol;
if (limit) request.params.limit = limit;
if (offset) request.params.offset = offset;
return this.sendRequest(request);
}
sendRequest(request) {
return new Promise((resolve, reject) => {
this.pendingRequests.set(request.id, { resolve, reject });
this.ws.send(JSON.stringify(request));
setTimeout(() => {
if (this.pendingRequests.has(request.id)) {
this.pendingRequests.delete(request.id);
reject(new Error('Request timeout'));
}
}, 10000);
});
}
handleResponse(response) {
const pending = this.pendingRequests.get(response.id);
if (pending) {
this.pendingRequests.delete(response.id);
if (response.error) {
pending.reject(new Error(response.error.message));
} else {
pending.resolve(response.result.response);
}
}
}
}
// Usage
const query = new OpenOrdersQuery(ws);
const openOrders = await query.getOpenOrders({
subAccountId: "1867542890123456789",
symbol: "BTC-USDT",
signature: { v: 28, r: "0x...", s: "0x..." }
});
console.log(`Found ${openOrders.length} open orders`);Comparison with getOrderHistory
| Feature | getOpenOrders | getOrderHistory |
|---|---|---|
| Purpose | Currently active orders only | All orders with comprehensive history |
| Time Filtering | Not supported | fromTime/toTime range |
| Status Filtering | Not supported (active only) | Multiple status filters |
| Default Scope | Active orders only | All orders (any status) |
| Use Case | Real-time order management | Historical analysis and reporting |
| Performance | Faster (smaller dataset) | May be slower with large history |
Integration with Subscriptions
Combine request-response queries with subscriptions for complete order management:
class OrderManager {
constructor(ws, subAccountId) {
this.ws = ws;
this.subAccountId = subAccountId;
this.openOrders = new Map();
}
async initialize() {
// 1. Get initial open orders
const request = {
id: "init-openorders",
method: "post",
params: {
action: "getOpenOrders",
subAccountId: this.subAccountId,
expiresAfter: 0,
signature: { /* ... */ }
}
};
this.ws.send(JSON.stringify(request));
// 2. Subscribe to real-time updates
this.ws.send(JSON.stringify({
id: "subscribe-orders",
method: "subscribe",
params: {
type: "subAccountUpdates",
subAccountId: this.subAccountId
}
}));
}
handleOrderUpdate(update) {
const { eventType } = update.data;
const orderKey = update.data.order?.venueId || update.data.orderId;
if (eventType === 'cancelled' || eventType === 'filled') {
this.openOrders.delete(orderKey);
} else if (eventType === 'placed' || eventType === 'partially_filled') {
this.openOrders.set(orderKey, update.data);
}
}
}Validation Rules
- Subaccount ID must be valid and accessible
- Limit must be between 1 and 100 (default: 50)
- Offset must be non-negative (default: 0)
- Symbol must be a valid trading pair (if specified)
| Error Code | Description | Retryable |
|---|---|---|
UNAUTHORIZED | EIP-712 signature validation failed | No |
VALIDATION_ERROR | Request validation failed | No |
MISSING_REQUIRED_FIELD | Required field is missing | No |
INVALID_FORMAT | Field format is invalid | No |
INVALID_VALUE | Invalid parameter value | No |
RATE_LIMIT_EXCEEDED | Too many requests in time window | Yes |
INSUFFICIENT_MARGIN | Not enough margin for trade | No |
ORDER_NOT_FOUND | Order does not exist | No |
OPERATION_TIMEOUT | Operation timed out | Yes |
Next Steps
- SubAccount Updates Subscription - Real-time order change notifications
- Get Order History - Query historical orders with filters
- Cancel Orders - Cancel open orders
- REST Alternative - REST API comparison