> ## Documentation Index
> Fetch the complete documentation index at: https://docs.exponent.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Historical vault holders and exposure

> Returns historical vault exposure by user and venue, with each page’s venue rows ranked by `cumulativeDepositSeconds` over a time window.

export const ApiResponse = ({children, errors = {}}) => {
  const [status, setStatus] = useState("200");
  const statuses = ["200", ...Object.keys(errors)];
  return <section className="api-response" aria-label="Response">
      <div className="api-response-header not-prose">
        <h2>Response</h2>
        <div className="api-response-format">
          {statuses.length > 1 ? <select aria-label="Response status" value={status} onChange={event => setStatus(event.target.value)}>
              {statuses.map(code => <option key={code} value={code}>{code}</option>)}
            </select> : <span>200</span>}
          <span className="api-response-mime">application/json</span>
        </div>
      </div>
      <div hidden={status !== "200"}>{children}</div>
      {status !== "200" && <div aria-live="polite">
          {Object.entries(errors[status]).map(([name, value]) => <ResponseField key={name} name={name} type={value === null ? "null" : Array.isArray(value) ? "array" : typeof value}>
              {name === "error" ? "Error message describing why the request failed." : "Additional error details."}
            </ResponseField>)}
        </div>}
    </section>;
};

## Path parameters

<ParamField path="vaultAddress" type="string" required>
  Vault address.
</ParamField>

## Query parameters

<ParamField query="user" type="string">
  Filter to one wallet address.
</ParamField>

<ParamField query="startDate" type="string">
  ISO 8601 string or Unix timestamp in seconds. Defaults to vault start.
</ParamField>

<ParamField query="endDate" type="string">
  ISO 8601 string or Unix timestamp in seconds. Defaults to now.
</ParamField>

<ParamField query="page" type="integer" default="1">
  Positive integer. Pagination counts wallets before venue expansion.
</ParamField>

<ParamField query="limit" type="integer" default="1000">
  Positive integer; capped at 1000 wallets per page.
</ParamField>

<ParamField query="maxStaleness" type="number" default="3600">
  Cache staleness in seconds, capped at 86400. Invalid or negative values use 3600.
</ParamField>

## Default time window

If `startDate` is omitted, the endpoint uses the vault start timestamp.

If `endDate` is omitted, the endpoint uses the current time, capped at vault maturity when the vault has a maturity timestamp.

Explicit start dates are clamped to vault start, and explicit end dates are capped at maturity too. The effective start must be earlier than the effective end.

## Example requests

All holders:

<RequestExample dropdown>
  ```bash cURL theme={null}
  curl 'https://api.exponent.finance/holders/historical/vault/Cmry6B5824MGAKrtL2u7YG9PiLZLoTBWs8hVaCJeUFaH?startDate=2026-10-13T00:00:00Z&endDate=2026-10-14T00:00:00Z&limit=2'
  ```

  ```python Python theme={null}
  import requests

  response = requests.get("https://api.exponent.finance/holders/historical/vault/Cmry6B5824MGAKrtL2u7YG9PiLZLoTBWs8hVaCJeUFaH?startDate=2026-10-13T00:00:00Z&endDate=2026-10-14T00:00:00Z&limit=2", timeout=30)
  response.raise_for_status()
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.exponent.finance/holders/historical/vault/Cmry6B5824MGAKrtL2u7YG9PiLZLoTBWs8hVaCJeUFaH?startDate=2026-10-13T00:00:00Z&endDate=2026-10-14T00:00:00Z&limit=2");
  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }
  const data = await response.json();
  console.log(data);
  ```
</RequestExample>

Single user:

```bash theme={null}
curl "https://api.exponent.finance/holders/historical/vault/78MLjMXyKyjwXtHXCuZHnBUH5wMh89KwBpvoFvcBzxN1?user=HmzCnQBzSFW4THri7t9f9tcVBHXT7fuw4iczfPKMwEL8"
```

Explicit time window:

```bash theme={null}
curl "https://api.exponent.finance/holders/historical/vault/78MLjMXyKyjwXtHXCuZHnBUH5wMh89KwBpvoFvcBzxN1?startDate=2026-05-31T00:00:00Z&endDate=2026-06-06T00:00:00Z"
```

Paginated:

```bash theme={null}
curl "https://api.exponent.finance/holders/historical/vault/78MLjMXyKyjwXtHXCuZHnBUH5wMh89KwBpvoFvcBzxN1?page=1&limit=1000"
```

<ApiResponse errors={{}}>
  | Field | Description |
  | - | - |
  | `pagination.page` | Current page number |
  | `pagination.limit` | Maximum holder wallets included on the page |
  | `pagination.total_count` | Total holder wallets matching the query before venue expansion |
  | `pagination.total_pages` | Total number of pages |
  | `pagination.has_next` | Whether another page is available |
  | `pagination.has_prev` | Whether a previous page is available |
  | `syExchangeRate` | Time-weighted average SY exchange rate over the effective response window, sourced from V2 `timeseries.sy_prices` samples |
  | `count` | Number of holder-venue rows returned; a wallet can contribute more than one row |
  | `venue` | Exposure venue: `vaults`, `orderbook`, `amm`, or `clmm` |
  | `cumulativeDepositSeconds` | Total time (seconds) the user held a non-zero balance within the window |
  | `balanceSecondsBase` | Sum of base-normalized balance seconds |
  | `timeWeightedAverageBalanceBase` | `balanceSecondsBase / cumulativeDepositSeconds` - average base-normalized exposure while the user had non-zero exposure in that venue |
</ApiResponse>

## Venue composition

| Venue | Included exposure |
| - | - |
| `vaults` | Wallet/core YT plus open and filled orderbook YT attributed to the position owner |
| `orderbook` | Open and filled orderbook SY attributed to the position owner |
| `amm` | Legacy AMM LP; LP balances are converted using average SY per LP from legacy market history and the response window's `syExchangeRate` |
| `clmm` | CLMM LP; recorded historical SY exposure is converted using the response window's `syExchangeRate` |

## Example calculation

User holds 100 tokens for 10 days, then 200 tokens for 20 days. The user has no balance for the rest of the requested window.

| Metric | Calculation | Value |
| - | - | - |
| `cumulativeDepositSeconds` | 10 + 20 days | 30 days (in seconds) |
| `balanceSecondsBase` | (100 × 10) + (200 × 20) | 5000 base-days |
| `timeWeightedAverageBalanceBase` | 5000 / 30 | 166.67 base |

<ResponseExample>
  ```json 200 theme={null}
  {
    "pagination": {
      "page": 1,
      "limit": 2,
      "total_count": 15,
      "total_pages": 8,
      "has_next": true,
      "has_prev": false
    },
    "data": {
      "vaultAddress": "Cmry6B5824MGAKrtL2u7YG9PiLZLoTBWs8hVaCJeUFaH",
      "startDate": "2026-10-13T00:00:00.000Z",
      "endDate": "2026-10-14T00:00:00.000Z",
      "syExchangeRate": 1.1184787225252104,
      "count": 3,
      "holders": [
        {
          "userAddress": "2kyoEvCVfCoGmWGZG4MCzbv9xDgV7NCNDujFr776YzDQ",
          "venue": "vaults",
          "cumulativeDepositSeconds": 86400,
          "balanceSecondsBase": 562178.6208,
          "timeWeightedAverageBalanceBase": 6.506697
        },
        {
          "userAddress": "8Y7ApemW5UHzczZNYHW3tU4yZZjML8ho87i1dnf7kvw7",
          "venue": "vaults",
          "cumulativeDepositSeconds": 86400,
          "balanceSecondsBase": 99913.4784,
          "timeWeightedAverageBalanceBase": 1.156406
        }
      ]
    }
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.