Positions

View and manage open positions

Get Positions

Retrieve your current positions. By default returns open positions only.

GET /v1/positions
Authorization: Bearer <token>

Query Parameters:

FieldTypeRequiredDescription
statusstringNoOPEN (default) or CLOSED

Response:

{
  "ok": true,
  "positions": [
    {
      "id": "clx...",
      "accountId": "clx...",
      "venuePositionId": "33600",
      "symbol": "BTCUSDT",
      "quantity": "0.05",
      "avgEntryPrice": "70500.00",
      "markPrice": "71034.50",
      "liquidationPrice": "51493.41",
      "unrealizedPnl": "26.75",
      "realizedPnl": "0",
      "fundingFee": "-1.23",
      "initialMargin": "176.25",
      "maintenanceMargin": "14.10",
      "leverage": 20,
      "marginMode": "Isolated",
      "positionSide": "LONG",
      "status": "OPEN",
      "closeReason": null,
      "closedAt": null,
      "updatedAt": "2026-04-02T22:35:25.456Z"
    }
  ]
}
FieldTypeDescription
idstringInternal position ID. Use this value when calling /v1/positions/close.
venuePositionIdstringExchange-assigned position ID
quantitystringPosition size. Positive = long, negative = short
avgEntryPricestringAverage entry price
markPricestringCurrent mark price from exchange
liquidationPricestringEstimated liquidation price
unrealizedPnlstringUnrealized PnL from exchange
realizedPnlstringRealized PnL from exchange
fundingFeestringAccumulated funding fees
initialMarginstringInitial margin (collateral) for this position
maintenanceMarginstringMaintenance margin requirement
leveragenumberPosition leverage multiplier
marginModestringIsolated or Cross
positionSidestringBOTH (one-way mode), LONG, or SHORT (hedge mode)
statusstringOPEN or CLOSED
closeReasonstring|nullWhy the position was closed: MANUAL, LIQUIDATED, RECONCILED, or UNKNOWN
closedAtstring|nullISO timestamp when position was closed

Position History

Get closed positions by passing status=CLOSED:

GET /v1/positions?status=CLOSED
Authorization: Bearer <token>

Closed positions include a closeReason field:

Close ReasonDescription
MANUALUser closed the position manually
LIQUIDATEDPosition was liquidated (mark price crossed liquidation price)
RECONCILEDExchange confirmed no open position for this record. The local row was cleaned up by the reconciler or the close endpoint's self-heal path.
UNKNOWNClosed during a period when WebSocket was disconnected

Exchange Position History

Paginated closed-position history sourced directly from the exchange. Unlike /v1/positions?status=CLOSED (which returns the local DB view), this endpoint passes through the exchange's authoritative record and includes per-position realizedPnL, fundingFee, and fee fields that are not maintained locally.

GET /v1/futures/positionHistory
Authorization: Bearer <token>

Query Parameters:

FieldTypeRequiredDescription
symbolstringNoFilter to a single symbol. If omitted, results from every symbol the account has ever held are merged.
subAccountIdstringNoSub-account venue id. Resolved from auth context if omitted.
pageintegerNoPage number, default 1
limitintegerNoResults per page, default 500, max 1000
startTimeintegerNoFilter positions opened on or after this Unix ms
endTimeintegerNoFilter positions opened on or before this Unix ms

Response:

{
  "ok": true,
  "data": [
    {
      "positionHistoryId": 1001,
      "positionId": 500,
      "symbol": "BTCUSDT",
      "baseAsset": "BTC",
      "quoteAsset": "USDT",
      "orderSide": 1,
      "marginMode": 0,
      "entryPrice": 50000.00,
      "quoteQuantity": 50.00,
      "contractSize": 1.0,
      "leverage": 20,
      "initialMargin": 2.5,
      "maintenanceMargin": 0.5,
      "liquidationPrice": 48000.00,
      "fundingFee": -0.05,
      "fee": 0.12,
      "realizedPnL": 5.25,
      "markPrice": 50500.00,
      "openedAt": "2026-03-01T10:00:00Z",
      "averageClosePrice": 50500.00,
      "totalClosedQuantity": 0.001,
      "closedAt": "2026-03-02T14:30:00Z",
      "liquidatedAt": null
    }
  ]
}
FieldTypeDescription
positionHistoryIdnumberExchange-assigned id for this history record
positionIdnumberOriginal exchange position id
orderSidenumber1 = Long, 2 = Short
marginModenumber0 = Cross, 1 = Isolated
entryPricenumberAverage entry price
quoteQuantitynumberTotal quote value
leveragenumberLeverage used
fundingFeenumberTotal funding paid (negative) or received (positive) over the life of the position
feenumberTotal trading fees paid
realizedPnLnumberRealized profit and loss as reported by the exchange
averageClosePricenumberAverage price across all closing fills
totalClosedQuantitynumberTotal quantity closed
openedAt / closedAtstringISO timestamps (UTC); closedAt is null if liquidated
liquidatedAtstring|nullLiquidation timestamp, or null if closed normally

Results are sorted by closedAt descending. When symbol is omitted the server iterates every symbol the account has held and merges the pages returned for each — use the symbol parameter for lower latency.


Close Position

Close a specific position at market price by its id. In hedge mode, every position (LONG and SHORT on the same symbol) has its own id, so you close them independently.

POST /v1/positions/close
Authorization: Bearer <token>
Content-Type: application/json

{
  "positionId": "clx..."
}

Parameters:

FieldTypeRequiredDescription
positionIdstringYesThe id field from GET /v1/positions.
quantitystringNoAmount to close. Omit for full close.

No accountId, subAccountId, symbol, or positionSide needs to be sent — the server resolves everything from the authenticated positionId. The reduce-only market order is placed in the opposite direction of the position automatically.

Response — successful close:

{
  "ok": true,
  "closed": {
    "symbol": "BTCUSDT",
    "side": "SELL",
    "quantity": "0.05",
    "remainingPosition": "0"
  },
  "venue": { "orderId": 987654321 }
}

Response — already closed on the exchange (self-heal):

If the exchange reports no open position for this record (error -2010), the server marks the row as CLOSED with closeReason: "RECONCILED" and returns success so the UI can clear it without the user retrying.

{
  "ok": true,
  "closed": {
    "symbol": "BTCUSDT",
    "reconciled": true,
    "note": "Position was already closed on exchange"
  }
}

Response fields:

FieldTypeDescription
closed.symbolstringTrading pair of the closed position
closed.sidestringDirection of the close order: BUY or SELL
closed.quantitystringAmount actually closed
closed.remainingPositionstringRemaining quantity after this close (partial close). "0" on full close.
closed.reconciledbooleantrue only when the position was already closed on the exchange and the DB row was cleaned up without sending a new order
venueobjectRaw order response from the exchange (omitted on reconciled closes)

Risk Exposure

Get aggregated risk metrics across all open positions:

GET /v1/risk/exposure
Authorization: Bearer <token>
{
  "ok": true,
  "grossExposure": "3525.00",
  "positions": [...]
}

On this page