Positions & Orders
Base URL: https://service.leverup.xyz
These endpoints return indexed data across all markets in one request, which is the main reason to prefer them over getPositionsV4 — the contract read takes one pairBase at a time. They also cover closed positions, which the contract does not retain.
The trade-off is indexing lag: a position appears here a moment after it appears onchain. For anything latency-sensitive, read the contract.
Open positions
GET /v1/user/{user_address}/open-positions| Parameter | Default | Notes |
|---|---|---|
block_chain | MONAD | |
page | 0 | |
size | 20 | Capped at 100 |
Response
{
"content": [
{
"positionHash": "0x…",
"pair": "BTC/USD",
"pairBase": "0xcf5a…",
"trader": "0x…",
"tokenIn": "0x7547…",
"marginToken": "0xfd44…",
"isLong": true,
"margin": "9930000000000000000",
"qty": "10000000",
"entryPrice": "100123450000000000000000",
"stopLoss": "0",
"takeProfit": "0",
"openFee": "70000000000000000",
"executionFee": "0",
"longAccFundingFeePerShare": "0",
"holdingFeeRate": "0",
"timestamp": 1785312000,
"status": "OPEN",
"closeInfo": null
}
],
"pageNumber": 0,
"pageSize": 20,
"totalPages": 1,
"totalElements": 1
}| Field | Unit |
|---|---|
qty | 1e10 |
entryPrice, stopLoss, takeProfit | 1e18 |
margin, openFee, executionFee | marginToken decimals — 18 for LVUSD and LVMON |
holdingFeeRate | 1e12 |
longAccFundingFeePerShare | 1e18, signed |
timestamp | Unix seconds |
marginToken is the lvToken. Every amount above is denominated in it, not in tokenIn.
Accrued fees are not here
This endpoint returns the position as indexed at open time. Live accrued funding and holding fees come from getPositionsV4 onchain.
All positions
Open, closing, closed and cancelled.
GET /v1/user/{user_address}/positions| Parameter | Default | Notes |
|---|---|---|
block_chain | MONAD | |
page | 0 | |
size | 20 | Capped at 100 |
timestamp_after | — | Only positions opened after this Unix second |
close_time_after | — | Only positions closed after this Unix second |
Same shape as above, plus a populated closeInfo for closed positions:
{
"positionHash": "0x…",
"status": "CLOSED",
"closeInfo": {
"closePrice": "101500000000000000000000",
"fundingFee": "-1200000000000000",
"closeFee": "70000000000000000",
"pnl": "1370000000000000000",
"holdingFee": "500000000000000",
"closeTime": 1785315600
}
}status | Meaning |
|---|---|
PENDING | Requested, not yet filled |
OPEN | Live |
CLOSING | Close requested, not yet settled |
CLOSED | Settled |
CANCELLED | Never opened — refunded |
closeInfo is present for CLOSED, and for CLOSING once the PnL is known. fundingFee and pnl are signed. All amounts use marginToken decimals.
async function realizedPnl(address: string, sinceUnix: number) {
const res = await fetch(
`${API}/v1/user/${address}/positions?close_time_after=${sinceUnix}&size=100`,
)
const { content } = await res.json()
return content
.filter((p: any) => p.status === 'CLOSED')
.reduce((sum: bigint, p: any) => sum + BigInt(p.closeInfo.pnl), 0n)
}Limit orders
There is no public per-user limit-order endpoint. Read them onchain with getLimitOrders, and TP/SL orders with getTraderDecreaseOrders.
Order lifecycle events do appear in trade history, so a completed order is visible there after the fact.