Get Trades
Retrieve trade execution history (fills) from Synthetix's orderbook. Each trade represents a filled order or partial fill that has been executed. Returns trades for the specified subaccount.
Endpoint
POST https://papi.synthetix.io/v1/tradeRequest
Request Format
{
"params": {
"action": "getTrades",
"subAccountId": "1867542890123456789",
"symbol": "BTC-USDT",
"limit": 100,
"offset": 0,
"startTime": 1730678400000,
"endTime": 1730764800000
},
"expiresAfter": 1704067300,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Request Parameters
Action Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
params | object | Yes | Request parameters wrapper |
params.action | string | Yes | Must be "getTrades" |
params.subAccountId | string | Yes | SubAccount ID to retrieve trades for |
params.symbol | string | No | Filter trades by market symbol (e.g., "BTC-USDT") |
params.orderId | string | No | Filter trades by venue order ID (only returns trades for this order) |
params.limit | integer | No | Maximum number of trades to return (default: 100, max: 1000) |
params.offset | integer | No | Number of trades to skip for pagination (default: 0) |
params.startTime | integer | No | Start timestamp in milliseconds (inclusive) |
params.endTime | integer | No | End timestamp in milliseconds (inclusive). When both startTime and endTime are provided, the time range cannot exceed 7 days. |
Common Request Parameters
| 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.
:::
| Parameter | Type | Required | Description |
|---|---|---|---|
expiresAfter | integer | No | Optional expiration timestamp in seconds |
Response
Response Structure
| Field | Type | Description |
|---|---|---|
status | string | Always "ok" for successful requests or "error" for failures |
response | object | Response object containing trades array and pagination info (omitted when status is "error") |
response.trades | array | Array of trade objects matching filter criteria |
response.trades[].orderType | string | Order type that produced this trade: "limit", "market", "stopMarket", "takeProfitMarket", "stopLimit", or "takeProfitLimit" |
response.hasMore | boolean | Whether more trades exist beyond current result |
response.total | integer | Total number of trades matching the query |
error | object | Error details (only present when status is "error") |
request_id | string | Request tracking identifier |
Success Response Examples
Multiple Trades with Various Details
{
"status": "ok",
"response": {
"trades": [
{
"tradeId": "123456789",
"order": {
"venueId": "1948058938469519360",
"clientId": "cli-1948058938469519360"
},
"orderId": "1948058938469519360",
"symbol": "BTC-USDT",
"side": "buy",
"direction": "open long",
"orderType": "limit",
"price": "50000.50",
"quantity": "0.1",
"realizedPnl": "125.50",
"fee": "5.00",
"feeRate": "0.001",
"markPrice": "50025.00",
"entryPrice": "49500.00",
"timestamp": 1704067200500,
"maker": false,
"reduceOnly": false,
"triggeredByLiquidation": false,
"postOnly": false
},
{
"tradeId": "123456790",
"order": {
"venueId": "1948058938469519361",
"clientId": "cli-1948058938469519361"
},
"orderId": "1948058938469519361",
"symbol": "ETH-USDT",
"side": "sell",
"direction": "close long",
"orderType": "market",
"price": "2999.25",
"quantity": "1.5",
"realizedPnl": "-75.25",
"fee": "4.50",
"feeRate": "0.001",
"markPrice": "3000.00",
"entryPrice": "2950.00",
"timestamp": 1704067201000,
"maker": true,
"reduceOnly": true,
"triggeredByLiquidation": false,
"postOnly": false
},
{
"tradeId": "123456791",
"order": {
"venueId": "1948058938469519362",
"clientId": "cli-1948058938469519362"
},
"orderId": "1948058938469519362",
"symbol": "BTC-USDT",
"side": "sell",
"direction": "open short",
"orderType": "stopMarket",
"price": "49500.00",
"quantity": "0.05",
"realizedPnl": "0.00",
"fee": "2.48",
"feeRate": "0.001",
"markPrice": "49450.00",
"entryPrice": "50000.00",
"timestamp": 1704067201500,
"maker": false,
"reduceOnly": false,
"triggeredByLiquidation": true,
"postOnly": false
}
],
"hasMore": false,
"total": 3
},
"request_id": "5ccf215d37e3ae6d"
}Single Symbol Filter
{
"status": "ok",
"response": {
"trades": [
{
"tradeId": "123456792",
"order": {
"venueId": "1948058938469519363",
"clientId": "cli-1948058938469519363"
},
"orderId": "1948058938469519363",
"symbol": "BTC-USDT",
"side": "buy",
"direction": "close short",
"orderType": "limit",
"price": "50250.00",
"quantity": "0.2",
"realizedPnl": "50.00",
"fee": "10.05",
"feeRate": "0.001",
"markPrice": "50275.00",
"entryPrice": "50100.00",
"timestamp": 1704067202000,
"maker": false,
"reduceOnly": false,
"triggeredByLiquidation": false,
"postOnly": false
}
],
"hasMore": true,
"total": 150
},
"request_id": "5ccf215d37e3ae6e"
}Empty Result Set
{
"status": "ok",
"response": {
"trades": [],
"hasMore": false,
"total": 0
},
"request_id": "5ccf215d37e3ae6f"
}Trade Object
| Field | Type | Description |
|---|---|---|
tradeId | string | Unique trade execution identifier |
order | object | Canonical composite order identifier |
order.venueId | string | Venue-generated order identifier |
order.clientId | string | Optional client-provided order identifier |
orderId | string | Deprecated legacy venue identifier |
orderType | string | Order type that produced this trade: "limit", "market", "stopMarket", "takeProfitMarket", "stopLimit", or "takeProfitLimit" |
symbol | string | Market symbol (e.g., "BTC-USDT") |
side | string | Trade side: "buy" or "sell" |
price | string | Actual filled price of this trade |
quantity | string | Actual filled quantity of this trade |
realizedPnl | string | Realized P&L from position closure |
fee | string | Trading fee amount |
feeRate | string | Fee rate applied |
timestamp | integer | Trade timestamp (Unix milliseconds) |
maker | boolean | true if maker order, false if taker |
reduceOnly | boolean | true if trade reduced existing position |
postOnly | boolean | true if order was post-only (maker-only) |
markPrice | string | Mark price at time of trade |
entryPrice | string | Position average entry price at time of trade |
triggeredByLiquidation | boolean | true if triggered by liquidation |
direction | string | Position direction after trade |
Trade Field Explanations
| Field | Description |
|---|---|
tradeId | Unique identifier for this specific trade execution |
order.venueId | Canonical venue-generated order ID for this trade |
order.clientId | Optional client-provided order ID for this trade |
orderId | Deprecated legacy order ID field |
orderType | Type of order that generated this trade: "limit", "market", "stopMarket", "takeProfitMarket", "stopLimit", or "takeProfitLimit" |
price | Actual execution price at which this trade was filled (not the mark price or entry price) |
quantity | Actual filled quantity for this trade execution |
realizedPnl | Profit/loss realized from this trade |
fee | Trading fee charged for this execution |
feeRate | Fee rate applied (maker/taker rate) |
markPrice | Mark price at time of trade execution (used for unrealized P&L and liquidations) |
entryPrice | Position's average entry price at time of trade (weighted average of all entries) |
maker | Whether this trade provided liquidity (maker) or took liquidity (taker) |
reduceOnly | Whether this trade reduced an existing position |
triggeredByLiquidation | Whether this trade was part of a liquidation |
postOnly | Whether this order was post-only (maker-only) |
Error Response
{
"status": "error",
"error": {
"message": "Invalid time range: startTime must be less than or equal to endTime",
"code": "VALIDATION_ERROR"
},
"request_id": "5ccf215d37e3ae6d"
}Examples
Get Recent Trades (Own Account)
{
"params": {
"action": "getTrades",
"subAccountId": "1867542890123456789",
"limit": 50
},
"expiresAfter": 1704067300,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Filter by Symbol
{
"params": {
"action": "getTrades",
"subAccountId": "1867542890123456789",
"symbol": "ETH-USDT",
"limit": 100
},
"expiresAfter": 1704067300,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Filter by Order ID
{
"params": {
"action": "getTrades",
"subAccountId": "1867542890123456789",
"orderId": "1948058938469519360"
},
"expiresAfter": 1704067300,
"signature": {
"v": 28,
"r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
}Sorting
Trades are returned in descending order by timestamp (newest first).
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: "getTrades",
expiresAfter: 0
};
const signature = await signer._signTypedData(domain, types, message);Implementation Notes
- Subaccount parameter required for trade retrieval scope
- Explicit time range cannot exceed 7 days (604,800,000 milliseconds) when both
startTimeandendTimeare provided - If only
startTimeis provided, the backend queries up to 7 days afterstartTime, capped at the current time - If only
endTimeis provided, the backend queries the 7 days beforeendTime - If both time bounds are omitted, the backend applies its default 7-day trade-history window
- Pagination supports up to 1000 trades per request (default: 100)
- Time filtering uses inclusive millisecond timestamp bounds
- Symbol filtering reduces response size for multi-market accounts
- Order ID filtering via
orderIdreturns only trades for a specific order (useorder.venueIdfrom trade history as the filter value) - Trade identification uses unique
tradeIdwith canonical order linking viaorder.venueId(orderIdfield on the trade object is deprecated) - The
directionfield indicates the position effect (e.g.,"open long","close long","open short","close short")
Trade Types
Regular Trades
Standard trades from limit or market orders:
- Contains standard execution information
- May be partial fills (group by
order.venueIdto see all fills for the same order)
Liquidation Trades
Forced trades due to insufficient margin:
- Identified by
triggeredByLiquidation: true - Otherwise contains the same fields as regular trades
Maker vs Taker
- Maker: Order added liquidity to the orderbook (
maker: true)- Typically receives fee rebate or reduced fees
- Taker: Order removed liquidity from the orderbook (
maker: false)- Typically pays higher fees
Error Handling
Common Errors
| Error | Description | Solution |
|---|---|---|
Invalid time range | Start time is after end time, or both bounds span more than 7 days | Ensure startTime < endTime and range ≤ 7 days |
Invalid limit | Limit exceeds maximum | Use limit ≤ 1000 |
Invalid offset | Negative offset value | Use offset ≥ 0 |
market name invalid (INVALID_FORMAT) | Market symbol is malformed or not recognized | Use a valid symbol (e.g., "BTC-USDT") from getMarkets |
market name empty (INVALID_FORMAT) | Empty string passed as symbol | Provide a non-empty market symbol |
Invalid orderId | orderId is non-numeric, zero, or exceeds the maximum allowed value | Use a positive numeric string matching a valid venue order ID |
Authentication failed | Invalid signature | Verify signature generation |
Unauthorized access | No permission for specified subAccountId | Ensure you have access to the specified subaccount |
500 Internal Server Error | Trade history contains an unrecognized direction value (e.g. "unknown", "", or any unexpected string) | Indicates corrupted trade direction data on the backend that requires operator investigation. Previously these cases were silently defaulted to side: "buy" in the response. |
Rate Limiting
- Each request counts as 1 against rate limits
- Large queries (high limits) may have higher weight
- Consider caching trade history for frequently accessed data
- See Rate Limits for details
Next Steps
- Place Orders - Create new orders
- Cancel Orders - Cancel existing orders
- WebSocket Trading - Real-time trade updates