---
title: "Get wallet portfolio summary"
method: GET
path: "/v4/data/prediction/wallets/{address}/portfolio"
tags: ["Prediction API"]
---

# Get wallet portfolio summary

`GET /v4/data/prediction/wallets/{address}/portfolio`

/v4/data/prediction/wallets/{address}/portfolio

**200 credits per API call**

Aggregated portfolio summary for a single wallet. Returns position counts (open, redeemable, closed), unrealised and realised PnL, total cost basis, active notional, win rate and ROI — all computed over the requested `period`. Useful as the headline KPI block on a wallet detail page.

**Platform support**

*   Polymarket only. Passing any non-EVM address returns `400`.

**Filtering**

*   `period` selects the lookback window for closed-position aggregates: `24h`, `7d`, `30d` or `all`. Defaults to `all`.
*   Open-position counts and `activeNotional` are always live (the period only affects closed-position roll-ups).

**Other notes**

*   `address` is normalised to lowercase before being echoed back in the response.
*   `winRate` is a percentage in `[0, 100]` (e.g. `42.5` = 42.5%). It is `null` when `closedPositions` is zero — the ratio is undefined, not zero.
*   `roi` is realised ROI as a percentage (e.g. `23.45` = 23.45%). Computed from realised PnL over total cost basis of closed positions only — unrealised PnL is excluded. `null` when `totalCostBasis` is zero.
*   `redeemablePositions` is the count of positions on a resolved market that the wallet has won but has not yet redeemed. Disjoint from both `openPositions` and `closedPositions` — tracked separately so the count of currently actionable positions is visible.

## Path parameters

- `address` string, required — EVM wallet address — `0x`-prefixed, 40 hex characters. Returned lowercased in response payloads. Non-EVM inputs (e.g. Kalshi user identifiers) return `400` from every wallets endpoint.

## Query parameters

- `period` '24h' | '7d' | '30d' | 'all' — Window for `totalPnl` and the settlement counts (`closedPositions`/`wins`/`losses`/ `winRate`) on `/wallets/{address}/portfolio`. `totalCostBasis`/`realizedPnl`/`roi` are all-time regardless.

## Response `200`

OK

- PredictionPortfolioResponse — Wallet portfolio summary response.
  - `data` PredictionPortfolio, required — Server-aggregated wallet summary. Synthesised from the wallet's current open positions, redeemable positions, total notional and closed-position roll-ups within the requested `period`.
    - `address` string, required — Wallet address, lowercased.
    - `period` '24h' | '7d' | '30d' | 'all', required — Window for `totalPnl` and the settlement counts (`closedPositions`/`wins`/`losses`/ `winRate`) on `/wallets/{address}/portfolio`. `totalCostBasis`/`realizedPnl`/`roi` are all-time regardless.
    - `generatedAt` string, date-time, required — ISO-8601 timestamp the snapshot was computed at.
    - `openPositions` integer, required — Count of currently open positions.
    - `redeemablePositions` integer, required — Count of positions on a resolved market that the wallet has won but has not yet redeemed. Disjoint from `openPositions` and `closedPositions`.
    - `activeNotional` number, required — Total USD notional of currently open positions (rounded to 2dp).
    - `unrealizedPnl` number, required — Sum of unrealised PnL across currently open positions.
    - `closedPositions` integer, required — Count of closed positions within the requested `period`.
    - `wins` integer, required — Count of winning closed positions within the requested `period`.
    - `losses` integer, required — Count of losing closed positions within the requested `period`.
    - `winRate` number, nullable, required — Win rate as a percentage in [0, 100]. `null` when `closedPositions` is 0 — the ratio is undefined, not zero.
    - `totalCostBasis` number, required — All-time cost basis in USDC across all closed positions (full history) — NOT windowed by `period`. Computed per position as shares bought × average buy price (`totalBought * avgPrice`); upstream `totalBought` is a share quantity, not a dollar amount.
    - `realizedPnl` number, required — All-time realised PnL in USDC across all closed positions — NOT windowed by `period` (same lifetime-attribution reason as `totalCostBasis`). Does not reconcile with the windowed `totalPnl`. Upstream reports 0 for positions won by redemption (the payout is omitted); for those we recompute it as shares × (resolutionPrice − avgPrice) so winnings are credited.
    - `totalPnl` number, required — Profit/loss matching the public profile page (Polymarket `/user-pnl`). For `period=all` it is the wallet's current all-time P&L; for `24h`/`7d`/`30d` it is the P&L generated *during* that trailing window. NOT the arithmetic sum of `realizedPnl` and `unrealizedPnl`. Windowed values track the website rather than matching to the cent (open positions mark-to-market intraday); `period=all` is exact.
    - `roi` number, nullable, required — All-time realised ROI as a percentage — NOT windowed by `period`. `realizedPnl` over `totalCostBasis` (both all-time); unrealised PnL is excluded. `null` when `totalCostBasis` is 0.

## Other responses

- `400` — Bad Request
- `401` — Unauthorized. Not valid or inactive subscription key present in the HTTP Header.
- `403` — Forbidden. The request is authenticated, but it is not possible to perform the operation due to logical error or invalid permissions.
- `500` — Internal server error. There was an error on the server during the processing of the request.

---

[API](https://skmtc.net/tatum/apis/blockchain-data.md) · [All operations](https://skmtc.net/tatum/apis/blockchain-data/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/tatum/blockchain-data/versions/8622ee4b8fae/schema)
