Skip to content

Get Position History

Retrieve closed position history for an authenticated subaccount with symbol and time-range filtering plus pagination.

Endpoint

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

Request

Request Format

{
  "params": {
    "action": "getPositionHistory",
    "subaccountId": "123456789",
    "symbol": "BTC-USDT",
    "startTime": 1769364177000,
    "endTime": 1769450577000,
    "limit": 50,
    "offset": 0
  },
  "signature": {
    "v": 27,
    "r": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "s": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
  }
}

Request Parameters

ParameterTypeRequiredDescription
paramsobjectYesRequest parameters wrapper
params.actionstringYesMust be "getPositionHistory"
params.subaccountIdstringYesSubaccount ID in request payload. The authenticated selected account is enforced server-side for access control
params.symbolstringNoFilter by trading pair (for example "BTC-USDT")
params.startTimeintegerNoStart timestamp in milliseconds (inclusive). Maximum range between startTime and endTime is 30 days
params.endTimeintegerNoEnd timestamp in milliseconds (inclusive). Maximum range between startTime and endTime is 30 days
params.limitintegerNoNumber of records to return (default: 100, max: 1000)
params.offsetintegerNoNumber of records to skip (default: 0, max: 10000)
signatureobjectYesEIP-712 signature for the request

This read endpoint does not require nonce management in its request flow.

ParameterTypeRequiredDescription
nonceuint64Yes*Positive integer nonce (must be incrementing and unique per request)
signatureobjectYesEIP-712 signature object
expiresAfteruint64NoUnix 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, getOrdersHistory, getTrades, getFundingPayments, getSubAccount, getSubAccounts, getDelegatedSigners, getBalanceUpdates) do not require the nonce parameter. Only signature and optional expiresAfter are needed. :::

Response

Success Response

{
  "status": "ok",
  "response": {
    "positions": [
      {
        "positionId": "2015847946616049664",
        "symbol": "BTC-USDT",
        "side": "long",
        "entryPrice": "95000",
        "quantity": "0.001",
        "closePrice": "96000",
        "closeReason": "close",
        "realizedPnl": "1",
        "accumulatedFees": "0.1",
        "netFunding": "0",
        "closedAt": 1769450577774,
        "createdAt": 1769450577000,
        "tradeId": "123"
      }
    ],
    "hasMore": false
  },
  "requestId": "abcd1234",
  "request_id": "abcd1234",
  "timestamp": 1769450577774
}

Response Fields

FieldTypeDescription
statusstring"ok" on success, "error" on failure
responseobjectContainer for result data
response.positionsarrayClosed position records for the requested filters
response.hasMorebooleanWhether additional records are available for pagination
requestIdstringRequest tracking identifier
request_idstringLegacy request tracking identifier (same value as requestId)
timestampintegerServer timestamp in milliseconds

Position History Object

FieldTypeDescription
positionIdstringUnique position identifier
symbolstringTrading pair symbol
sidestringPosition side ("long" or "short")
entryPricestringAverage entry price
quantitystringPosition size
closePricestringExecution price of closure
closeReasonstringPosition close reason (for example "close")
realizedPnlstringRealized PnL for this closed position
accumulatedFeesstringTotal fees paid for the position lifecycle
netFundingstringNet funding paid/received
closedAtintegerPosition close timestamp in milliseconds
createdAtintegerPosition creation timestamp in milliseconds
tradeIdstringAssociated trade identifier

Error Response

{
  "status": "error",
  "error": {
    "category": "REQUEST",
    "message": "Invalid time range",
    "code": "VALIDATION_ERROR",
    "retryable": false
  },
  "requestId": "abcd1234",
  "request_id": "abcd1234",
  "timestamp": 1769450577774
}

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: '123456789',
  action: 'getPositionHistory',
  expiresAfter: 0
};
 
const signature = await signer._signTypedData(domain, types, message);

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.

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
ErrorDescription
Invalid request formatRequest payload is malformed
Invalid subaccountSubaccount does not exist or is not accessible
Invalid time rangestartTime is greater than endTime
Time range exceeds maximumstartTime and endTime are more than 30 days apart
Offset exceeds maximumoffset is greater than 10000
Invalid paginationlimit or offset is outside accepted bounds

symbol is a filter field, but this endpoint does not document dedicated symbol-validation errors in its handler path.