Skip to content

Get Subaccounts (WebSocket)

Retrieve all subaccounts under the same master account as the authenticated subaccount through the WebSocket connection. Works for both account owners and delegated signers — any subaccount that can authenticate will receive the full list of sibling subaccounts, each including collateral balances, cross margin summary, positions, market preferences, fee rates, and delegated signers. This is a more comprehensive alternative to getSubAccount that returns multiple subaccounts with delegation information included.

Endpoint

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

Request

Request Format

{
  "id": "subaccounts-1",
  "method": "post",
  "params": {
    "action": "getSubAccounts",
    "subAccountId": "1867542890123456789",
    "expiresAfter": 1704067500000,
    "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 "getSubAccounts"
subAccountIdstringYesThe ID of a subaccount owned by the authenticated wallet
expiresAfterintegerNoOptional expiration timestamp (milliseconds)
signatureobjectYesEIP-712 signature using SubAccountAction type
Important Notes:
  • This endpoint uses SubAccountAction EIP-712 type (no nonce required, only expiresAfter is optional)
  • Returns all subaccounts associated with the authenticated wallet

Response Format

Success Response

{
  "id": "subaccounts-1",
  "status": 200,
  "result": {
    "subAccounts": [
      {
        "subAccountId": "1867542890123456789",
        "masterAccountId": "1867542890123456788",
        "subAccountName": "Trading Account 1",
        "collaterals": [
          {
            "symbol": "USDC",
            "quantity": "1000.00000000",
            "withdrawable": "1000.00000000",
            "pendingWithdraw": "0.00000000",
            "adjustedCollateralValue": "1000.00",
            "collateralValue": "1000.00",
            "haircutRate": "0",
            "haircutAdjustment": "0.00",
            "price": "1.0000",
            "calculatedAt": 0
          },
          {
            "symbol": "ETH",
            "quantity": "0.5000",
            "withdrawable": "0.5000",
            "pendingWithdraw": "0.0000",
            "adjustedCollateralValue": "975.00",
            "collateralValue": "1000.00",
            "haircutRate": "0.025",
            "haircutAdjustment": "25.00",
            "price": "2000.00",
            "calculatedAt": 1735689600000
          }
        ],
        "crossMarginSummary": {
          "accountValue": "6750.50",
          "availableMargin": "2415.00",
          "totalUnrealizedPnl": "75.00",
          "maintenanceMargin": "1207.50",
          "initialMargin": "2415.00",
          "withdrawable": "4335.50",
          "adjustedAccountValue": "6750.50",
          "debt": "0.00"
        },
        "positions": [],
        "marketPreferences": {
          "leverages": {
            "BTC-USDT": 20,
            "ETH-USDT": 10
          }
        },
        "feeRates": {
          "makerFeeRate": "0.0002",
          "takerFeeRate": "0.0005",
          "tierName": "Regular User"
        },
        "accountLimits": {
          "maxBorrowCapacity": "10000.00",
          "maxOrdersPerMarket": 10,
          "maxSubAccounts": 10,
          "maxTotalOrders": 100
        },
        "delegatedSigners": [
          {
            "subAccountId": "1867542890123456789",
            "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590",
            "permissions": ["trading"],
            "expiresAt": null,
            "addedBy": "0x1234567890abcdef1234567890abcdef12345678"
          }
        ]
      },
      {
        "subAccountId": "1867542890123456790",
        "masterAccountId": "1867542890123456788",
        "subAccountName": "Trading Account 2",
        "collaterals": [
          {
            "symbol": "USDC",
            "quantity": "5000.00000000",
            "withdrawable": "5000.00000000",
            "pendingWithdraw": "0.00000000",
            "adjustedCollateralValue": "5000.00",
            "collateralValue": "5000.00",
            "haircutRate": "0",
            "haircutAdjustment": "0.00",
            "price": "1.0000",
            "calculatedAt": 0
          }
        ],
        "crossMarginSummary": {
          "accountValue": "5000.00",
          "availableMargin": "5000.00",
          "totalUnrealizedPnl": "0.00",
          "maintenanceMargin": "0.00",
          "initialMargin": "0.00",
          "withdrawable": "5000.00",
          "adjustedAccountValue": "5000.00",
          "debt": "0.00"
        },
        "positions": [],
        "marketPreferences": {
          "leverages": {}
        },
        "feeRates": {
          "makerFeeRate": "0.0002",
          "takerFeeRate": "0.0005",
          "tierName": "Regular User"
        },
        "accountLimits": {
          "maxBorrowCapacity": "10000.00",
          "maxOrdersPerMarket": 10,
          "maxSubAccounts": 10,
          "maxTotalOrders": 100
        },
        "delegatedSigners": []
      }
    ]
  }
}

Response Fields

FieldTypeDescription
subAccountsarrayArray of subaccount objects

Each subaccount in the subAccounts array includes:

FieldTypeDescription
subAccountIdstringUnique subaccount identifier
masterAccountIdstring | nullID of the master account (null if this is a master account)
subAccountNamestringHuman-readable subaccount name
collateralsarrayArray of collateral assets held in this subaccount
crossMarginSummaryobjectCross margin summary with account value, margins, and P&L
positionsarrayArray of open positions for this subaccount
marketPreferencesobjectMarket-specific preferences and settings
marketPreferences.leveragesobjectPer-market leverage settings (key: symbol, value: leverage multiplier)
feeRatesobjectFee rate information for this subaccount
feeRates.makerFeeRatestringMaker fee rate as decimal (e.g., "0.0002" for 0.02%)
feeRates.takerFeeRatestringTaker fee rate as decimal (e.g., "0.0005" for 0.05%)
feeRates.tierNamestringFee tier name (e.g., "Regular User", "Tier 1")
accountLimitsobjectAccount limits for this subaccount
accountLimits.maxBorrowCapacitystringMaximum borrow capacity in USD
accountLimits.maxOrdersPerMarketintegerMaximum number of open orders per market
accountLimits.maxSubAccountsintegerMaximum number of subaccounts allowed for the master account
accountLimits.maxTotalOrdersintegerMaximum total number of open orders across all markets
FieldTypeDescription
delegatedSignersarrayArray of delegated signer objects for this subaccount

Collateral Object

FieldTypeDescription
symbolstringCollateral token symbol (e.g., "USDT")
quantitystringAmount of collateral held
withdrawablestringAmount available for withdrawal
pendingWithdrawstringAmount pending withdrawal
adjustedCollateralValuestringCollateral value after applying haircut discount (USD equivalent)
collateralValuestringFull collateral value before haircut (USD equivalent)
haircutRatestringHaircut rate applied to this collateral (e.g., "0.1" = 10% discount)
haircutAdjustmentstringAbsolute haircut adjustment amount in USD
pricestringCollateral token price in USD at time of calculation
calculatedAtintegerUnix timestamp (milliseconds) when price was last calculated; 0 for USDT

Cross 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
debtstringOutstanding debt in the account

Delegate Object

Delegate Object

The delegate object represents a delegated signer in API responses. Note that the response uses walletAddress while EIP-712 signing uses delegateAddress.

FieldTypeDescription
subAccountIdstringSubaccount ID this delegation applies to
walletAddressstringEthereum wallet address of the delegated signer (42-character hex format)
permissionsstring[]Array of permission levels granted, such as ["session"] or ["delegate"]
expiresAtinteger | nullUnix timestamp (milliseconds) when the delegation expires. null indicates no expiration
addedBystring | omittedWallet address that created this delegation. Omitted for pre-migration records where the creator was not recorded

Example Delegate Object

{
  "subAccountId": "1867542890123456789",
  "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590",
  "permissions": ["session"],
  "expiresAt": null,
  "addedBy": "0x1111111111111111111111111111111111111111"
}

Example with Expiration

{
  "subAccountId": "1867542890123456789",
  "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590",
  "permissions": ["delegate"],
  "expiresAt": 1767225600000
}

Error Response

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

Implementation Example

class SubaccountsQuery {
  constructor(ws, signer) {
    this.ws = ws;
    this.signer = signer;
    this.pendingRequests = new Map();
  }
 
  async getSubAccounts(subAccountId) {
    const expiresAfter = Date.now() + 300000; // 5 minutes in milliseconds
    // Sign using SubAccountAction type (no nonce required)
    const signature = await this.signSubAccountAction(subAccountId, "getSubAccounts", expiresAfter);
 
    const request = {
      id: `subaccounts-${Date.now()}`,
      method: "post",
      params: {
        action: "getSubAccounts",
        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 sig = await this.signer.signTypedData(domain, types, message);
    const { v, r, s } = ethers.Signature.from(sig);
    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 SubaccountsQuery(ws, signer);
const subaccounts = await query.getSubAccounts("1867542890123456789");
 
subaccounts.subAccounts.forEach(account => {
  console.log(`Account: ${account.subAccountName}`);
  console.log(`Value: ${account.crossMarginSummary.accountValue}`);
  console.log(`Delegates: ${account.delegatedSigners.length}`);
});

Code Examples

Get All Subaccounts

{
  "id": "get-subaccounts",
  "method": "post",
  "params": {
    "action": "getSubAccounts",
    "subAccountId": "1867542890123456789",
    "expiresAfter": 0,
    "signature": { "v": 28, "r": "0x...", "s": "0x..." }
  }
}

Implementation Notes

  • This endpoint uses SubAccountAction EIP-712 type (no nonce required)
  • Returns all subaccounts under the same master account as the authenticated subaccount
  • Works for both account owners and delegated signers
  • Includes delegated signers for each subaccount, unlike getSubAccount
Error CodeDescriptionRetryable
UNAUTHORIZEDEIP-712 signature validation failedNo
VALIDATION_ERRORRequest validation failedNo
MISSING_REQUIRED_FIELDRequired field is missingNo
INVALID_FORMATField format is invalidNo
INVALID_VALUEInvalid parameter valueNo
RATE_LIMIT_EXCEEDEDToo many requests in time windowYes
INSUFFICIENT_MARGINNot enough margin for tradeNo
ORDER_NOT_FOUNDOrder does not existNo
OPERATION_TIMEOUTOperation timed outYes

Next Steps