Exchange Collateral
Swap one collateral asset for another within a subaccount. The platform uses current oracle prices to determine the exchange rate.
Endpoint
POST https://papi.synthetix.io/v1/tradeRequest
Request Format
{
"params": {
"action": "exchangeCollateral",
"subAccountId": "1867542890123456789",
"fromSymbol": "ETH",
"toSymbol": "USDT",
"fromAmount": "0.5"
},
"nonce": 1704067200000,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
},
"expiresAfter": 1704067300
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
params | object | Yes | Parameters object containing method details |
params.action | string | Yes | Must be "exchangeCollateral" |
params.subAccountId | string | Yes | Subaccount identifier |
params.fromSymbol | string | Yes | Source collateral asset symbol (e.g., "ETH") |
params.toSymbol | string | Yes | Destination collateral asset symbol (e.g., "USDT") |
params.fromAmount | string | Yes | Amount of the source asset to exchange, as a decimal string |
nonce | integer (uint64) | Yes | Positive integer, incrementing nonce |
signature | object | Yes | EIP-712 signature object |
expiresAfter | integer | No | Expiration timestamp in Unix milliseconds (optional) |
| Parameter | Type | Required | Description |
|---|---|---|---|
nonce | uint64 | Yes* | Positive integer nonce (must be incrementing and unique per request) |
signature | object | Yes | EIP-712 signature object |
expiresAfter | uint64 | No | Unix milliseconds expiration timestamp (5x rate limit on stale cancels) |
:::info Common Parameters
These are top-level request parameters. The subAccountId parameter is specified within the params object (see each endpoint's parameter table).
:::
:::info SubAccountAction Endpoints
Endpoints using SubAccountAction signing (getPositions, getOpenOrders, getOrderHistory, getTrades, getFundingPayments, getSubAccount, getSubAccounts, getDelegatedSigners, getBalanceUpdates, getWithdrawableAmounts, getFeeRate, getSnaxpotEpochTickets) do not require the nonce parameter. Only signature and optional expiresAfter are needed.
:::
Response
Success Response
{
"status": "ok",
"response": {
"fromSymbol": "ETH",
"toSymbol": "USDT",
"fromAmount": "0.5",
"toAmount": "1250.00"
},
"request_id": "5ccf215d37e3ae6d"
}Response Fields
| Field | Type | Description |
|---|---|---|
fromSymbol | string | Source collateral asset symbol |
toSymbol | string | Destination collateral asset symbol |
fromAmount | string | Amount exchanged from the source asset |
toAmount | string | Amount received in the destination asset |
Error Response
{
"status": "error",
"error": {
"message": "collateral price stale: order rejected",
"code": "COLLATERAL_PRICE_STALE"
},
"request_id": "5ccf215d37e3ae6d"
}Common Errors
| Error Code | Description | Action |
|---|---|---|
COLLATERAL_PRICE_STALE | Source asset price exceeds the staleness threshold | Wait for fresh oracle prices; do not retry immediately |
INSUFFICIENT_MARGIN | Exchange would leave the account under margin requirements | Reduce exchange amount or add collateral |
INVALID_VALUE | Asset symbol is not a recognized collateral type | Check supported collaterals via POST /v1/info (getCollaterals) |
Implementation Notes
COLLATERAL_PRICE_STALEis a non-retryable trading rejection (error categoryTrading), not an internal server error — treat it as a transient condition and wait for oracle prices to refresh before retryingfromAmountmust conform to the source asset'sQuantityPrecision; queryPOST /v1/info (getAssets)for the allowed precision- Exchange rates are determined by current oracle prices at execution time
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, getOrderHistory, getTrades, getFundingPayments, getSubAccount, getSubAccounts, getDelegatedSigners, getBalanceUpdates, getWithdrawableAmounts, getFeeRate, getSnaxpotEpochTickets) do not require a nonce. Only the signature and optional expiresAfter parameters are needed.
:::
Error Handling
| Error Code | Description | Retryable |
|---|---|---|
UNAUTHORIZED | EIP-712 signature validation failed | No |
VALIDATION_ERROR | Request validation failed | No |
MISSING_REQUIRED_FIELD | Required field is missing | No |
INVALID_FORMAT | Field format is invalid | No |
INVALID_VALUE | Invalid parameter value | No |
RATE_LIMIT_EXCEEDED | Too many requests in time window | Yes |
INSUFFICIENT_MARGIN | Not enough margin for trade | No |
ORDER_NOT_FOUND | Order does not exist | No |
OPERATION_TIMEOUT | Operation timed out | Yes |
Related
- Get Collaterals — List supported collateral assets
- Get Subaccount — Check current collateral balances
- Withdraw Collateral — Withdraw collateral to an external wallet
