Skip to content

Get Subaccount (WebSocket)

Retrieve complete account information for the authenticated subaccount through the WebSocket connection, including collateral balances, open positions, margin summary, market preferences, and fee rate information.

Endpoint

ws.send() wss://api.synthetix.io/v1/ws/trade

Request

Request Format

{
  "id": "subaccount-1",
  "method": "post",
  "params": {
    "action": "getSubAccount",
    "subAccountId": "1867542890123456789",
    "expiresAfter": 1704067500,
    "signature": {
      "v": 28,
      "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
      "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
    }
  }
}

Parameters

Request Parameters

ParameterTypeRequiredDescription
idstringYesClient-generated unique request identifier
methodstringYesMust be "post"
paramsobjectYesContains all parameters for the request

Params Object

ParameterTypeRequiredDescription
actionstringYesMust be "getSubAccount"
subAccountIdstringYesSubaccount identifier
expiresAfterintegerNoOptional expiration timestamp in seconds
signatureobjectYesEIP-712 signature using SubAccountAction type
Important Notes:
  • This endpoint uses SubAccountAction EIP-712 type (no nonce required, only expiresAfter is optional)
  • Returns data for the specified subaccount

Response Format

Success Response

{
  "id": "subaccount-1",
  "status": 200,
  "result": {
    "subAccountId": "1867542890123456789",
    "masterAccountId": null,
    "name": "Trading Account 1",
    "collaterals": [
      {
        "symbol": "USDT",
        "quantity": "10000.00000000",
        "withdrawable": "5000.00000000",
        "pendingWithdraw": "0.00000000"
      },
      {
        "symbol": "ETH",
        "quantity": "2.50000000",
        "withdrawable": "1.00000000",
        "pendingWithdraw": "0.00000000"
      }
    ],
    "marginSummary": {
      "accountValue": "15750.50",
      "availableMargin": "8250.00",
      "unrealizedPnl": "125.50",
      "maintenanceMargin": "3150.25",
      "initialMargin": "6300.50",
      "withdrawable": "9450.00",
      "adjustedAccountValue": "15750.50"
    },
    "positions": [
      {
        "symbol": "BTC-USDT",
        "side": "long",
        "entryPrice": "43500.00",
        "quantity": "0.25",
        "pnl": "50.00",
        "upnl": "125.50",
        "usedMargin": "2175.00",
        "maintenanceMargin": "1087.50",
        "liquidationPrice": "41000.00"
      }
    ],
    "marketPreferences": {
      "leverages": {
        "BTC-USDT": 20,
        "ETH-USDT": 10
      }
    },
    "feeRates": {
      "maker": "0.0002",
      "taker": "0.0005",
      "tierName": "VIP 0"
    }
  }
}

Response Fields

FieldTypeDescription
subAccountIdstringUnique subaccount identifier
masterAccountIdstring | nullParent account ID if this is a delegated subaccount, null otherwise
namestringHuman-readable subaccount name
collateralsarrayArray of collateral balances held in this subaccount
marginSummaryobjectComprehensive margin and balance information
positionsarrayArray of open positions for this subaccount
marketPreferencesobjectMarket-specific settings (leverage per market)
feeRatesobjectFee rates applicable to this subaccount

Collateral Object

FieldTypeDescription
symbolstringCollateral token symbol (e.g., "USDT")
quantitystringAmount of collateral held
withdrawablestringAmount available for withdrawal
pendingWithdrawstringAmount pending withdrawal

Margin Summary Object

FieldTypeDescription
accountValuestringTotal account value including PnL
availableMarginstringUSDT amount available for new positions
totalUnrealizedPnlstringSum of all unrealized PnL
maintenanceMarginstringMinimum margin required for all positions
initialMarginstringInitial margin required for all positions
withdrawablestringUSDT amount available for withdrawal
adjustedAccountValuestringAdjusted account value for margin calculations

Position Fields

FieldTypeDescription
symbolstringMarket symbol
sidestringPosition side: "long" or "short"
entryPricestringVolume-weighted average entry price
quantitystringPosition size (always positive)
pnlstringRealized profit/loss
upnlstringUnrealized profit/loss
usedMarginstringMargin allocated to this position
maintenanceMarginstringMinimum margin required to maintain position
liquidationPricestringPrice at which position will be liquidated

Market Preferences

FieldTypeDescription
leveragesobjectMap of market symbols to leverage values (e.g., {"BTC-USDT": 20})

Fee Rates

FieldTypeDescription
makerstringMaker fee rate (e.g., "0.0002" = 0.02%)
takerstringTaker fee rate (e.g., "0.0005" = 0.05%)
tierNamestringFee tier name (e.g., "VIP 0", "VIP 1")

Error Response

{
  "id": "subaccount-1",
  "status": 400,
  "result": null,
  "error": {
    "code": 400,
    "message": "subaccountId is required"
  }
}

Implementation Example

class SubaccountQuery {
  constructor(ws, signer) {
    this.ws = ws;
    this.signer = signer;
    this.pendingRequests = new Map();
  }
 
  async getSubAccount(subAccountId, expiresAfter = 0) {
    // Sign using SubAccountAction type (no nonce required)
    const signature = await this.signSubAccountAction(subAccountId, "getSubAccount", expiresAfter);
 
    const request = {
      id: `subaccount-${Date.now()}`,
      method: "post",
      params: {
        action: "getSubAccount",
        subAccountId,
        expiresAfter,
        signature
      }
    };
 
    return this.sendRequest(request);
  }
 
  async signSubAccountAction(subAccountId, action, expiresAfter = 0) {
    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: BigInt(subAccountId),
      action,
      expiresAfter: BigInt(expiresAfter)
    };
 
    const signature = await this.signer._signTypedData(domain, types, message);
    const { v, r, s } = ethers.utils.splitSignature(signature);
    return { v, r, s };
  }
 
  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);
      }
    }
  }
}
 
// Usage
const query = new SubaccountQuery(ws, signer);
const subaccount = await query.getSubAccount("1867542890123456789");
 
console.log('Account Value:', subaccount.marginSummary.accountValue);
console.log('Positions:', subaccount.positions.length);

Implementation Notes

  • This endpoint uses SubAccountAction EIP-712 type (no nonce required)
  • Returns data for the specified subaccount
ErrorDescription
Invalid signatureEIP-712 signature validation failed
Invalid market symbolMarket symbol not recognized
Nonce already usedNonce must be greater than previous value
Rate limit exceededToo many requests in time window
Request expiredexpiresAfter timestamp has passed

Next Steps