---
title: "Every wallet's positions on a chain, shaped exactly as the app's Portfolio page renders them"
method: GET
path: "/v1/ops/portfolios"
tags: ["Ops"]
---

# Every wallet's positions on a chain, shaped exactly as the app's Portfolio page renders them

`GET /v1/ops/portfolios`

## Request

- Base URL: `https://api.spiralstake.xyz`
- URL: `https://api.spiralstake.xyz/v1/ops/portfolios`
- Auth: HTTP bearer

Internal monitoring surface. Requires a key on the `ops` tier. Per wallet: the header totals, open loops, open equity vaults, closed/liquidated positions (closed vaults re-skinned as the vault), and dashboard rows with nothing behind them on chain. Values are unformatted decimal strings (format with the app's displayTokenAmount). `dbDrift` flags dashboard/chain disagreements the app silently self-heals. Cached 60s; `stale`/`degraded` flag older numbers.

## Query parameters

- `chainId` 1 | 4663

## Response `200`

Portfolios

- object
  - `chainId` integer
  - `asOf` string
  - `stale` boolean
  - `degraded` boolean
  - `computedAt` string
  - `counts` object
  - `users` object[]

## Other responses

- `400`: Invalid input
- `401`: Missing/invalid API key
- `429`: Rate limited
- `503`: Transient (stale data / no route / RPC) — retry

---

[API](https://skmtc.dev/spiralstake/apis/spiral-stake-read-api-v1.md) · [All operations](https://skmtc.dev/spiralstake/apis/spiral-stake-read-api-v1/llms.txt) · [OpenAPI document](https://skmtc.dev/spiralstake/apis/spiral-stake-read-api-v1/revisions/e58af20cd747?raw)
