Skip to content

Create Subaccount (WebSocket)

Create a new trading subaccount under the authenticated wallet address through the WebSocket connection. Subaccounts allow for isolated trading strategies, separate margin management, and organized position tracking within a single master account.

Endpoint

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

Request

Request Format

{
  "id": "create-subaccount-1",
  "method": "post",
  "params": {
    "action": "createSubaccount",
    "name": "Trading Bot Strategy",
    "nonce": 1735689600000,
    "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 "createSubaccount"
namestringNoOptional display name for the new subaccount (max 50 chars)
nonceintegerYesUnix milliseconds timestamp, monotonically increasing
signatureobjectYesEIP-712 signature for wallet authentication

Important: This endpoint authenticates at the wallet level rather than requiring an existing subAccountId.

Naming Guidelines

  • Optional Parameter: Name can be omitted for system-generated naming
  • Character Limit: Maximum 50 characters when specified
  • Default Behavior: If no name provided, system may generate a default identifier

Examples: "Main Trading", "DCA Strategy", "Arbitrage Bot", "Risk Management"

Response Format

Success Response (New Account)

When a subaccount is first created, only subAccountId and subAccountName are populated:

{
  "id": "create-subaccount-1",
  "status": 200,
  "result": {
    "subAccountId": "1867542890123456790",
    "masterAccountId": null,
    "subAccountName": "Trading Bot Strategy",
    "collaterals": null,
    "crossMarginSummary": {
      "accountValue": "0",
      "availableMargin": "0",
      "totalUnrealizedPnl": "0",
      "maintenanceMargin": "0",
      "initialMargin": "0",
      "withdrawable": "0",
      "adjustedAccountValue": "0"
    },
    "positions": null,
    "marketPreferences": {
      "leverages": null
    },
    "feeRates": {
      "makerFeeRate": "0",
      "takerFeeRate": "0",
      "tierName": ""
    }
  }
}

Response Fields

FieldTypeDescription
subAccountIdstringSystem-generated unique identifier for the new subaccount
masterAccountIdstring | nullMaster account ID (returns null)
subAccountNamestringDisplay name provided in request (or empty if not specified)
collateralsarray | nullCollateral balances (returns null for new accounts)
crossMarginSummaryobjectCross-margin account summary (returns zeros for new accounts)
positionsarray | nullOpen positions (returns null for new accounts)
marketPreferencesobjectMarket-specific preferences like leverage
feeRatesobjectFee rate information

Error Response

{
  "id": "create-subaccount-1",
  "status": 400,
  "result": null,
  "error": {
    "code": 400,
    "message": "Subaccount limit reached"
  }
}

Implementation Example

import { ethers } from 'ethers';
 
async function createSubaccount(ws, signer, name = "") {
  const nonce = Date.now();
 
  const domain = {
    name: "Synthetix",
    version: "1",
    chainId: 1,
    verifyingContract: "0x0000000000000000000000000000000000000000"
  };
 
  const types = {
    CreateSubaccount: [
      { name: "name", type: "string" },
      { name: "nonce", type: "uint256" }
    ]
  };
 
  const message = {
    name,
    nonce: BigInt(nonce)
  };
 
  const sig = await signer.signTypedData(domain, types, message);
  const signature = ethers.Signature.from(sig);
 
  ws.send(JSON.stringify({
    id: `create-subaccount-${Date.now()}`,
    method: "post",
    params: {
      action: "createSubaccount",
      name,
      nonce,
      signature: { v: signature.v, r: signature.r, s: signature.s }
    }
  }));
}
 
// Usage: Create a new trading subaccount
await createSubaccount(ws, signer, "Grid Trading Bot");

Code Examples

Create Basic Subaccount

{
  "id": "create-basic",
  "method": "post",
  "params": {
    "action": "createSubaccount",
    "name": "Main Trading",
    "nonce": 1735689600000,
    "signature": { "v": 28, "r": "0x...", "s": "0x..." }
  }
}

Create Strategy-Specific Subaccount

{
  "id": "create-strategy",
  "method": "post",
  "params": {
    "action": "createSubaccount",
    "name": "Grid Trading Bot",
    "nonce": 1735689600001,
    "signature": { "v": 28, "r": "0x...", "s": "0x..." }
  }
}

Create Subaccount Without Name

{
  "id": "create-unnamed",
  "method": "post",
  "params": {
    "action": "createSubaccount",
    "nonce": 1735689600002,
    "signature": { "v": 28, "r": "0x...", "s": "0x..." }
  }
}

Implementation Notes

  • Wallet-Level Auth: Authenticates at wallet level (no existing subAccountId needed)
  • Immediate Availability: Subaccount is immediately available for trading after creation
  • Account Limits: Platform may enforce maximum number of subaccounts per wallet
  • Initial State: New subaccounts have zero balances and no positions
  • Security Inheritance: Each subaccount inherits master wallet security settings

Common Errors

Error CodeMessageDescription
400Subaccount limit reachedMaximum subaccounts for this wallet exceeded
400Invalid subaccount nameName exceeds 50 characters or contains invalid characters
401Authentication failedInvalid signature
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