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/tradeRequest
Request Format
{
"id": "subaccount-1",
"method": "post",
"params": {
"action": "getSubAccount",
"subAccountId": "1867542890123456789",
"expiresAfter": 1704067500,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}
}Parameters
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client-generated unique request identifier |
method | string | Yes | Must be "post" |
params | object | Yes | Contains all parameters for the request |
Params Object
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "getSubAccount" |
subAccountId | string | Yes | Subaccount identifier |
expiresAfter | integer | No | Optional expiration timestamp in seconds |
signature | object | Yes | EIP-712 signature using SubAccountAction type |
- This endpoint uses
SubAccountActionEIP-712 type (no nonce required, onlyexpiresAfteris 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
| Field | Type | Description |
|---|---|---|
subAccountId | string | Unique subaccount identifier |
masterAccountId | string | null | Parent account ID if this is a delegated subaccount, null otherwise |
name | string | Human-readable subaccount name |
collaterals | array | Array of collateral balances held in this subaccount |
marginSummary | object | Comprehensive margin and balance information |
positions | array | Array of open positions for this subaccount |
marketPreferences | object | Market-specific settings (leverage per market) |
feeRates | object | Fee rates applicable to this subaccount |
Collateral Object
| Field | Type | Description |
|---|---|---|
symbol | string | Collateral token symbol (e.g., "USDT") |
quantity | string | Amount of collateral held |
withdrawable | string | Amount available for withdrawal |
pendingWithdraw | string | Amount pending withdrawal |
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 |
Position Fields
| Field | Type | Description |
|---|---|---|
symbol | string | Market symbol |
side | string | Position side: "long" or "short" |
entryPrice | string | Volume-weighted average entry price |
quantity | string | Position size (always positive) |
pnl | string | Realized profit/loss |
upnl | string | Unrealized profit/loss |
usedMargin | string | Margin allocated to this position |
maintenanceMargin | string | Minimum margin required to maintain position |
liquidationPrice | string | Price at which position will be liquidated |
Market Preferences
| Field | Type | Description |
|---|---|---|
leverages | object | Map of market symbols to leverage values (e.g., {"BTC-USDT": 20}) |
Fee Rates
| Field | Type | Description |
|---|---|---|
maker | string | Maker fee rate (e.g., "0.0002" = 0.02%) |
taker | string | Taker fee rate (e.g., "0.0005" = 0.05%) |
tierName | string | Fee 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
SubAccountActionEIP-712 type (no nonce required) - Returns data for the specified subaccount
| 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 |
Next Steps
- Get Positions - Detailed position information
- Get Order History - Order history and status
- SubAccount Updates - Real-time account updates
- Get Subaccount IDs - List all subaccount IDs for a wallet