Skip to content

List a portfolio's positions

GET
/portfolios/{id}/positions
curl --request GET \
--url http://localhost:3001/portfolios/00000000-0000-0000-0000-000000000000/positions \
--header 'Authorization: Bearer <token>'
id
required
string format: uuid

Portfolio ID

OK

Media typeapplication/json
Array<object>

A position row as returned by the API.

realized_pnl comes from the projection; the mark-dependent fields are joined in from the in-memory [crate::marks::MarkStore] at request time. They are None when no live mark exists for the instrument — a position we can hold but not value (no market-data source, or the feed is down) is a first-class state, not an error, so it renders as a gap rather than a misleading zero.

object
avg_cost
required
number format: double
instrument_id
required
string
mark

Mid of the current top-of-book quote.

number format: double
nullable
mark_ts

When the mark was received; lets a caller judge staleness.

string format: date-time
nullable
market_value

net_qty * mark * contract_size — signed, so shorts are negative.

number format: double
nullable
net_qty
required
number format: double
portfolio_id
required
string format: uuid
realized_pnl
required
number format: double
unrealized_pnl

(mark - avg_cost) * net_qty * contract_size — signed-correct for shorts.

number format: double
nullable
updated_at
required
string format: date-time

Example generated

[
{
"avg_cost": 1,
"instrument_id": "example",
"mark": 1,
"mark_ts": "2026-04-15T12:00:00Z",
"market_value": 1,
"net_qty": 1,
"portfolio_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"realized_pnl": 1,
"unrealized_pnl": 1,
"updated_at": "2026-04-15T12:00:00Z"
}
]

No view grant for principal/portfolio