Skip to content

SubAccount Updates

Consolidated real-time stream of all subaccount activity including orders, trades, margin updates, and liquidations. This subscription replaces the need to subscribe to multiple separate streams.

Endpoint

Public subscriptions (candles, marketPrices, orderbook):

wss://papi.synthetix.io/v1/ws/info

Private subscriptions (subAccountUpdates - requires authentication):

wss://papi.synthetix.io/v1/ws/trade

Subscription Request

Subscribe to SubAccount Updates

{
  "id": "sub-1",
  "method": "subscribe",
  "params": {
    "type": "subAccountUpdates",
    "sub_account_id": "1867542890123456789"
  }
}

Request Parameters

ParameterTypeRequiredDescription
idstringYesClient-generated unique request identifier
methodstringYesMust be "subscribe"
params.typestringYesMust be "subAccountUpdates"
params.sub_account_idstringYesSubaccount ID to receive events for

Event Types

Event TypeDescription
orderPlacedOrder successfully placed on orderbook
orderFilledOrder fully executed
orderPartiallyFilledOrder partially executed
orderCancelledOrder cancelled by user or system
orderModifiedOrder price or quantity modified
orderRejectedOrder rejected due to validation failure
tradeTrade execution with fill details
marginUpdateAccount margin/balance state updated
liquidationPosition liquidated due to insufficient margin
fundingFunding payment for open positions
wickInsurancePositionIncreasedWick insurance position size increased
wickInsuranceProtectionActivatedWick insurance protection activated
wickInsuranceProtectionCompletedWick insurance protection completed

User Event Messages

Order Placed

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "orderPlaced",
    "subAccountId": "1867542890123456789",
    "orderId": "1948058938469519360",
    "symbol": "BTC-USDT",
    "timestamp": 1704067200000,
    "side": "buy",
    "orderType": "limit",
    "price": "50000.00",
    "quantity": "0.1",
    "filledQuantity": "0",
    "remainingQuantity": "0.1",
    "direction": "long",
    "status": "OrderStatePlaced",
    "createdAt": 1704067199998,
    "placedAt": 1704067200000,
    "updatedAt": 1704067200000,
    "clientOrderId": "0x1234567890abcdef1234567890abcdef"
  }
}

Order Filled

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "orderFilled",
    "subAccountId": "1867542890123456789",
    "orderId": "1948058938469519360",
    "symbol": "BTC-USDT",
    "timestamp": 1704067210000,
    "side": "buy",
    "orderType": "limit",
    "price": "50000.00",
    "quantity": "0.1",
    "filledQuantity": "0.1",
    "remainingQuantity": "0",
    "direction": "long",
    "status": "OrderStateFilled",
    "createdAt": 1704067199998,
    "placedAt": 1704067200000,
    "updatedAt": 1704067210000,
    "clientOrderId": "0x1234567890abcdef1234567890abcdef"
  }
}

Order Cancelled

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "orderCancelled",
    "subAccountId": "1867542890123456789",
    "orderId": "1948058938469519360",
    "symbol": "BTC-USDT",
    "timestamp": 1704067220000,
    "side": "buy",
    "orderType": "limit",
    "price": "50000.00",
    "quantity": "0.1",
    "filledQuantity": "0",
    "remainingQuantity": "0.1",
    "direction": "long",
    "status": "OrderStateCancelled",
    "cancelledAt": 1704067220000,
    "createdAt": 1704067199998,
    "placedAt": 1704067200000,
    "updatedAt": 1704067220000,
    "clientOrderId": "0x1234567890abcdef1234567890abcdef"
  }
}

Order Rejected

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "orderRejected",
    "subAccountId": "1867542890123456789",
    "orderId": "1948058938469519360",
    "symbol": "BTC-USDT",
    "timestamp": 1704067200000,
    "side": "buy",
    "orderType": "limit",
    "price": "50000.00",
    "quantity": "0.1",
    "direction": "long",
    "status": "OrderStateRejected",
    "reason": "Insufficient margin",
    "createdAt": 1704067199998,
    "updatedAt": 1704067200000,
    "clientOrderId": "0x1234567890abcdef1234567890abcdef"
  }
}

Trade Execution

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "trade",
    "tradeId": "123456790",
    "orderId": "1948058938469519360",
    "subAccountId": "1867542890123456789",
    "symbol": "BTC-USDT",
    "side": "buy",
    "price": "50010.00",
    "quantity": "0.1",
    "fee": "5.00",
    "feeRate": "0.001",
    "realizedPnl": "0.00",
    "isTaker": true,
    "timestamp": 1704067230000,
    "tradedAt": 1704067230000,
    "position": {
      "side": "long",
      "size": "0.1",
      "entryPrice": "50010.00",
      "unrealizedPnl": "0.00"
    }
  }
}

Margin Update

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "marginUpdate",
    "subAccountId": "1867542890123456789",
    "accountValue": "10000.00",
    "availableMargin": "8500.00",
    "totalUnrealizedPnl": "125.50",
    "maintenanceMargin": "750.00",
    "initialMargin": "1500.00",
    "withdrawable": "8500.00",
    "adjustedAccountValue": "9875.50",
    "timestamp": 1704067800000,
    "position": {
      "symbol": "BTC-USDT",
      "upnl": "125.50",
      "initialMargin": "750.00",
      "maintenanceMargin": "375.00",
      "markPrice": "50125.50"
    }
  }
}

Liquidation

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "liquidation",
    "tradeId": "123456791",
    "subAccountId": "1867542890123456789",
    "symbol": "BTC-USDT",
    "side": "sell",
    "price": "40000.00",
    "quantity": "0.2",
    "realizedPnl": "-2000.00",
    "fee": "20.00",
    "feeRate": "0.005",
    "liquidationPrice": "40000.00",
    "timestamp": 1704067900000,
    "position": {
      "side": null,
      "size": "0.0",
      "entryPrice": "0.0",
      "unrealizedPnl": "0.00"
    }
  }
}

Funding

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "funding",
    "paymentId": "fp_1958787130134106112",
    "subAccountId": "1867542890123456789",
    "symbol": "BTC-USDT",
    "positionSize": "0.2",
    "fundingRate": "0.0000125",
    "payment": "-3.625312",
    "markPrice": "50000.00",
    "timestamp": 1704067800000
  }
}

Wick Insurance - Position Increased

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "wickInsurancePositionIncreased",
    "subAccountId": "1867542890123456789",
    "symbol": "BTC-USDT",
    "oldQuantity": "0.1",
    "newQuantity": "0.2",
    "timestamp": 1704067200000
  }
}

Wick Insurance - Protection Activated

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "wickInsuranceProtectionActivated",
    "subAccountId": "1867542890123456789",
    "expiredTime": 1704067800000,
    "timestamp": 1704067200000
  }
}

Wick Insurance - Protection Completed

{
  "method": "subAccountEvent",
  "data": {
    "eventType": "wickInsuranceProtectionCompleted",
    "subAccountId": "1867542890123456789",
    "protectionId": "12345",
    "expiredTime": 1704067800000,
    "timestamp": 1704067200000
  }
}

Event Data Fields

Common Fields

FieldTypeDescription
eventTypestringType of event
subAccountIdstringAffected subaccount
timestampintegerEvent timestamp in milliseconds
symbolstringTrading pair (when applicable)

Order Fields

FieldTypeDescription
orderIdstringUnique order identifier
clientOrderIdstringClient-provided order ID
sidestringOrder side: "buy" or "sell"
orderTypestringOrder type: "limit", "market", "stopLoss", "takeProfit"
pricestringOrder price (empty for market orders)
quantitystringTotal order quantity
filledQuantitystringAmount already filled
remainingQuantitystringAmount remaining to fill
directionstringPosition direction: "long" or "short"
statusstringOrder status (see Order Status Values below)
reasonstringCancellation/rejection reason
createdAtintegerOrder creation timestamp in milliseconds
placedAtintegerOrder placement timestamp in milliseconds
cancelledAtintegerOrder cancellation timestamp in milliseconds (cancelled orders only)
updatedAtintegerOrder last update timestamp in milliseconds

Order Status Values

StatusDescription
OrderStatePlacedOrder placed on orderbook
OrderStatePartiallyFilledOrder partially executed
OrderStateFilledOrder fully executed
OrderStateCancelledOrder cancelled
OrderStateRejectedOrder rejected
OrderStateModifyOrder modification in progress
OrderStateModifiedOrder successfully modified

Trade Fields

FieldTypeDescription
tradeIdstringUnique trade identifier
orderIdstringOrder ID that generated this trade
feestringTrading fee amount
feeRatestringFee rate applied
realizedPnlstringRealized P&L from trade
isTakerbooleanWhether this was a taker trade
timestampintegerEvent timestamp in milliseconds (deprecated, use tradedAt)
tradedAtintegerTrade execution timestamp in milliseconds
liquidationPricestringLiquidation price (liquidations only)

Position Snapshot (in Trade Events)

FieldTypeDescription
position.sidestring | nullPosition side after event
position.sizestringPosition size after event
position.entryPricestringAverage entry price
position.unrealizedPnlstringCurrent unrealized P&L

Margin Update Fields

FieldTypeDescription
accountValuestringTotal account value including unrealized P&L
availableMarginstringMargin available for new positions
totalUnrealizedPnlstringSum of unrealized P&L across all positions
maintenanceMarginstringRequired margin to maintain positions
initialMarginstringRequired margin to open positions
withdrawablestringAmount available for withdrawal
adjustedAccountValuestringAccount value adjusted for risk
positionobjectOptional position that triggered update
position.symbolstringMarket symbol
position.upnlstringPosition unrealized P&L
position.initialMarginstringPosition initial margin requirement
position.maintenanceMarginstringPosition maintenance margin requirement
position.markPricestringCurrent mark price

Funding Fields

FieldTypeDescription
paymentIdstringUnique funding payment identifier
symbolstringTrading pair
positionSizestringPosition size at time of funding
fundingRatestringFunding rate applied
paymentstringFunding payment amount (negative = paid, positive = received)
markPricestringMark price at time of funding

Wick Insurance Fields

FieldTypeDescription
symbolstringTrading pair (position increased only)
oldQuantitystringPrevious position size (position increased only)
newQuantitystringNew position size (position increased only)
expiredTimeintegerProtection expiry time in milliseconds (protection events)
protectionIdstringProtection identifier (protection completed only)

Implementation Example

// Subscribe to all subaccount updates
const subscription = {
  id: "sub-1",
  method: "subscribe",
  params: {
    type: "subAccountUpdates",
    sub_account_id: "1867542890123456789"
  }
};
 
ws.send(JSON.stringify(subscription));
 
// Handle subaccount events
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
 
  if (message.method === "subAccountEvent") {
    const { eventType, symbol } = message.data;
 
    switch (eventType) {
      case "orderPlaced":
        console.log(`Order placed: ${message.data.orderId}`);
        updateOrdersUI(message.data);
        break;
 
      case "orderFilled":
      case "orderPartiallyFilled":
        console.log(`Order ${eventType}: ${message.data.orderId}`);
        updateOrdersUI(message.data);
        break;
 
      case "orderCancelled":
        console.log(`Order cancelled: ${message.data.orderId}`);
        updateOrdersUI(message.data);
        break;
 
      case "trade":
        console.log(`Trade executed: ${message.data.tradeId}`);
        updateTradesUI(message.data);
        updatePositionsUI(message.data.position);
        break;
 
      case "marginUpdate":
        console.log(`Margin updated for account: ${message.data.subAccountId}`);
        updateMarginUI(message.data);
        if (message.data.position) {
          updatePositionMarginUI(message.data.position);
        }
        break;
 
      case "liquidation":
        console.log(`LIQUIDATION: ${symbol} at ${message.data.price}`);
        handleLiquidation(message.data);
        break;
 
      default:
        console.log(`${eventType} event:`, message.data);
    }
  }
};

Benefits

Single Subscription

  • One WebSocket connection for all user activity
  • Simplified client implementation
  • Reduced connection overhead

Complete Context

  • Each event includes all relevant data
  • Position snapshots after trades
  • No need to correlate multiple streams

Consistent Format

  • Unified event structure
  • Standard field naming
  • Predictable data types

Migration from Separate Subscriptions

If you're currently using separate subscriptions:

  1. Replace multiple subscriptions with single subAccountUpdates subscription
  2. Update event handlers to use eventType field and "subAccountEvent" method
  3. Remove correlation logic - each event is self-contained
  4. Simplify state management - position data included in trade events
  5. Add margin update handling - receive real-time margin/balance updates

Before (Multiple Subscriptions)

// Old approach - multiple subscriptions
subscribeToOrders(subAccountId, handleOrderUpdate);
subscribeToTrades(subAccountId, handleTradeUpdate);

After (Single Subscription)

// New approach - single subscription
subscribeToSubAccountUpdates(subAccountId, (event) => {
  switch(event.eventType) {
    case "orderPlaced":
    case "orderFilled":
    case "orderPartiallyFilled":
    case "orderCancelled":
    case "orderModified":
    case "orderRejected":
      handleOrderUpdate(event);
      break;
    case "trade":
      handleTradeUpdate(event);
      break;
    case "marginUpdate":
      handleMarginUpdate(event);
      break;
    case "liquidation":
      handleLiquidation(event);
      break;
  }
});

Error Handling

Subscription Errors

{
  "id": "sub-1",
  "status": 401,
  "result": null,
  "error": {
    "code": 401,
    "message": "Invalid subaccount ID"
  }
}

Common Issues

ErrorDescriptionSolution
Invalid subaccount IDSubaccount doesn't exist or no accessVerify subaccount ownership
Authentication requiredWebSocket not authenticatedComplete authentication first
Rate limit exceededToo many eventsImplement backpressure handling

Related Endpoints