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, trades):

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",
    "subAccountId": "1867542890123456789"
  }
}

Request Parameters

ParameterTypeRequiredDescription
idstringYesClient-generated unique request identifier
methodstringYesMust be "subscribe"
params.typestringYesMust be "subAccountUpdates"
params.subAccountIdstringYesSubaccount 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
delegationAddedDelegation created or refreshed for a signer
delegationRevokedDelegation removed for a signer
fundingFunding payment for open positions
wickInsurancePositionIncreasedWick insurance position size increased
wickInsuranceProtectionActivatedWick insurance protection activated
wickInsuranceProtectionCompletedWick insurance protection completed

Order events can include additive optional expiresAt and cancelReason fields. Trade events include additive direction, order (with venueId/clientId), maker, reduceOnly, postOnly, markPrice, entryPrice, and triggeredByLiquidation fields, and the position object now includes netFunding. marginUpdate notifications include an additive debt field. funding notifications include additive paymentTime, fundingTime (replacing the deprecated timestamp and fundingTimestamp). If your client uses an exhaustive switch over eventType, keep a safe default branch so future additive event types do not break message handling.

User Event Messages

Order Placed

{
  "channel": "subAccountUpdate",
  "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"
  },
  "timestamp": 1704067200000
}

Order Filled

{
  "channel": "subAccountUpdate",
  "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"
  },
  "timestamp": 1704067210000
}

Order Cancelled

{
  "channel": "subAccountUpdate",
  "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"
  },
  "timestamp": 1704067220000
}

Order Rejected

{
  "channel": "subAccountUpdate",
  "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"
  },
  "timestamp": 1704067200000
}

Trade Execution

{
  "channel": "subAccountUpdate",
  "data": {
    "eventType": "trade",
    "tradeId": "123456790",
    "order": {
      "venueId": "1948058938469519360",
      "clientId": "cli-1948058938469519360"
    },
    "orderId": "1948058938469519360",
    "subAccountId": "1867542890123456789",
    "symbol": "BTC-USDT",
    "side": "buy",
    "direction": "open long",
    "price": "50010.00",
    "quantity": "0.1",
    "fee": "5.00",
    "feeRate": "0.001",
    "realizedPnl": "0.00",
    "isTaker": true,
    "maker": false,
    "reduceOnly": false,
    "postOnly": false,
    "markPrice": "50025.00",
    "entryPrice": "50010.00",
    "timestamp": 1704067230000,
    "tradedAt": 1704067230000,
    "position": {
      "adlBucket": 2,
      "side": "long",
      "size": "0.1",
      "entryPrice": "50010.00",
      "unrealizedPnl": "0.00",
      "netFunding": "0.00"
    }
  },
  "timestamp": 1704067230000
}

Trade event fields

FieldTypeDescription
tradeIdstringUnique trade execution identifier
orderobjectCanonical composite order identifier (venueId, optional clientId)
order.venueIdstringVenue-generated order identifier
order.clientIdstringOptional client-provided order identifier
orderIdstringDeprecated legacy venue identifier
subAccountIdstringSubaccount identifier
symbolstringTrading pair symbol
sidestringTrade side: "buy" or "sell"
directionstringPosition effect: "open long", "close long", "open short", "close short"
pricestringFilled price
quantitystringFilled quantity
feestringTrading fee amount
feeRatestringFee rate applied
realizedPnlstringRealized P&L from position closure
isTakerbooleanDeprecated; prefer maker
makerbooleantrue if the trade was maker (provided liquidity), false if taker
reduceOnlybooleantrue if the trade reduced an existing position
postOnlybooleantrue if the order was post-only (maker-only)
markPricestringMark price at time of trade
entryPricestringPosition average entry price at time of trade
timestampintegerTrade timestamp (Unix milliseconds)
tradedAtintegerTrade execution timestamp (Unix milliseconds)
positionobjectPost-trade position snapshot
position.netFundingstringNet funding accrued on the position (positive = received)

Margin Update

{
  "channel": "subAccountUpdate",
  "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",
    "debt": "0.00",
    "timestamp": 1704067800000,
    "position": {
      "adlBucket": 3,
      "symbol": "BTC-USDT",
      "upnl": "125.50",
      "initialMargin": "750.00",
      "maintenanceMargin": "375.00",
      "markPrice": "50125.50"
    }
  },
  "timestamp": 1704067800000
}

Margin update fields

FieldTypeDescription
subAccountIdstringSubaccount identifier
accountValuestringTotal account value (equity)
availableMarginstringMargin available for opening new positions
totalUnrealizedPnlstringAggregated unrealized P&L across all positions
maintenanceMarginstringTotal maintenance margin requirement
initialMarginstringTotal initial margin requirement
withdrawablestringAmount currently withdrawable
adjustedAccountValuestringAccount value adjusted for unrealized P&L
debtstringOutstanding debt on the subaccount (e.g. unpaid funding). "0.00" when no debt is owed.
timestampintegerEvent timestamp (Unix milliseconds)
positionobjectOptional per-position snapshot included when the update is triggered by a specific position

Liquidation

{
  "channel": "subAccountUpdate",
  "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": {
      "adlBucket": 0,
      "side": null,
      "size": "0.0",
      "entryPrice": "0.0",
      "unrealizedPnl": "0.00"
    }
  },
  "timestamp": 1704067900000
}

Funding

{
  "channel": "subAccountUpdate",
  "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,
    "paymentTime": 1704067800000,
    "fundingTimestamp": 1704067800000,
    "fundingTime": 1704067800000
  },
  "timestamp": 1704067800000
}

Funding event fields

FieldTypeDescription
paymentIdstringUnique identifier for the funding payment
subAccountIdstringSubaccount identifier
symbolstringTrading pair symbol
positionSizestringPosition size at funding time (signed)
fundingRatestringFunding rate applied
paymentstringFunding payment amount (negative = paid out)
markPricestringMark price used for payment calculation
timestampintegerDEPRECATED - use paymentTime. When the payment was processed (Unix milliseconds)
paymentTimeintegerWhen the payment was processed (Unix milliseconds) — replaces timestamp
fundingTimestampintegerDEPRECATED - use fundingTime. Funding period timestamp (Unix milliseconds)
fundingTimeintegerFunding period timestamp (Unix milliseconds) — replaces fundingTimestamp

Delegation Added

{
  "channel": "subAccountUpdate",
  "data": {
    "eventType": "delegationAdded",
    "subAccountId": "1867542890123456789",
    "delegateAddress": "0x1234567890abcdef1234567890abcdef12345678",
    "permissions": ["trade", "transfer"],
    "expiresAt": 1767225600000,
    "addedBy": "0xabcdef1234567890abcdef1234567890abcdef12",
    "timestamp": 1704068000000
  },
  "timestamp": 1704068000000
}

Delegation Revoked

{
  "channel": "subAccountUpdate",
  "data": {
    "eventType": "delegationRevoked",
    "subAccountId": "1867542890123456789",
    "delegateAddress": "0x1234567890abcdef1234567890abcdef12345678",
    "timestamp": 1704068100000
  },
  "timestamp": 1704068100000
}

Wick Insurance - Position Increased

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

Wick Insurance - Protection Activated

{
  "channel": "subAccountUpdate",
  "data": {
    "eventType": "wickInsuranceProtectionActivated",
    "subAccountId": "1867542890123456789",
    "expiredTime": 1704067800000,
    "timestamp": 1704067200000
  },
  "timestamp": 1704067200000
}

Wick Insurance - Protection Completed

{
  "channel": "subAccountUpdate",
  "data": {
    "eventType": "wickInsuranceProtectionCompleted",
    "subAccountId": "1867542890123456789",
    "protectionId": "12345",
    "expiredTime": 1704067800000,
    "timestamp": 1704067200000
  },
  "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
expiresAtintegerOrder expiry timestamp in milliseconds, when the order has an explicit expiry
cancelReasonstringMachine-readable cancellation reason when supplied by the backend

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)
directionstringPosition direction associated with the fill, when included
markPricestringMark price at execution time, when included
entryPricestringAverage entry price relevant to the execution, when included
makerbooleanWhether the fill executed as maker liquidity
reduceOnlybooleanWhether the order was reduce-only
postOnlybooleanWhether the order was post-only
triggeredByLiquidationbooleanWhether the trade was triggered by liquidation flow

Position Snapshot (in Trade Events)

FieldTypeDescription
position.adlBucketintegerADL priority bucket (1–5). 5 = highest risk, 1 = lowest risk. 0 when position is closed.
position.sidestring | nullPosition side after event
position.sizestringPosition size after event
position.entryPricestringAverage entry price
position.unrealizedPnlstringCurrent unrealized P&L
position.netFundingstringCumulative net funding received/paid for this position

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.adlBucketintegerADL priority bucket (1–5). 5 = highest risk, 1 = lowest risk.
position.symbolstringMarket symbol
position.upnlstringPosition unrealized P&L
position.initialMarginstringPosition initial margin requirement
position.maintenanceMarginstringPosition maintenance margin requirement
position.markPricestringCurrent mark price

Delegation Fields

FieldTypeDescription
delegateAddressstringWallet address whose delegation was added or revoked
permissionsarrayDelegated permissions granted to the signer (delegationAdded only)
expiresAtintegerExpiry timestamp in milliseconds when the delegation is time-bounded (delegationAdded only)
addedBystringWallet address that added or refreshed the delegation (delegationAdded only)
timestampintegerEvent timestamp in milliseconds

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",
    subAccountId: "1867542890123456789"
  }
};
 
ws.send(JSON.stringify(subscription));
 
// Handle subaccount events
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
 
  if (message.channel === "subAccountUpdate") {
    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;
 
      case "delegationAdded":
      case "delegationRevoked":
        console.log(`Delegation update: ${eventType}`);
        handleDelegationUpdate(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 "subAccountUpdate" channel
  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;
    case "delegationAdded":
    case "delegationRevoked":
      handleDelegationUpdate(event);
      break;
    default:
      handleUnknownSubAccountEvent(event);
  }
});

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