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>'import requests
url = "http://localhost:3001/portfolios/00000000-0000-0000-0000-000000000000/positions"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.json())use reqwest;
#[tokio::main]pub async fn main() { let url = "http://localhost:3001/portfolios/00000000-0000-0000-0000-000000000000/positions";
let mut headers = reqwest::header::HeaderMap::new(); headers.insert("Authorization", "Bearer <token>".parse().unwrap());
let client = reqwest::Client::new(); let response = client.get(url) .headers(headers) .send() .await;
let results = response.unwrap() .json::<serde_json::Value>() .await .unwrap();
dbg!(results);}Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”id
required
string format: uuid
Portfolio ID
Responses
Section titled “Responses”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
mark_ts
When the mark was received; lets a caller judge staleness.
string format: date-time
market_value
net_qty * mark * contract_size — signed, so shorts are negative.
number format: double
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
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