Get Positions
Retrieve detailed information about positions for the authenticated subaccount with time range filtering and pagination. This unified endpoint supports both current and historical position data.
Endpoint
POST https://papi.synthetix.io/v1/tradeRequest
Request Format
{
"params": {
"action": "getPositions",
"subAccountId": "1867542890123456789",
"status": "open",
"symbol": "BTC-USDT",
"startTime": 1704067200000,
"endTime": 1704153600000,
"limit": 50,
"offset": 0,
"sortBy": "createdAt",
"sortOrder": "desc"
},
"expiresAfter": 1735689900,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
params | object | Yes | Request parameters wrapper |
params.action | string | Yes | Must be "getPositions" |
params.subAccountId | string | Yes | SubAccount ID to retrieve positions for |
params.status | string | No | Filter by position status: "open", "close", or "update" |
params.symbol | string | No | Filter by market symbol (e.g., "BTC-USDT"). Case-insensitive; normalized to uppercase. Validated against known markets |
params.startTime | integer | No | Start time in Unix milliseconds (inclusive) |
params.endTime | integer | No | End time in Unix milliseconds (inclusive) |
params.fromTime | integer | No | Deprecated — use startTime instead |
params.toTime | integer | No | Deprecated — use endTime instead |
params.limit | integer | No | Maximum number of positions to return (default: 50) |
params.offset | integer | No | Number of positions to skip for pagination (default: 0) |
params.sortBy | string | No | Field to sort results by |
params.sortOrder | string | No | Sort direction: "asc" or "desc" |
| 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
Response Structure
| Field | Type | Description |
|---|---|---|
status | string | Always "ok" for successful requests or "error" for failures |
response | array | Array of position objects matching filter criteria (omitted when status is "error") |
error | object | Error details (only present when status is "error") |
request_id | string | Client-provided request identifier echoed back from the request |
Success Response Examples
Multiple Positions (Open and Closed)
{
"status": "ok",
"response": [
{
"adlBucket": 1,
"positionId": "pos_12345",
"subAccountId": "1867542890123456789",
"symbol": "ETH-USDT",
"side": "long",
"entryPrice": "3000.00",
"quantity": "0.5000",
"realizedPnl": "150.00",
"unrealizedPnl": "0.00",
"usedMargin": "0.00",
"maintenanceMargin": "0.00",
"liquidationPrice": "0.00",
"status": "close",
"netFunding": "8.50",
"takeProfitOrders": [],
"takeProfitOrderIds": [],
"stopLossOrders": [],
"stopLossOrderIds": [],
"updatedAt": 1735689600000,
"createdAt": 1735686000000
},
{
"adlBucket": 4,
"positionId": "pos_12346",
"subAccountId": "1867542890123456789",
"symbol": "BTC-USDT",
"side": "short",
"entryPrice": "42000.00",
"quantity": "0.1000",
"realizedPnl": "0.00",
"unrealizedPnl": "-12.50",
"usedMargin": "840.00",
"maintenanceMargin": "420.00",
"liquidationPrice": "45000.00",
"status": "open",
"netFunding": "8.50",
"takeProfitOrders": [],
"takeProfitOrderIds": [],
"stopLossOrders": [
{
"venueId": "2026771048053084162",
"clientId": "cli-sl_002"
}
],
"stopLossOrderIds": ["2026771048053084162"],
"updatedAt": 1735689600000,
"createdAt": 1735680000000
}
],
"request_id": "5ccf215d37e3ae6d"
}Open Positions Only
{
"status": "ok",
"response": [
{
"adlBucket": 2,
"positionId": "pos_12347",
"subAccountId": "1867542890123456789",
"symbol": "BTC-USDT",
"side": "long",
"entryPrice": "43500.00",
"quantity": "0.2000",
"realizedPnl": "0.00",
"unrealizedPnl": "200.00",
"usedMargin": "1740.00",
"maintenanceMargin": "870.00",
"liquidationPrice": "41000.00",
"status": "open",
"netFunding": "8.50",
"takeProfitOrders": [
{
"venueId": "2026771048053084163",
"clientId": "cli-tp_001"
}
],
"takeProfitOrderIds": ["2026771048053084163"],
"stopLossOrders": [
{
"venueId": "2026771048053084164",
"clientId": "cli-sl_003"
}
],
"stopLossOrderIds": ["2026771048053084164"],
"updatedAt": 1735689700000,
"createdAt": 1735689000000
}
],
"request_id": "5ccf215d37e3ae6e"
}Empty Result Set
{
"status": "ok",
"response": [],
"request_id": "5ccf215d37e3ae6f"
}Position Object
| Field | Type | Description |
|---|---|---|
adlBucket | integer | ADL priority bucket (1–5). 5 = highest risk, 1 = lowest risk. Defaults to 1 until ranked. |
positionId | string | Position identifier |
subAccountId | string | Subaccount identifier |
symbol | string | Trading symbol (e.g., "BTC-USDT") |
side | string | Position side: "long" or "short" |
entryPrice | string | Average entry price |
quantity | string | Position size/quantity |
realizedPnl | string | Realized profit/loss |
unrealizedPnl | string | Unrealized profit/loss |
usedMargin | string | Margin used for this position |
maintenanceMargin | string | Maintenance margin required |
liquidationPrice | string | Position liquidation price |
status | string | Position status: "open", "close", "update" |
netFunding | string | Net funding payments (positive = received) |
takeProfitOrders | array[object] | Canonical take-profit order ID objects (venueId, optional clientId) |
takeProfitOrderIds | array[string] | Deprecated take-profit venue identifiers |
stopLossOrders | array[object] | Canonical stop-loss order ID objects (venueId, optional clientId) |
stopLossOrderIds | array[string] | Deprecated stop-loss venue identifiers |
updatedAt | integer | Last update timestamp (Unix milliseconds, not seconds!) |
createdAt | integer | Creation timestamp (Unix milliseconds, not seconds!) |
Migration Note: Use takeProfitOrders[*].venueId and stopLossOrders[*].venueId as canonical order references. takeProfitOrderIds and stopLossOrderIds are deprecated compatibility fields.
Position Status Types
| Status | Description | Characteristics |
|---|---|---|
open | Active position | Has unrealized PnL, margin requirements, liquidation price |
close | Closed position | Only realized PnL, no margin requirements |
update | Position being updated | Transitional state during modifications |
Position Calculations
realizedPnl: Profit/loss from closed portions of the positionunrealizedPnl: Current profit/loss based on mark price (open positions only)usedMargin: Margin currently allocated to this positionmaintenanceMargin: Minimum margin for position maintenanceliquidationPrice: Price at which position would be liquidated (open positions only)entryPrice: Volume-weighted average price of all fills that opened the positionnetFunding: Net funding payments received/paid for this positionadlBucket: Auto-Deleveraging priority bucket (1–5). Positions in bucket 5 are the first to be auto-deleveraged in a liquidation event. Buckets are assigned per market per side based on PnL ratio and effective leverage, recalculated periodically. New positions default to bucket 1 until the next ranking cycle.
Error Response
{
"status": "error",
"error": {
"message": "Failed to get positions",
"code": "INTERNAL_ERROR"
},
"request_id": "5ccf215d37e3ae6d"
}Code Examples
Get All Open Positions
{
"params": {
"action": "getPositions",
"subAccountId": "1867542890123456789",
"status": "open",
"limit": 50
},
"expiresAfter": 1735689900,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Position Information
- Real-time Data: Open position data is updated in real-time with current mark prices and PnL
- Risk Metrics: Includes liquidation prices, margin requirements, and position-level risk assessment
- Order Links: References to associated take profit and stop loss orders
- Detailed Margins: Both used margin and maintenance margin requirements
- USDT Denomination: All monetary values are denominated in USDT for consistency
- Performance Tracking: Comprehensive PnL, volume, and fee tracking per position
Code Example
EIP-712 Signature
const domain = {
name: "Synthetix",
version: "1",
chainId: 1,
verifyingContract: "0x0000000000000000000000000000000000000000"
};
const types = {
SubAccountAction: [
{ name: "subAccountId", type: "uint256" },
{ name: "action", type: "string" },
{ name: "expiresAfter", type: "uint256" }
]
};
const message = {
subAccountId: "1867542890123456789",
action: "getPositions",
expiresAfter: Math.floor(Date.now() / 1000) + 60 // 1 min from now
};
const signature = await signer._signTypedData(domain, types, message);Implementation Notes
- Authentication requires signature by account owner or authorized delegate
- Subaccount ID must be valid and accessible to requesting wallet
- Pagination: Use
limitandoffsetparameters for result pagination - When
symbolis omitted, all positions for the subaccount are returned - When
symbolis provided, only positions for that market are returned. The filter is case-insensitive and normalized to uppercase (for example"eth-usdt"becomes"ETH-USDT") - An unknown or invalid
symbolreturns a validation error before query execution
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
Common error scenarios:
| 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 |