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)
nonceintegerYesPositive integer, incrementing nonce
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
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