Portal para programadores
Tema

Account API#

GET /account/balance - Account Balance#

Retrieves the total account equity, perp position notional value, position mode, and Token asset details for the master account or a specified sub-account.

For collateral tokens, accAvgPx, spotUpl, spotUplRatio, and entryCost return empty strings.

Request Parameters

ParameterTypeRequiredDescription
vaultAddressStringNoSub-account address. Omit to query the master account; provide it to query a specified sub-account.

Request Examples

text
GET /api/v5/exchangeos/account/balance
GET /api/v5/exchangeos/account/balance?vaultAddress=0x6d1a19e1e03b83163fb38d7336b58875e71c50c2

Envelope Response Fields

FieldTypeDescription
codeStringAPI response code. "0" indicates success.
msgStringResponse message. Empty on success.
dataArrayAccount balance data.

data[] Fields

FieldTypeDescription
totalEqStringTotal account equity, including only Tokens where pointFlag=false.
notionalUsdStringSum of the absolute notional values of all established perp positions, in USD.
positionModeStringPosition mode: oneWay or hedge.
block_heightStringOn-chain block height corresponding to the query result.
block_timestampStringOn-chain block time corresponding to the query result, as a Unix timestamp in milliseconds.
detailsArrayAsset details for each Token.

details[] Fields

FieldTypeDescription
tokenIdStringToken ID.
collateralEnabledBooleanWhether the Token is enabled as collateral.
eqStringToken equity.
eqUsdStringUSD value of Token equity.
isoEqStringIsolated equity. Returns an empty string when not applicable.
cashBalStringCash balance.
availBalStringAvailable balance.
availEqStringAvailable equity. Returns an empty string when not applicable.
frozenMgnStringFrozen margin.
spotFrozenStringFrozen Spot amount.
perpFrozenStringFrozen perp margin. Returns an empty string when not applicable.
predFrozenStringFrozen Prediction margin. Returns an empty string when not applicable.
mmrStringMaintenance margin requirement. Returns an empty string when not applicable.
mgnRatioStringMargin ratio. Returns an empty string when not applicable.
frozenMgnRatioStringFrozen margin ratio. Returns an empty string when not applicable.
accAvgPxStringSpot accumulated average position price. Returns an empty string for collateral Tokens.
spotUplStringSpot unrealized PnL. Returns an empty string for collateral Tokens.
spotUplRatioStringSpot unrealized PnL ratio. Returns an empty string for collateral Tokens.
entryCostStringSpot position cost. Returns an empty string for collateral Tokens.
uplStringperp unrealized PnL. Returns an empty string when not applicable.
isoUplStringIsolated unrealized PnL. Returns an empty string when not applicable.
lastPxStringLatest price.
tokenPxStringToken price.
totalLeverStringTotal leverage. Returns an empty string when not applicable.

Calculation Basis

text
totalEq
= Σ details[].eqUsd, including only Tokens where pointFlag=false

frozenMgn
= spotFrozen + perpFrozen + predFrozen

notionalUsd
= Σ abs(positionValue of all established perp positions)

Return Rules

  • A valid numeric value of zero is returned as "0".
  • Fields that are not applicable are returned as "".
  • Margin-related fields for non-collateral Tokens return "".
  • Equity for live trading and points trading must not be combined.

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "totalEq": "110060.000000",
      "notionalUsd": "9891.086264",
      "positionMode": "oneWay",
      "block_height": "12092417",
      "block_timestamp": "1785218400074",
      "details": [
        {
          "tokenId": "0",
          "collateralEnabled": true,
          "eq": "100060.000000",
          "eqUsd": "100060.000000",
          "isoEq": "0.000000",
          "cashBal": "100000.000000",
          "availBal": "98712.000000",
          "availEq": "98712.000000",
          "frozenMgn": "1288.000000",
          "spotFrozen": "0.000000",
          "perpFrozen": "1288.000000",
          "mmr": "43.500000",
          "mgnRatio": "0.000435",
          "frozenMgnRatio": "0.012872",
          "accAvgPx": "",
          "spotUpl": "",
          "spotUplRatio": "",
          "entryCost": "",
          "upl": "60.000000",
          "isoUpl": "0.000000",
          "lastPx": "1.000000",
          "tokenPx": "1.000000",
          "totalLever": "0.086948"
        },
        {
          "tokenId": "3",
          "collateralEnabled": false,
          "eq": "0.125000",
          "eqUsd": "10000.000000",
          "isoEq": "",
          "cashBal": "0.125000",
          "availBal": "0.100000",
          "availEq": "",
          "frozenMgn": "0.025000",
          "spotFrozen": "0.025000",
          "perpFrozen": "",
          "predFrozen": "0",
          "mmr": "",
          "mgnRatio": "",
          "frozenMgnRatio": "",
          "accAvgPx": "60000.000000",
          "spotUpl": "2500.000000",
          "spotUplRatio": "0.333333",
          "entryCost": "7500.000000",
          "upl": "",
          "isoUpl": "",
          "lastPx": "80000.000000",
          "tokenPx": "80000.000000",
          "totalLever": ""
        }
      ]
    }
  ]
}

GET /account/positions - Positions#

Retrieves perp positions for the master account or a specified sub-account. Spot does not create positions.

Request Parameters

ParameterTypeRequiredDescription
assetIdStringNoperp instrument ID. Omit to return all positions.
vaultAddressStringNoSub-account address. Omit to query the master account.

Request Examples

text
GET /api/v5/exchangeos/account/positions
GET /api/v5/exchangeos/account/positions?assetId=602
GET /api/v5/exchangeos/account/positions?assetId=602&vaultAddress=0x6d1a19e1e03b83163fb38d7336b58875e71c50c2

Response Fields

FieldTypeDescription
block_heightStringOn-chain block height corresponding to the query result.
block_timestampStringOn-chain block time corresponding to the query result, as a Unix timestamp in milliseconds.
assetIdStringInstrument ID.
assetStatusStringInstrument status.
positionSideStringPosition side: net, long, or short.
marginModeStringMargin mode: cross or isolated.
leverageStringCurrent position leverage.
posStringPosition size. Short positions use a negative value.
avgPxStringAverage entry price.
markPxStringMark price.
positionValueStringPosition notional value.
uplStringUnrealized PnL.
uplRatioStringUnrealized PnL ratio.
liqPxStringEstimated liquidation price.
imrStringInitial margin rate.
marginStringPosition margin.
mmrStringMaintenance margin requirement.
mgnRatioStringMargin ratio.
realizedPnlStringRealized PnL.
feeStringTrading fee.
fundingFeeStringFunding fee.
tradeIdStringMost recent trade ID.
closeOrderAlgoArrayClosing TPSL orders associated with the position.
> oidStringOrder ID.
> assetIdStringInstrument ID.
> assetStatusStringInstrument status.
> sideStringOrder side: buy or sell.
> positionSideStringPosition side being reduced.
> marginModeStringMargin mode.
> priceStringOrder price.
> sizeStringOrder size.
> reduceOnlyBooleanWhether the order is Reduce-Only.
> triggerPxStringTrigger price.
> triggerPriceTypeStringTrigger price type: mark or index.
> triggerCondStringTrigger condition: Gte or Lte.
> isMarketBooleanWhether the order executes at market after triggering.
> tpslStringTPSL type: tp or sl.
> parentOrderIdStringParent order ID. Empty when no parent order exists.
> isActiveBooleanWhether the order is active.
> tpLimitBooleanWhether the order is a TP Limit order.

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "block_height": "12092417",
      "block_timestamp": "1785218400074",
      "assetId": "602",
      "assetStatus": "normal",
      "positionSide": "long",
      "marginMode": "isolated",
      "leverage": "20",
      "pos": "1.500",
      "avgPx": "3000.000",
      "markPx": "3020.000",
      "positionValue": "4530.000",
      "upl": "30.000",
      "uplRatio": "0.132450",
      "liqPx": "2864.100",
      "imr": "",
      "margin": "226.500000",
      "mmr": "22.650",
      "mgnRatio": "0.088304",
      "realizedPnl": "-2.265",
      "fee": "-2.265",
      "fundingFee": "0.000",
      "tradeId": "776",
      "closeOrderAlgo": [
        {
          "oid": "32733862",
          "assetId": "602",
          "assetStatus": "normal",
          "side": "sell",
          "positionSide": "long",
          "marginMode": "isolated",
          "price": "0",
          "size": "0",
          "reduceOnly": true,
          "triggerPx": "3200.000",
          "triggerPriceType": "mark",
          "triggerCond": "Gte",
          "isMarket": true,
          "tpsl": "tp",
          "parentOrderId": "",
          "isActive": true,
          "tpLimit": false
        }
      ]
    },
    {
      "assetId": "602",
      "assetStatus": "normal",
      "positionSide": "short",
      "marginMode": "isolated",
      "leverage": "10",
      "pos": "-2.000",
      "avgPx": "3100.000",
      "markPx": "3020.000",
      "positionValue": "6040.000",
      "upl": "160.000",
      "uplRatio": "0.258065",
      "liqPx": "3394.900",
      "imr": "",
      "margin": "620.000000",
      "mmr": "30.200",
      "mgnRatio": "0.038718",
      "realizedPnl": "-3.100",
      "fee": "-3.100",
      "fundingFee": "0.000",
      "tradeId": "777",
      "closeOrderAlgo": [
        {
          "oid": "32733863",
          "assetId": "602",
          "assetStatus": "normal",
          "side": "buy",
          "positionSide": "short",
          "marginMode": "isolated",
          "price": "0",
          "size": "0",
          "reduceOnly": true,
          "triggerPx": "3250.000",
          "triggerPriceType": "mark",
          "triggerCond": "Gte",
          "isMarket": true,
          "tpsl": "sl",
          "parentOrderId": "",
          "isActive": true,
          "tpLimit": false
        }
      ]
    }
  ]
}

GET /account/max-size - Maximum Order Size#

Retrieves the maximum buy size, maximum sell size, available funds, and closable position size for a specified instrument and account. Supports querying the closable size in hedge mode.

Request Parameters

ParameterTypeRequiredDescription
assetIdStringYesperp instrument ID.
priceStringNoPrice used to calculate the maximum opening size.
leverageStringNoLeverage used to calculate the maximum opening size.
reduceOnlyBooleanNoWhether to query the maximum Reduce-Only order size.
vaultAddressStringNoSub-account address. Omit to query the master account.

Request Example: Maximum Opening Size

json
{
  "method": "GET",
  "path": "/api/v5/exchangeos/account/max-size",
  "query": {
    "assetId": "102",
    "price": "95000",
    "leverage": "10"
  }
}

Request Example: Maximum Reduce-Only Size

json
{
  "method": "GET",
  "path": "/api/v5/exchangeos/account/max-size",
  "query": {
    "assetId": "102",
    "reduceOnly": true
  }
}

Request Example: Sub-account Query

json
{
  "method": "GET",
  "path": "/api/v5/exchangeos/account/max-size",
  "query": {
    "assetId": "102",
    "price": "95000",
    "leverage": "10",
    "vaultAddress": "0x6d1a19e1e03b83163fb38d7336b58875e71c50c2"
  }
}

Response Fields

FieldTypeDescription
assetIdStringInstrument ID.
maxBuySzStringMaximum buy size.
maxSellSzStringMaximum sell size.
availStringAvailable funds.
longAvailPosStringAvailable long-position size to close. Returns an empty string when not applicable.
shortAvailPosStringAvailable short-position size to close. Returns an empty string when not applicable.

Response Example: oneWay Opening Query

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "maxBuySz": "0.42",
      "maxSellSz": "0.58",
      "avail": "667.09",
      "longAvailPos": "",
      "shortAvailPos": ""
    }
  ]
}

Response Example: hedge With reduceOnly=true

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "maxBuySz": "0.20",
      "maxSellSz": "0.50",
      "avail": "667.09",
      "longAvailPos": "0.50",
      "shortAvailPos": "0.20"
    }
  ]
}

GET /account/position-tiers - Effective User Position Tiers#

perp only. Requires OK-ACCESS-* authentication. Returns the effective tier for the current account and specified contract, including function parameters and the derived limit table. The structure is the same as public GET /market/position-tiers.

Effective Tier Resolution Rules

  1. The system looks up the tier role roleId bound to the user address.
  2. It looks up the special tier configured for the contract and roleId.
  3. If a matching special tier is found, it is used. If the user is not bound to a role, or no special tier is configured for that contract and role, the contract default tier is used.

Accounts bound to special tier roles, such as MM or VIP, must use this endpoint to calculate opening limits and rates instead of using the public default tier.

Request Parameters

ParameterTypeRequiredDescription
assetIdStringYesperp instrument ID.
vaultAddressStringNoSub-account address. Omit to query the master account.

Request Example

text
GET /api/v5/exchangeos/account/position-tiers?assetId=102

Response Fields

Formulas and behavior are the same as GET /market/position-tiers.

FieldTypeDescription
assetIdStringInstrument ID.
positionTierIdStringEffective position tier ID.
roleIdStringEffective tier role ID.
roleNameStringEffective tier role name.
basePositionValue0StringReference position value of the margin-rate curve.
baseMMR0StringBase maintenance margin rate.
baseIMR0StringBase initial margin rate.
mmrChangeRateStringMaintenance margin rate change rate.
imrChangeRateStringInitial margin rate change rate.
maxPositionValueStringMaximum position value.
imrCurvePosValueGridStringPosition-value grid of the initial margin-rate curve.
maxLeverageStringMaximum leverage.
tiersArrayMapping between leverage and maximum allowed position value.
> leverageStringLeverage value.
> maxPositionAllowedStringMaximum allowed position value at this leverage.

Response Example: MM Role With a Matching Special Tier

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "positionTierId": "16",
      "roleId": "1",
      "roleName": "MM",
      "basePositionValue0": "100000",
      "baseMMR0": "0.004",
      "baseIMR0": "0.008",
      "mmrChangeRate": "0.0002",
      "imrChangeRate": "0.0004",
      "maxPositionValue": "10000000",
      "imrCurvePosValueGrid": "10000",
      "maxLeverage": "125",
      "tiers": [
        {
          "leverage": "125",
          "maxPositionAllowed": "100000"
        },
        {
          "leverage": "50",
          "maxPositionAllowed": "3100000"
        },
        {
          "leverage": "1",
          "maxPositionAllowed": "10000000"
        }
      ]
    }
  ]
}

POST /account/set-leverage - Set Leverage#

Sets leverage for a specified perp instrument. The target account is determined by user and the optional vaultAddress.

This endpoint sets leverage only; it does not switch between cross and isolated. The current margin mode is determined by the on-chain account configuration.

General Leverage and Margin-Mode Rules

  • Margin mode is configured by account and assetId.
  • For the same account and assetId, only cross or isolated can be used at a time; the two modes cannot coexist.
  • In hedge mode, long cannot use cross while short uses isolated.
  • A configured leverage value persists and is not changed by closing positions or other trading operations. It remains configured even with no positions and no open orders, and can be changed only by another leverage-setting request.
  • positionSide is optional and nullable. Valid non-empty values are net, long, and short.
  • In oneWay mode or hedge + cross mode, omit positionSide or pass null.
  • In hedge + isolated mode, explicitly pass long or short.

Request Fields

ParameterTypeRequiredDescription
actionObjectYesBusiness action object included in the EIP-712 signature.
> typeStringYesFixed as updateLeverage.
> assetIdStringYesperp instrument ID.
> positionSideStringConditionally requirednet, long, short, or null. Must be long or short in hedge + isolated mode.
> leverageStringYesTarget leverage. Must be an integer greater than or equal to 1.
nonceNumberYesCurrent timestamp in milliseconds, used for signing and replay protection.
userStringYesMaster account address.
vaultAddressStringNoSub-account address. When provided, the specified sub-account is updated.
signatureObjectYesEIP-712 ECDSA signature.
> EcdsaObjectYesECDSA signature object.
>> rStringYesSignature r value prefixed with 0x.
>> sStringYesSignature s value prefixed with 0x.
>> vNumberYesSignature recovery value: 0 or 1.

positionSide Rules

In hedge + isolated mode, each updateLeverage action can modify only one side, either long or short. It cannot modify both sides in a single action.

To modify both long and short, submit two independent requests with different nonce values. The two on-chain transactions execute independently and are not atomic.

Validation and Behavior

  • leverage must be an integer greater than or equal to 1.
  • The maximum permitted leverage is dynamically determined by the current position tier, position value, and opening-order value.
  • oneWay mode does not accept long or short.
  • hedge + cross does not permit an update to only long or short.
  • hedge + isolated requires an explicit long or short.
  • Updating one side in hedge + isolated mode does not affect the leverage of the other side.
  • Increasing leverage does not perform an additional margin validation.
  • Decreasing leverage requires sufficient margin at the target leverage.
  • The request is rejected if the number of open orders exceeds the limit allowed for leverage adjustment. Cancel some open orders first.
  • A request with the same leverage as the current value for the target configuration is treated as a no-op.
  • Leverage configuration does not depend on an existing position and remains stored even if no position exists.

Request Example: oneWay With cross or isolated

positionSide is omitted:

json
{
  "action": {
    "type": "updateLeverage",
    "assetId": "102",
    "leverage": "10"
  },
  "nonce": 1708930000000,
  "user": "0x9a8f...",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Request Example: hedge With cross

Long and short share leverage, so positionSide is also omitted:

json
{
  "action": {
    "type": "updateLeverage",
    "assetId": "102",
    "leverage": "8"
  },
  "nonce": 1708930000001,
  "user": "0x9a8f...",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Request Example: hedge With isolated, Update long

json
{
  "action": {
    "type": "updateLeverage",
    "assetId": "102",
    "positionSide": "long",
    "leverage": "10"
  },
  "nonce": 1708930000002,
  "user": "0x9a8f...",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Request Example: hedge With isolated, Update short

json
{
  "action": {
    "type": "updateLeverage",
    "assetId": "102",
    "positionSide": "short",
    "leverage": "5"
  },
  "nonce": 1708930000003,
  "user": "0x9a8f...",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "txHash": "0x..."
    }
  ]
}

POST /account/set-margin-mode - Set Margin Mode#

Sets the margin mode for a specified perp instrument, switching between cross and isolated.

This is a write operation. The request action is the EIP-712 signing object and must use canonical Action fields.

The configuration scope is:

text
target account × assetId

Master accounts and sub-accounts maintain margin mode independently. Include vaultAddress in the signed envelope when operating on a sub-account.

This endpoint applies only to perp, does not apply to Spot, and does not accept positionSide. In hedge mode, the long and short sides must switch margin mode together.

Margin-Mode Rules

  • Only one margin mode can exist for the same account and assetId.
  • Cross and isolated positions cannot coexist for the same account and assetId.
  • In oneWay mode, the net position for the assetId switches as a whole.
  • In hedge mode, long and short switch together.
  • Switching only long or only short is not allowed.
  • positionSide must not be included in action.
  • Master-account and sub-account configurations are independent.
  • Partially closed positions can still switch margin mode.
  • The switch updates the position marginMode directly; it does not close and reopen positions.
  • Setting the target mode to the current mode is accepted as an idempotent request and leaves the configuration unchanged.
  • An idempotent request does not guarantee an exchangeos-setting-updates event.
  • If the switch fails, the original marginMode, positions, leverage, and funds remain unchanged.

Preconditions

Before switching, the system checks:

  • assetId must exist and be a valid perp instrument.
  • The target marginMode must be supported by the instrument.
  • An isolated-only instrument cannot switch to cross.
  • The same assetId must not have any pending orders, including regular resting orders, Trigger Orders, Order-Attached TPSL, and Position-Attached TPSL.
  • Mark Price must be available.
  • Margin after the switch must satisfy risk-control requirements.
  • When switching hedge + isolated to cross, the long and short leverage values must satisfy the merge rules.

If any condition is not met, the switch fails and the original configuration remains unchanged.

Leverage Inheritance Rules

oneWay

  • cross to isolated: retains the current net leverage.
  • isolated to cross: retains the current net leverage.

hedge + cross to isolated

  • Long and short switch to isolated together.
  • Both long and short initially inherit the shared cross leverage.
  • After the switch, long and short leverage can be adjusted independently through POST /account/set-leverage.

hedge + isolated to cross

  • If long and short both have positions with different leverage, the switch fails.
  • If long and short both have positions with the same leverage, the resulting cross mode uses that shared leverage.
  • If only long has a position, the resulting shared leverage uses the long leverage.
  • If only short has a position, the resulting shared leverage uses the short leverage.
  • If neither long nor short has a position, the shared leverage uses the currently effective account-level setting for the assetId.

Margin Validation: cross to isolated

The system transfers sufficient funds from the cross balance to isolated positions.

Initial margin required for each position:

text
positionIM
= abs(pos) × avgPx ÷ leverage

Additional amount required for negative unrealized PnL:

text
negativeUplBuffer
= abs(min(0, upl))

Required transfer for one position:

text
requiredTransfer
= positionIM + negativeUplBuffer

In hedge mode, if both long and short positions exist, calculate each separately and add them together:

text
requiredTransferTotal
= Σ(positionIM + negativeUplBuffer)

Validation condition:

text
coinMaxTransfer >= requiredTransferTotal

The switch is permitted at equality:

text
coinMaxTransfer == requiredTransferTotal

The request is rejected when:

text
coinMaxTransfer < requiredTransferTotal

After a successful switch:

  • The system transfers requiredTransferTotal from the cross balance to the relevant isolated positions.
  • The position marginMode is updated to isolated.
  • The isolated position balances increase by the transferred amount.

Margin Validation: isolated to cross

The system transfers isolated position balances back to cross and reruns risk validation using the hypothetical post-switch account state.

Validation condition:

text
coinEquityAfter >= coinPerpPosFrozenMarginAfter

Where:

  • coinEquityAfter is the collateral-token equity after hypothetically converting isolated positions to cross.
  • coinPerpPosFrozenMarginAfter is the margin required by all cross perp positions after the hypothetical switch.

The switch is permitted at equality:

text
coinEquityAfter == coinPerpPosFrozenMarginAfter

The request is rejected when:

text
coinEquityAfter < coinPerpPosFrozenMarginAfter

After a successful switch:

  • The relevant isolated position posIsoPerpBalance is transferred back to cross.
  • The position marginMode is updated to cross.
  • The original isolated position balance is reset to zero.
  • Cross margin jointly bears position risk after the switch.

Precision and Boundary Rules

  • Margin validation uses the internal fixed-point precision of the on-chain risk-control system.
  • Calculations must not be truncated or rounded using the display decimal places in API responses.
  • Comparisons use >=; equality with the required amount is sufficient.
  • Even if the difference is smaller than the API display precision, the request is rejected when the internal exact value is below the requirement.
  • API fields such as availBal, availEq, upl, and avgPx are estimates only and cannot guarantee reproduction of the final on-chain validation result.
  • coinMaxTransfer is the internal transferable amount used in risk validation.
  • If OpenAPI does not return coinMaxTransfer directly, use the synchronous receipt or the on-chain result from GET /trade/transaction as the final determination.
  • Having 0.000001 available balance does not by itself mean that funds are sufficient. It must be compared against requiredTransferTotal using internal precision.

Request Fields

ParameterTypeRequiredDescription
actionObjectYesBusiness action object included in the EIP-712 signature. Must not contain positionSide.
> typeStringYesFixed as updateMarginMode.
> assetIdStringYesperp instrument ID.
> marginModeStringYesTarget margin mode: cross or isolated.
nonceNumberYesCurrent timestamp in milliseconds, used for signing and replay protection.
userStringYesMaster account address.
vaultAddressStringNoSub-account address. When provided, the specified sub-account is updated.
signatureObjectYesEIP-712 ECDSA signature.
> EcdsaObjectYesECDSA signature object.
>> rStringYesSignature r value prefixed with 0x.
>> sStringYesSignature s value prefixed with 0x.
>> vNumberYesSignature recovery value: 0 or 1.

Margin mode is a unified assetId-level setting. In hedge mode, long and short for the same assetId must switch together and cannot use different marginMode values.

Request Example: Master Account, cross to isolated

json
{
  "action": {
    "type": "updateMarginMode",
    "assetId": "102",
    "marginMode": "isolated"
  },
  "nonce": 1708930100000,
  "user": "0x742d35cc00000000000000000000000000000000",
  "signature": {
    "Ecdsa": {
      "r": "0x1111111111111111111111111111111111111111111111111111111111111111",
      "s": "0x2222222222222222222222222222222222222222222222222222222222222222",
      "v": 1
    }
  }
}

Request Example: Sub-account, isolated to cross

json
{
  "action": {
    "type": "updateMarginMode",
    "assetId": "102",
    "marginMode": "cross"
  },
  "nonce": 1708930100001,
  "user": "0x742d35cc00000000000000000000000000000000",
  "vaultAddress": "0x6d1a19e1e03b83163fb38d7336b58875e71c50c2",
  "signature": {
    "Ecdsa": {
      "r": "0x1111111111111111111111111111111111111111111111111111111111111111",
      "s": "0x2222222222222222222222222222222222222222222222222222222222222222",
      "v": 1
    }
  }
}

Response: Successful Synchronous Mode

The endpoint synchronously waits for the on-chain receipt. The response structure matches the transaction receipt returned by GET /trade/transaction.

A successful updateMarginMode receipt is Empty and omits response. Clients must not treat a missing response as an error; use status="ok" to determine that on-chain execution succeeded.

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "blockHash": "0xbb177081b88369e4005bbf2098632579441b3b7b9c405a52d4d54fb03df15ee7",
      "blockHeight": "109575200",
      "txHash": "0x518a4e71ad4525b3fa2fad9f4c9284d13e23af022c081b9d065f047976b831a0",
      "txIndex": "0",
      "status": "ok"
    }
  ]
}

After synchronous success:

  • code="0" means OpenAPI successfully retrieved the transaction receipt.
  • status="ok" means updateMarginMode executed successfully on-chain.
  • An omitted response means the successful Action receipt is Empty.
  • Use GET /account/leverage-info to confirm the latest marginMode.
  • If the setting actually changed, the update can also be received through exchangeos-setting-updates.

Response: On-Chain Failure in Synchronous Mode

If the transaction is on-chain but fails business validation, the outer code remains "0", while status is "err". The failure reason is in response.code and response.message.

The following example shows nonce validation failure:

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "blockHash": "0xbb177081b88369e4005bbf2098632579441b3b7b9c405a52d4d54fb03df15ee7",
      "blockHeight": "109575200",
      "txHash": "0x518a4e71ad4525b3fa2fad9f4c9284d13e23af022c081b9d065f047976b831a0",
      "txIndex": "0",
      "status": "err",
      "response": {
        "code": "30004",
        "message": "Nonce validation failed"
      }
    }
  ]
}

In this case:

  • The margin-mode switch failed.
  • The original marginMode remains unchanged.
  • The original positions, leverage, and funds remain unchanged.
  • Do not determine success using only outer code="0".
  • Do not resubmit using the same nonce.

Response: Receipt Not Returned in Time in Synchronous Mode

When the transaction has been accepted but an on-chain receipt is not received during the synchronous wait, the endpoint returns 80106 and preserves txHash in data.

json
{
  "code": "80106",
  "msg": "transaction accepted but receipt notification was not received",
  "data": [
    {
      "txHash": "0x518a4e71ad4525b3fa2fad9f4c9284d13e23af022c081b9d065f047976b831a0"
    }
  ]
}

80106 is not a final failure. The transaction may have executed successfully. Do not submit it again; query the final result using the txHash:

text
GET /api/v5/exchangeos/trade/transaction?txHash=0x518a4e71ad4525b3fa2fad9f4c9284d13e23af022c081b9d065f047976b831a0

POST /account/adjust-isolated-margin - Adjust Isolated Margin#

Adds or removes margin for an isolated position. This is a write operation; the SDK constructs an updateIsolatedMargin action.

The adjustment direction is specified by direction, not by the sign of amount. amount must always be greater than 0.

The target position must already exist. Otherwise, the isolated-margin adjustment fails.

Request Fields

ParameterTypeRequiredDescription
actionObjectYesBusiness action object included in the EIP-712 signature.
> typeStringYesFixed as updateIsolatedMargin.
> assetIdStringYesperp instrument ID.
> positionSideStringYesTarget isolated position side: long or short.
> directionStringYesAdjustment direction: crossToIso adds isolated margin; isoToCross removes isolated margin.
> amountStringYesAdjustment amount. Must be greater than 0.
nonceNumberYesCurrent timestamp in milliseconds, used for signing and replay protection.
userStringYesMaster account address.
vaultAddressStringNoSub-account address. When provided, the specified sub-account is updated.
signatureObjectYesEIP-712 ECDSA signature.

Constraints

  • The target position must exist and use isolated margin mode.
  • The maximum crossToIso amount is the account's available margin.
  • The maximum isoToCross amount is the amount that can be released without violating maintenance margin requirements.

Request Example: Add 100 USDS of Isolated Margin

json
{
  "action": {
    "type": "updateIsolatedMargin",
    "assetId": "102",
    "positionSide": "long",
    "direction": "crossToIso",
    "amount": "100"
  },
  "nonce": 1708930500000,
  "user": "0x9a8f...",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "txHash": "0x..."
    }
  ]
}

POST /account/set-position-mode - Set Position Mode#

Switches between oneWay and hedge. The configuration scope is the account; master accounts and sub-accounts are configured independently.

Preconditions

  • The account must have no positions.
  • The account must have no regular resting orders, Trigger orders, or Attached TPSL orders.
  • A request whose target value equals the current positionMode is treated as a no-op.

Leverage Inheritance Rules

oneWay to hedge

  • Long leverage equals the original net leverage.
  • Short leverage equals the original net leverage.
  • If an assetId currently uses isolated, long and short leverage can be adjusted separately after the switch.

hedge to oneWay

  • Net leverage uses the lower of long leverage and short leverage.

Switching positionMode does not change the current marginMode of any assetId.

Request Fields

ParameterTypeRequiredDescription
actionObjectYesBusiness action object included in the EIP-712 signature.
> typeStringYesFixed as updatePositionMode.
> modeStringYesTarget position mode: oneWay or hedge.
nonceNumberYesCurrent timestamp in milliseconds, used for signing and replay protection.
userStringYesMaster account address.
vaultAddressStringNoSub-account address. When provided, the specified sub-account is updated.
signatureObjectYesEIP-712 ECDSA signature.

Request Example: Switch the Master Account to hedge

json
{
  "action": {
    "type": "updatePositionMode",
    "mode": "hedge"
  },
  "nonce": 1708930550000,
  "user": "0x742d35cc...",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Request Example: Switch a Sub-account to hedge

json
{
  "action": {
    "type": "updatePositionMode",
    "mode": "hedge"
  },
  "nonce": 1708930550001,
  "user": "0x742d35cc...",
  "vaultAddress": "0x6d1a19e1e03b83163fb38d7336b58875e71c50c2",
  "signature": {
    "Ecdsa": {
      "r": "0x...",
      "s": "0x...",
      "v": 1
    }
  }
}

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "txHash": "0x..."
    }
  ]
}

GET /account/leverage-info - Leverage Information#

Retrieves the effective leverage configuration and currently permitted maximum leverage for an account and specified perp instrument.

Request Parameters

ParameterTypeRequiredDescription
assetIdStringYesperp instrument ID.
positionSideStringNoIn hedge + isolated mode, specify long or short.
vaultAddressStringNoSub-account address. Omit to query the master account.

Request Example: All Effective Leverage Settings

text
GET /api/v5/exchangeos/account/leverage-info?assetId=102

Request Example: long in hedge + isolated Mode

text
GET /api/v5/exchangeos/account/leverage-info?assetId=102&positionSide=long

Request Example: Sub-account Query

text
GET /api/v5/exchangeos/account/leverage-info?assetId=102&vaultAddress=0x6d1a19e1e03b83163fb38d7336b58875e71c50c2

Return Rules

  • In hedge + cross mode, maxLeverage must be calculated separately for long and short positions and opening orders. The endpoint returns the lower value because a shared leverage update affects both sides.
  • In hedge + isolated mode, maxLeverage is calculated independently for long and short.

Response Fields

FieldTypeDescription
assetIdStringInstrument ID.
marginModeStringMargin mode: cross or isolated.
positionSideStringPosition side. Returns long or short in hedge + isolated mode.
leverageStringCurrent effective leverage.
maxLeverageStringMaximum leverage currently permitted.

Response Example: oneWay + cross

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "marginMode": "cross",
      "leverage": "10",
      "maxLeverage": "30"
    }
  ]
}

Response Example: oneWay + isolated

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "marginMode": "isolated",
      "leverage": "10",
      "maxLeverage": "25"
    }
  ]
}

These are examples of two independent states. The same account and assetId do not return both cross and isolated simultaneously.

Response Example: hedge + cross

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "marginMode": "cross",
      "leverage": "8",
      "maxLeverage": "20"
    }
  ]
}

Response Example: hedge + isolated

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "marginMode": "isolated",
      "positionSide": "long",
      "leverage": "10",
      "maxLeverage": "30"
    },
    {
      "assetId": "102",
      "marginMode": "isolated",
      "positionSide": "short",
      "leverage": "5",
      "maxLeverage": "20"
    }
  ]
}

GET /account/trade-fee - Trade Fee Rates#

Retrieves trading fee rates for a specified instrument.

Fee sign rules:

  • A positive value means the platform charges a fee.
  • A negative value means a rebate. Actual rates may vary by account level or fee program.

Request Parameters

ParameterTypeRequiredDescription
assetIdStringNoInstrument ID.

Request Example

text
GET /api/v5/exchangeos/account/trade-fee?assetId=102

Response Fields

FieldTypeDescription
assetIdStringInstrument ID.
takerStringTaker fee rate. A positive value is a fee; a negative value is a rebate.
makerStringMaker fee rate. A positive value is a fee; a negative value is a rebate.

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "assetId": "102",
      "taker": "0.000500",
      "maker": "0.000200"
    }
  ]
}

GET /account/bills - Bills#

Retrieves account balance-change records. Each record corresponds to one balance change and is traceable, reconcilable, and idempotent. The endpoint covers perp and spot, follows semantics aligned with order history, and returns at most one year of data.

balChg is a String:

  • A positive value indicates a balance increase or credit.
  • A negative value indicates a balance decrease or debit.
  • For example, a fee debit may be balChg="-0.00196", while fills.fee="0.00196" represents the fee amount. The two fields have different meanings.

Pagination Rules

  • Records are located in data[0].data and are returned in descending order by cTime.
  • Each response returns the next-page token in data[0].nextCursor. The token is opaque; clients must not parse or construct it.
  • Use data[0].hasMore to determine whether to request another page. hasMore=false with nextCursor="" indicates the final page.
  • Do not determine the end of pagination from a returned record count smaller than limit. When filters such as billType or flowCategory are used, a page can contain fewer records than limit while additional data still exists.
  • begin and end are time-window filters only; they are not pagination cursors. When passed with cursor, cursor determines the starting position.
  • Do not pass cursor on the first page.
  • billId is a global monotonic sequence shared across the entire market. It is not guaranteed to be continuous in a single user's view. Do not infer record counts from numeric gaps or treat gaps as lost data. The pagination contract guarantees completeness.

Request Parameters

ParameterTypeRequiredDescription
billTypeStringNoFilters by bill type.
flowCategoryStringNoFilters by fund-flow category.
assetIdStringNoFilters by instrument ID.
beginStringNoStart of the query time window, as a Unix timestamp in milliseconds.
endStringNoEnd of the query time window, as a Unix timestamp in milliseconds.
cursorStringNoPagination token returned by the previous page. Omit for the first page.
limitStringNoNumber of records to return.
vaultAddressStringNoSub-account address. Omit to query the master account.

Request Examples

text
GET /api/v5/exchangeos/account/bills?billType=funding_fee&assetId=102&limit=100
GET /api/v5/exchangeos/account/bills?cursor=1&limit=100
GET /api/v5/exchangeos/account/bills?flowCategory=transfer&begin=1704067200000&end=1704070800000&limit=100

Response Fields

FieldTypeDescription
dataArrayBill records.
> assetIdStringInstrument ID. Returns an empty string when not applicable.
> balStringBalance after the change.
> balChgStringBalance change amount. A positive value is a credit; a negative value is a debit.
> billIdStringBill ID. A global monotonic market-wide sequence; not guaranteed to be continuous for one user.
> billTypeStringBill type.
> cTimeStringBill creation time, as a Unix timestamp in milliseconds.
> flowCategoryStringFund-flow category.
> fromStringSource address. Returns an empty string when not applicable.
> marginModeStringMargin mode. Returns an empty string when not applicable.
> oidStringRelated order ID. Returns an empty string when not applicable.
> toStringDestination address. Returns an empty string when not applicable.
> tokenIdStringToken ID.
> tradeIdStringRelated trade ID. Returns an empty string when not applicable.
hasMoreBooleanWhether additional records are available.
nextCursorStringToken for retrieving the next page. Returns an empty string on the final page.

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "data": [
        {
          "assetId": "",
          "bal": "100",
          "balChg": "+100",
          "billId": "137074380-27-0",
          "billType": "deposit",
          "cTime": "1790068571545",
          "flowCategory": "transfer",
          "from": "",
          "marginMode": "",
          "oid": "",
          "to": "0x112001ee52b6a119272b273f9062208f7d75c6fd",
          "tokenId": "1771",
          "tradeId": ""
        }
      ],
      "hasMore": false,
      "nextCursor": ""
    }
  ]
}

GET /account/detail - Account Details#

Retrieves account Agents, sub-accounts, master-account relationships, user level, and other account-level settings.

Request Parameters

None.

Request Example

text
GET /api/v5/exchangeos/account/detail

Response Fields

FieldTypeDescription
userStringCurrent account address.
parentAccountStringMaster account address. The master account returns an empty string.
subAccountsArraySub-account list.
> addressStringSub-account address.
> positionModeStringSub-account position mode: oneWay or hedge.
positionModeStringCurrent account position mode: oneWay or hedge.
levelStringUser level.
ipStringConfigured IP address list.
agentsArrayAgent list.
> addressStringAgent address.
> statusStringAgent status, such as active or expired.
> expiryStringAgent expiry time, as a Unix timestamp in milliseconds.

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "user": "0x2e988a386a799f506693793c6a5af6b54dfaabfb",
      "parentAccount": "",
      "subAccounts": [
        {
          "address": "0x6d1a19e1e03b83163fb38d7336b58875e71c50c2",
          "positionMode": "hedge"
        },
        {
          "address": "0x93f51fc5190b1e7bb82238bcc2f93430b43a9243",
          "positionMode": "oneWay"
        }
      ],
      "positionMode": "oneWay",
      "level": "VIP5",
      "ip": "117.37.203.58,117.37.203.57",
      "agents": [
        {
          "address": "0xa880d6cc607a05ea617307ab3b0d335e8d8424ee",
          "status": "active",
          "expiry": "1816754400000"
        },
        {
          "address": "0x1563915e194d8cfba1943570603f7606a3115508",
          "status": "expired",
          "expiry": "1785218400000"
        }
      ]
    }
  ]
}

GET /account/limits - Account Limits#

Retrieves the effective on-chain trading limits for the master account or a specified sub-account, including Action allowance, daily cancelAll limit, cancellation exemption allowance, and open-order limits.

Master-account and sub-account limits are recorded and calculated separately by account address. They do not share allowances or usage. For batch transactions, allowance usage is based on the number of transactions in the batch.

Action Limit and actionLimit.used Rules

Each wallet address has an Action allowance for on-chain trading operations:

  • Every wallet address starts with 30,000 Actions.
  • By default, every 1 USD of completed trading volume earns 1 additional Action limit.
  • Regular order placement, cancellation, and modification each consume 1 Action used. cancelAll consumes 5 Actions used.
  • The cancellation limit is min(actionLimit × 2, limit + 200,000).
  • When action_used >= limit, regular Actions enter throttling. When action_used >= cancel_limit, cancellation requests enter throttling.
  • In throttled status, one request may be submitted every 5 seconds.

Request Parameters

ParameterTypeRequiredDescription
vaultAddressStringNoSub-account address. Omit to query the master account; provide it to query the specified sub-account. The gateway verifies that the address belongs to the authenticated user. Master and sub-account limits are recorded and calculated independently.

Request Examples

text
GET /api/v5/exchangeos/account/limits
GET /api/v5/exchangeos/account/limits?vaultAddress=0x6d1a19e1e03b83163fb38d7336b58875e71c50c2

Response Fields

FieldTypeDescription
actionLimitObjectUser Action request allowance.
> initialStringInitial Action allowance.
> earnedStringAction allowance earned from trading volume.
> purchasedStringAction allowance purchased through reserveRequestWeight.
> grantedStringAdditional Action allowance granted through governance settings.
> usedStringCumulative Action allowance consumed since the account began recording. It does not reset daily. Batch operations accumulate based on internal Action count.
> remainingStringCurrently available Action allowance, based on the server-calculated result.
> isThrottledBooleanWhether the account is throttled.
> throttleIntervalMsStringMinimum request interval after throttling, in milliseconds. The current configured value is still returned when not throttled.
cancelAllObjectUser daily cancelAll limit.
> dailyLimitStringTotal allowed cancelAll calls in the current accounting period.
> usedStringcancelAll calls used in the current period. Resets daily.
> remainingStringRemaining cancelAll calls available in the current accounting period.
> periodStartMsStringStart time of the current accounting period, as a Unix timestamp in milliseconds.
> periodEndMsStringEnd time of the current accounting period, as a Unix timestamp in milliseconds.
cancelExemptionObjectDedicated exemption allowance for cancelling existing resting orders after the Action allowance is limited.
> limitStringCumulative exemption allowance available for cancellation operations.
> remainingStringRemaining cancellation exemption allowance.
openOrdersObjectCurrent open-order count and open-order limit.
> currentStringCurrent number of uncompleted orders.
> limitStringCurrently effective open-order limit.
> userOverrideStringOpen-order limit set specifically by an administrator. Returns "" when not configured and "0" when explicitly configured as zero.
block_timestampStringOn-chain block time corresponding to the query result, as a Unix timestamp in milliseconds.
block_heightStringOn-chain block height corresponding to the query result.

When openOrders.userOverride is configured, openOrders.limit uses that value directly. Otherwise:

text
openOrders.limit
= min(
    initial_limit + weighted_volume / volume_per_extra_order,
    max_limit
  )

weighted_volume
= spot trading volume
+ perp trading volume
+ prediction trading volume × prediction_volume_multiplier

Default values:

text
initial_limit = 2000
volume_per_extra_order = 1,000,000
max_limit = 10000
prediction_volume_multiplier = 10

Clients should use openOrders.limit as the actual effective open-order limit.

Response Example

json
{
  "code": "0",
  "msg": "",
  "data": [
    {
      "actionLimit": {
        "initial": "30000",
        "earned": "125000",
        "granted": "0",
        "purchased": "10000",
        "used": "20000",
        "remaining": "145000",
        "isThrottled": false,
        "throttleIntervalMs": "5000"
      },
      "cancelAll": {
        "dailyLimit": "10",
        "periodStartMs": "1789056000000",
        "periodEndMs": "1789142400000",
        "remaining": "8",
        "used": "2"
      },
      "cancelExemption": {
        "limit": "330000",
        "remaining": "320000"
      },
      "openOrders": {
        "current": "128",
        "limit": "2000",
        "userOverride": "0"
      },
      "block_timestamp": "1789092000074",
      "block_height": "12092410"
    }
  ]
}