Get Position History (WebSocket)
Retrieve closed position history for an authenticated subaccount over WebSocket with symbol, time-range, and pagination filters.
Endpoint
ws.send() wss://api.synthetix.io/v1/ws/tradeRequest
Request Format
{
"id": "get-position-history-1",
"method": "post",
"params": {
"action": "getPositionHistory",
"subaccountId": "123456789",
"symbol": "BTC-USDT",
"fromTime": 1769364177000,
"toTime": 1769450577000,
"limit": 50,
"offset": 0,
"signature": {
"v": 27,
"r": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"s": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}
}
}Parameters
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client-generated request identifier |
method | string | Yes | Must be "post" |
params | object | Yes | Request payload container |
Params Object
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be "getPositionHistory" |
subaccountId | string | Yes | Subaccount ID in request payload. The authenticated selected account is enforced server-side for access control |
symbol | string | No | Filter by symbol (for example "BTC-USDT") |
fromTime | integer | No | Start timestamp in milliseconds (inclusive) |
toTime | integer | No | End timestamp in milliseconds (inclusive) |
limit | integer | No | Number of records to return (default: 100) |
offset | integer | No | Number of records to skip (default: 0) |
signature | object | Yes | EIP-712 signature for the request |
This read endpoint does not require nonce management in its request flow.
Response Format
Success Response
{
"id": "get-position-history-1",
"status": 200,
"result": {
"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
}
}Error Response
{
"id": "get-position-history-1",
"status": 400,
"result": null,
"error": {
"code": "VALIDATION_ERROR",
"category": "REQUEST",
"message": "Invalid time range",
"retryable": false
}
}Position History Object
| Field | Type | Description |
|---|---|---|
positionId | string | Unique position identifier |
symbol | string | Trading pair symbol |
side | string | Position side ("long" or "short") |
entryPrice | string | Average entry price |
quantity | string | Position size |
closePrice | string | Execution price of closure |
closeReason | string | Position close reason |
realizedPnl | string | Realized PnL |
accumulatedFees | string | Total fees for the position |
netFunding | string | Net funding paid/received |
closedAt | integer | Position close timestamp in milliseconds |
createdAt | integer | Position creation timestamp in milliseconds |
tradeId | string | Associated trade identifier |
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 |
| Error | Description |
|---|---|
| Invalid request format | Request payload is malformed |
| Invalid subaccount | Subaccount does not exist or is not accessible |
| Invalid time range | fromTime is greater than toTime |
| Invalid pagination | limit 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.