Get Subaccounts (WebSocket)
Retrieve a list of subaccounts (including delegated subaccounts) for the signing wallet address through the WebSocket connection, providing essential account metadata, collateral information, and cross margin summaries for account selection and management.
Endpoint
ws.send() wss://api.synthetix.io/v1/ws/tradeRequest
Request Format
{
"id": "subaccounts-1",
"method": "post",
"params": {
"action": "getSubaccounts",
"nonce": 1735689600000,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client-generated unique request identifier |
method | string | Yes | Must be "post" |
params | object | Yes | Request parameters wrapper |
params.action | string | Yes | Must be "getSubaccounts" |
params.nonce | integer | Yes | Current timestamp in milliseconds |
params.signature | object | Yes | EIP-712 signature of the request |
| Parameter | Type | Required | Description |
|---|---|---|---|
nonce | uint64 | Yes | Unix milliseconds timestamp (must be monotonically increasing) |
signature | object | Yes | EIP-712 signature object |
expiresAfter | uint64 | No | Unix milliseconds expiration timestamp (5x rate limit on stale cancels) |
:::info Common Parameters
These are top-level request parameters. The subAccountId parameter is specified within the params object (see each endpoint's parameter table).
:::
Response
Success Response
{
"id": "subaccounts-1",
"status": 200,
"result": [
{
"subAccountId": "1867542890123456789",
"masterAccountId": "1867542890123456788",
"subAccountName": "Trading Account 1",
"collaterals": [
{
"symbol": "USDT",
"quantity": "1000.00000000"
},
{
"symbol": "ETH",
"quantity": "0.5000"
}
],
"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
}
}
},
{
"subAccountId": "1867542890123456790",
"masterAccountId": null,
"subAccountName": "Trading Account 2",
"collaterals": [],
"crossMarginSummary": {
"accountValue": "0.00",
"availableMargin": "0.00",
"totalUnrealizedPnl": "0.00",
"maintenanceMargin": "0.00",
"initialMargin": "0.00",
"withdrawable": "0.00",
"adjustedAccountValue": "0.00"
},
"positions": [],
"marketPreferences": {
"leverages": {}
}
}
]
}Subaccount Object
| Field | Type | Description |
|---|---|---|
subAccountId | string | Unique subaccount identifier |
masterAccountId | string | null | ID of the master account (null if this is a master account) |
subAccountName | string | Human-readable subaccount name |
collaterals | array | Array of collateral assets held in this subaccount |
crossMarginSummary | object | Cross margin summary with account value, margins, and P&L |
positions | array | Array of open positions for this subaccount |
marketPreferences | object | Market-specific preferences and settings |
marketPreferences.leverages | object | Per-market leverage settings (key: symbol, value: leverage multiplier) |
feeRates | object | Fee rate information for this subaccount |
feeRates.makerFeeRate | string | Maker fee rate as decimal (e.g., "0.0002" for 0.02%) |
feeRates.takerFeeRate | string | Taker fee rate as decimal (e.g., "0.0005" for 0.05%) |
feeRates.tierName | string | Fee tier name (e.g., "Regular User", "Tier 1") |
Collateral Object
| Field | Type | Description |
|---|---|---|
symbol | string | Collateral token symbol (e.g., "USDT") |
quantity | string | Amount of collateral held |
Cross Margin Summary Object
| Field | Type | Description |
|---|---|---|
accountValue | string | Total account value including PnL |
availableMargin | string | USDT amount available for new positions |
totalUnrealizedPnl | string | Sum of all unrealized PnL |
maintenanceMargin | string | Minimum margin required for all positions |
initialMargin | string | Initial margin required for all positions |
withdrawable | string | USDT amount available for withdrawal |
adjustedAccountValue | string | Adjusted account value for margin calculations |
Error Response
{
"id": "subaccounts-1",
"status": 500,
"result": null,
"error": {
"code": 500,
"message": "Failed to list subaccounts"
}
}| Error | Description |
|---|---|
| Invalid signature | EIP-712 signature validation failed |
| Invalid market symbol | Market symbol not recognized |
| Nonce already used | Nonce must be greater than previous value |
| Rate limit exceeded | Too many requests in time window |
| Request expired | expiresAfter timestamp has passed |
WebSocket Connection Example
const ethers = require('ethers');
const WebSocket = require('ws');
async function getSubaccounts(wallet) {
const ws = new WebSocket('wss://papi.synthetix.io/v1/ws/trade');
await new Promise((resolve) => {
ws.on('open', resolve);
});
// Authenticate first
const authTimestamp = Date.now();
const authDomain = {
name: 'Synthetix',
version: '1',
chainId: 1,
verifyingContract: '0x0000000000000000000000000000000000000000'
};
const authTypes = {
Authenticate: [
{ name: 'timestamp', type: 'uint256' }
]
};
const authMessage = { timestamp: authTimestamp };
const authSignature = await wallet._signTypedData(authDomain, authTypes, authMessage);
ws.send(JSON.stringify({
id: 'auth-1',
method: 'auth',
params: {
message: JSON.stringify(authMessage),
signature: authSignature
}
}));
// Wait for auth response
await new Promise((resolve) => {
ws.once('message', (data) => {
const response = JSON.parse(data);
if (response.id === 'auth-1') {
console.log('Authenticated');
resolve();
}
});
});
// Now request subaccounts
const nonce = Date.now();
const domain = {
name: 'Synthetix',
version: '1',
chainId: 1,
verifyingContract: '0x0000000000000000000000000000000000000000'
};
const types = {
GetSubaccounts: [
{ name: 'action', type: 'string' },
{ name: 'nonce', type: 'uint256' }
]
};
const message = {
action: 'getSubaccounts',
nonce
};
const signature = await wallet._signTypedData(domain, types, message);
const sig = ethers.utils.splitSignature(signature);
ws.send(JSON.stringify({
id: 'subaccounts-1',
method: 'post',
params: {
action: 'getSubaccounts',
nonce,
signature: {
v: sig.v,
r: sig.r,
s: sig.s
}
}
}));
// Handle response
return new Promise((resolve) => {
ws.on('message', (data) => {
const response = JSON.parse(data);
if (response.id === 'subaccounts-1') {
if (response.status === 200) {
console.log('Subaccounts:', response.result);
resolve(response.result);
} else {
console.error('Error:', response.error);
resolve(null);
}
ws.close();
}
});
});
}
// Usage
const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY');
getSubaccounts(wallet);Subaccount Information
- Multiple Accounts: Users can have multiple subaccounts for different trading strategies
- Shared Wallet: All subaccounts share the same underlying wallet address
- Account Metadata: Provides essential account information for selection and identification
- Collateral Overview: Shows which assets are held in each subaccount for informed selection
- Master Account Relationships: Subaccounts can identify their master account hierarchy
- Account Selection: Designed for building account switchers and management interfaces
- Focused Data: Includes collateral and cross margin summary for informed account selection
- Margin Overview: Provides comprehensive margin and balance data across all positions for each subaccount
- Complementary Data: Use with
getPositionsfor position details
Use Cases
- Account Management: Build account switcher interfaces
- Portfolio Overview: Display account balances and collateral
- Risk Monitoring: Monitor margin usage across accounts
- Trading Interface: Enable multi-account trading strategies
- Delegation Management: View delegated subaccount access
Signing
All trading methods are signed using EIP-712. Each successful trading request will contain:
- A piece of structured data that includes the sender address
- A signature of the hash of that structured data, signed by the sender
For detailed information on EIP-712 signing, see EIP-712 Signing.
{
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}Nonce Management
The nonce system prevents replay attacks and ensures order uniqueness:
- Use current timestamp in milliseconds as nonce
- Each nonce must be greater than the previous one
- Recommended: Use
Date.now()or equivalent - If nonce conflicts occur, increment by 1 and retry
Related Endpoints
- Get Positions - Position data via WebSocket
- SubAccount Updates - Real-time account updates
- REST Alternative - HTTP POST request for subaccount