Skip to content

Get Subaccounts (WebSocket)

Retrieve all subaccounts for the authenticated wallet through the WebSocket connection, including comprehensive details for each subaccount such as 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"
          },
          {
            "symbol": "ETH",
            "quantity": "0.5000",
            "withdrawable": "0.5000",
            "pendingWithdraw": "0.0000"
          }
        ],
        "crossMarginSummary": {
          "accountValue": "6750.50",
          "availableMargin": "2415.00",
          "totalUnrealizedPnl": "75.00",
          "maintenanceMargin": "1207.50",
          "initialMargin": "2415.00",
          "withdrawable": "4335.50"
          "adjustedAccountValue": "6750.50"
        },
        "positions": [],
        "marketPreferences": {
          "leverages": {
            "BTC-USDT": 20,
            "ETH-USDT": 10
          }
        },
        "feeRates": {
          "makerFeeRate": "0.0002",
          "takerFeeRate": "0.0005",
          "tierName": "Regular User"
        },
        "delegatedSigners": [
          {
            "subAccountId": "1867542890123456789",
            "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590",
            "permissions": ["trading"],
            "expiresAt": null
          }
        ]
      },
      {
        "subAccountId": "1867542890123456790",
        "masterAccountId": "1867542890123456788",
        "subAccountName": "Trading Account 2",
        "collaterals": [
          {
            "symbol": "USDC",
            "quantity": "5000.00000000",
            "withdrawable": "5000.00000000",
            "pendingWithdraw": "0.00000000"
          }
        ],
        "crossMarginSummary": {
          "accountValue": "5000.00",
          "availableMargin": "5000.00",
          "totalUnrealizedPnl": "0.00",
          "maintenanceMargin": "0.00",
          "initialMargin": "0.00",
          "withdrawable": "5000.00"
          "adjustedAccountValue": "5000.00"
        },
        "positions": [],
        "marketPreferences": {
          "leverages": {}
        },
        "feeRates": {
          "makerFeeRate": "0.0002",
          "takerFeeRate": "0.0005",
          "tierName": "Regular User"
        },
        "delegatedSigners": []
      }
    ]
  }
}

Response Fields

FieldTypeDescription
subAccountsarrayArray of subaccount objects

Each subaccount in the subAccounts array includes:

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

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

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. Currently supports: ["trading"]
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": ["trading"],
  "expiresAt": null,
  "addedBy": "0x1111111111111111111111111111111111111111"
}

Example with Expiration

{
  "subAccountId": "1867542890123456789",
  "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f89590",
  "permissions": ["trading"],
  "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 associated with the authenticated wallet
  • 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