---
title: "Live per-market PnL for a (wallet, market) pair"
method: GET
path: "/pnl/hover/{provider_id}/{wallet}/{contract_id}"
tags: ["PnL"]
---

# Live per-market PnL for a (wallet, market) pair

`GET /pnl/hover/{provider_id}/{wallet}/{contract_id}`

## Request

- Base URL: `https://data.kairos.trade`
- URL: `https://data.kairos.trade/pnl/hover/{provider_id}/{wallet}/{contract_id}`
- Auth: API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`

Live "hover" PnL for a single wallet on a single market, sourced from a fast real-time pipeline — quick regardless of how far back the wallet's earliest trade goes. Returns one row per token held on the contract (e.g. YES + NO for a binary market) plus aggregate totals across those tokens. Only providers on this pipeline are supported: `polymarket`, `opinion`, `predictfun`; `kalshi` and `hyperliquid` are rejected with 400 and must use `/pnl/{user_id}`. When the underlying pipeline is disabled (e.g. while a backfill is ramping), the endpoint returns a well-formed zero/empty payload (`tokens: []`, all totals `0.0`) instead of erroring, matching the "no data" state the frontend already renders gracefully. For API-key callers, the requested provider must additionally have its API access enabled.

## Path parameters

- `provider_id` 'polymarket' | 'opinion' | 'predictfun', required
- `wallet` string, required
- `contract_id` string, required

## Response `200`

Per-token PnL rows and aggregate totals for the wallet on this market. Returns an empty/zeroed payload (not a 404) when the underlying PnL pipeline is disabled.

- PnlWalletMarketPnlResponse: Live hover-on-wallet PnL for a single (wallet, market) pair. Returns a zeroed/empty payload (`tokens: []`) instead of erroring when the underlying PnL pipeline is disabled.
  - `provider_id` 'polymarket' | 'opinion' | 'predictfun', required
  - `wallet_address` string, required
  - `contract_id` string, required
  - `tokens` PnlWalletMarketTokenPnL[], required
    - `token_id` string, required
    - `outcome` string, required
    - `balance` number, double, required
    - `avg_entry_price` number, double, required
    - `cost_basis_usd` number, double, required
    - `realized_pnl_usd` number, double, required
    - `mark_price` number, double, required
    - `position_value_usd` number, double, required
    - `unrealized_pnl_usd` number, double, required
  - `total_unrealized_pnl_usd` number, double, required
  - `total_realized_pnl_usd` number, double, required
  - `total_position_value_usd` number, double, required

## Other responses

- `400`: Missing/oversized `wallet`/`contract_id`, or `provider_id` is not a valid MV-pipeline provider (e.g. kalshi or hyperliquid).
- `401`: No valid credential presented — missing/invalid API-key headers, or an invalid/expired session token.
- `403`: API key missing `position:read` scope, or platform API access disabled for this provider.
- `422`: Request failed FastAPI parameter validation.
- `429`: Rate limit exceeded for this route's sliding window, keyed on the session `sub` when authenticated and on the trusted client IP otherwise. Honor `Retry-After`. A per-API-key data ceiling (set per credential) rejects with `{"detail": "API key data rate limit exceeded"}` instead of the `error` envelope below.
- `500`: Unexpected error fetching hover PnL.
- `503`: Per-venue API-access flag could not be read or validated.

---

[API](https://skmtc.dev/kairos/apis/kairos-data-api.md) - [All operations](https://skmtc.dev/kairos/apis/kairos-data-api/llms.txt) - [OpenAPI document](https://skmtc.dev/kairos/apis/kairos-data-api/revisions/cf6b76079e38?raw)
