Skip to content

Create Subaccount

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

Endpoint

POST https://papi.synthetix.io/v1/trade

Request

Request Format

{
  "params": {
    "action": "createSubaccount",
    "subAccountId": "1867542890123456789",
    "name": "Trading Bot Strategy"
  },
  "nonce": 1735689600000,
  "signature": {
    "v": 28,
    "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  },
  "expiresAfter": 1735689900
}

Request Parameters

ParameterTypeRequiredDescription
paramsobjectYesParameters object containing method details
params.actionstringYesMust be "createSubaccount"
params.subAccountIdstringYesExisting owned subaccount ID used to prove wallet ownership
params.namestringNoOptional display name for the new subaccount (max 50 chars)
nonceinteger (uint64)YesPositive integer, incrementing nonce
signatureobjectYesEIP-712 signature for wallet authentication
expiresAfterintegerNoOptional expiration timestamp in seconds

Authentication

This endpoint requires the wallet owner to sign a CreateSubaccount payload that includes an existing owned subaccount ID as proof of wallet ownership. In the request body, send that ownership-proof ID as params.subAccountId; in the EIP-712 payload it is signed as masterSubAccountId.

Naming Guidelines

  • Optional Parameter: Name can be omitted for system-generated naming
  • Descriptive Names: Use clear, meaningful names for easy identification when provided
  • Character Limit: Maximum 50 characters when specified
  • Default Behavior: If no name provided, system may generate a default identifier
  • Strategy-Based: Consider naming based on trading strategy or purpose

Examples:

  • "Main Trading"
  • "DCA Strategy"
  • "Arbitrage Bot"
  • "Risk Management"
  • "" (empty string) - System handles default naming

Response

Success Response (New Account)

When a subaccount is first created, subAccountId, subAccountName, and accountLimits are populated. All other fields return zero/null values:

{
  "status": "ok",
  "response": {
    "subAccountId": "1867542890123456790",
    "masterAccountId": null,
    "subAccountName": "Trading Bot Strategy",
    "collaterals": null,
    "crossMarginSummary": {
      "accountValue": "",
      "availableMargin": "",
      "totalUnrealizedPnl": "",
      "maintenanceMargin": "",
      "initialMargin": "",
      "withdrawable": "",
      "adjustedAccountValue": "",
      "debt": ""
    },
    "positions": null,
    "marketPreferences": {
      "leverages": null
    },
    "feeRates": {
      "makerFeeRate": "",
      "takerFeeRate": "",
      "tierName": ""
    },
    "accountLimits": {
      "maxBorrowCapacity": "100000",
      "maxOrdersPerMarket": 50,
      "maxSubAccounts": 10,
      "maxTotalOrders": 200
    }
  },
  "request_id": "5ccf215d37e3ae6d"
}

Response Structure

Response Fields

FieldTypeDescription
subAccountIdstringSystem-generated unique identifier for the new subaccount (populated)
masterAccountIdstring | nullMaster account ID (returns null)
subAccountNamestringDisplay name provided in request (or empty if not specified) (populated)
collateralsarray | nullCollateral balances (returns null for new accounts)
collaterals[].adjustedCollateralValuestringAdjusted collateral value after applying haircuts
collaterals[].calculatedAtintegerUnix millisecond timestamp of the collateral price calculation (0 for USDT)
collaterals[].collateralValuestringRaw collateral value
collaterals[].pendingWithdrawstringAmount pending withdrawal
collaterals[].pricestringCollateral price used for valuation
collaterals[].quantitystringTotal collateral quantity held
collaterals[].symbolstringCollateral asset symbol
collaterals[].withdrawablestringAmount available to withdraw
crossMarginSummaryobjectCross-margin account summary (returns empty strings for new accounts)
crossMarginSummary.debtstringUSDT debt after positive unrealized PnL offset
positionsarray | nullOpen positions (returns null for new accounts)
marketPreferencesobjectMarket-specific preferences like leverage (returns empty for new accounts)
feeRatesobjectFee rate information (returns empty strings for new accounts)
accountLimitsobjectAccount limit information
accountLimits.maxBorrowCapacitystringMaximum borrow capacity in USDT
accountLimits.maxOrdersPerMarketintegerMaximum open orders allowed per market
accountLimits.maxSubAccountsintegerMaximum number of subaccounts allowed for the wallet
accountLimits.maxTotalOrdersintegerMaximum total open orders across all markets

Initial State

  • Populated Fields: subAccountId, subAccountName, and accountLimits are populated upon creation
  • Zero/Null Values: Other fields are returned with zero or null values since the account has no positions or collaterals yet
  • Active Status: Subaccount is immediately available for trading
  • Full Functionality: All trading features are enabled upon creation
  • Additional Details: Use Get Subaccount after deposits/trades to retrieve populated account information including positions and collaterals

Error Response

{
  "status": "error",
  "error": {
    "message": "Failed to create subaccount",
    "code": "INTERNAL_ERROR"
  },
  "request_id": "5ccf215d37e3ae6d"
}

Common Error Cases

{
  "status": "error",
  "error": {
    "message": "Subaccount limit reached",
    "code": "VALIDATION_ERROR"
  },
  "request_id": "5ccf215d37e3ae6d"
}
{
  "status": "error",
  "error": {
    "message": "Invalid subaccount name",
    "code": "VALIDATION_ERROR"
  },
  "request_id": "5ccf215d37e3ae6d"
}

Code Examples

Create Basic Subaccount

{
  "params": {
    "action": "createSubaccount",
    "subAccountId": "1867542890123456789",
    "name": "Main Trading"
  },
  "nonce": 1735689600000,
  "signature": {
    "v": 28,
    "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  },
  "expiresAfter": 1735689900
}

Create Strategy-Specific Subaccount

{
  "params": {
    "action": "createSubaccount",
    "subAccountId": "1867542890123456789",
    "name": "Grid Trading Bot"
  },
  "nonce": 1735689600001,
  "signature": {
    "v": 28,
    "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  },
  "expiresAfter": 1735689901
}

Implementation Notes

  • Wallet owner signature required, plus an existing owned subaccount ID supplied as params.subAccountId for ownership proof
  • Subaccount name parameter is optional and accepts empty string for system-generated naming
  • Name length must not exceed 50 characters when provided
  • Account creation limits may apply per platform configuration
  • New subaccounts are immediately available for trading operations
  • Each subaccount inherits master wallet security and authorization settings

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.

Nonce Management

The nonce system prevents replay attacks and ensures order uniqueness:

  • Use any positive integer as nonce
  • Each nonce must be greater than the previous one (incrementing)
  • Date.now() is a convenient option, not a requirement
  • If nonce conflicts occur, increment by 1 and retry

:::note SubAccountAction Exception SubAccountAction endpoints (getPositions, getOpenOrders, getOrdersHistory, getTrades, getFundingPayments, getSubAccount, getSubAccounts, getDelegatedSigners, getBalanceUpdates) do not require a nonce. Only the signature and optional expiresAfter parameters are needed. :::

Error Handling

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