# ETF Holdings

> Returns all holdings with weights, values, and share counts.

`GET https://api.bavest.co/v2/etfs/holdings`

Group: ETFs. Route id: `v2_etfs_holdings`. Included in: Pro, Growth.

## Description

Returns all holdings with weights, values, and share counts. Swaps, futures, Treasury bills, money market funds and cash are rows of their own (`holdingType`); `view` picks market-value weights (`display`, default) or the issuer's exposure weights (`raw`).

## Authentication

Send your API key in the `x-api-key` header on every request. No key yet? Sign up at https://dashboard.bavest.co/sign-up (free trial). The examples read the key from the `BAVEST_API_KEY` environment variable.

## Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `symbol` | query | string | one of symbol, isin | ETF ticker symbol (e.g., `IWDA.AS`). Provide exactly one of symbol or isin; clear the ISIN example before using a symbol. |
| `isin` | query | string | one of symbol, isin | ETF ISIN code (e.g., `IE00B4L5Y983`, iShares Core MSCI World UCITS ETF). Provide exactly one of symbol or isin. Example `IE00B4L5Y983`. |
| `view` | query | string | no | Holdings view. `display` (default) weighs every row by market value, so a fund sums to ~100, with cash, Treasury bills and money market funds as their own rows; swaps and futures (no market value) and negative cash rows are left out. `raw` lists every row and keeps the issuer's exposure weights, so derivatives count at notional (a 3x fund ~300) and swaps list their counterparty. Plain ETFs are the same in both views. Unrecognized values fall back to `display`. One of `display`, `raw`. Default `display`. |
| `limit` | query | integer (int32) | no | Maximum number of results to return (default 100, max 1000) Default `100`. |
| `offset` | query | integer (int32) | no | Number of results to skip for pagination (default 0) Default `0`. |
| `cursor` | query | string | no | Opaque cursor for cursor-based pagination. When provided, returns results after the cursor position. Takes precedence over offset. |

Required: one of `symbol`, `isin`.

## Response

200 Successful response (`application/json`).

| Field | Type | Always present | Description |
|---|---|---|---|
| `data` | array of HoldingRecord | no | Holdings for the requested page. |
| `data[].name` | string \| null | yes | Holding name. Null when the constituent has no resolved master-record name yet; the key is always present. Example: `Apple Inc.`. |
| `data[].symbol` | string \| null | no | Ticker symbol. Example: `AAPL`. |
| `data[].isin` | string \| null | no | ISIN identifier. |
| `data[].percent` | number (double) \| null | yes | Weight (%) of net assets. With `view=display` (default) the market-value weight, so a fund's rows sum to ~100; swaps and futures without a market value and negative cash rows are left out (they are in `raw`). With `view=raw` a derivative's exposure weight (a 3x fund sums to ~300, an inverse fund's swaps are negative). Plain ETFs carry the same rows and weights in both views. Null only when the issuer publishes neither weight. Example: `7.79`. |
| `data[].value` | number (double) \| null | no | Issuer-reported position value in the source currency, which is not normalized here. Null when not reported. Use calculatedValue for an explicitly labelled USD estimate. |
| `data[].share` | number (double) \| null | no | Shares held. |
| `data[].cusip` | string \| null | no | CUSIP identifier. |
| `data[].calculatedValue` | object \| null | no | Bavest-calculated USD estimate, separate from issuer-reported value. Only available for a currently matching equity position with no reported value. |
| `data[].calculatedValue.value` | number (double) | yes | Estimated position value in USD. |
| `data[].calculatedValue.currency` | string | yes | One of `USD`. |
| `data[].calculatedValue.method` | string | yes | Example: `equity_quantity_times_historical_close_v1`. |
| `data[].calculatedValue.priceDate` | string (date) | yes |  |
| `data[].calculatedValue.fxDate` | string (date) | yes |  |
| `data[].calculatedValue.calculatedAt` | string (date-time) | yes |  |
| `data[].holdingType` | string \| null | no | Position type. `equity` for a listed security; swaps, futures, Treasury bills, money market funds and cash / net other assets are kept as their own rows (no ISIN); `other` for an unlisted instrument such as a bond. Null on issuer top-10 lists that publish names only. One of `equity`, `swap`, `future`, `cash`, `money_market`, `treasury_bill`, `other`, `null`. Example: `equity`. |
| `data[].marketValue` | number (double) \| null | no | Issuer-reported market value in the source currency; the basis of `percent` in `view=display`. Null when the issuer publishes none (swaps, futures). |
| `data[].exposureValue` | number (double) \| null | no | Issuer-reported exposure (notional plus gain/loss) of a swap or future, in the source currency; the basis of `percent` in `view=raw`. Null for positions without one. Example: `9920928648.41`. |
| `data[].counterparty` | string \| null | no | Swap counterparty as the issuer names it. Null for every other position. Example: `BNP Paribas`. |
| `meta` | ResponseMeta | no | Response metadata for paginated endpoints. Offset pagination returns `page`/`pageSize`/`totalPages`/`totalCount`; cursor pagination returns `pageSize`/`hasMore`/`nextCursor` and `totalCount` only when known. |
| `meta.time` | integer | no | Server-side processing time in milliseconds. Example: `17`. |
| `meta.parameters` | object | no | Echo of the request parameters the endpoint resolved. |
| `meta.page` | integer | no | Current page number (offset pagination) Example: `1`. |
| `meta.pageSize` | integer | no | Number of results per page. Example: `50`. |
| `meta.totalPages` | integer | no | Total number of pages (offset pagination) Example: `2`. |
| `meta.totalCount` | integer | no | Total number of results across all pages. Example: `100`. |
| `meta.hasMore` | boolean | no | Whether more results follow (cursor pagination) |
| `meta.nextCursor` | string \| null | no | Cursor for the next page (cursor pagination), null on the last page. |

## Example request

```bash
curl 'https://api.bavest.co/v2/etfs/holdings?isin=IE00B4L5Y983&view=display' \
  -H "x-api-key: $BAVEST_API_KEY"
```

## Example response

```json
{
  "data": [
    {
      "name": "NVIDIA CORP",
      "percent": 5.7488,
      "value": 8712724624.12,
      "isin": "US67066G1040",
      "symbol": "NVDA",
      "cusip": null,
      "share": 38346572
    },
    {
      "name": "APPLE INC",
      "percent": 5.3245,
      "value": 8069636917.8,
      "isin": "US0378331005",
      "symbol": "AAPL",
      "cusip": null,
      "share": 24497987
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 100,
    "totalPages": 13,
    "totalCount": 1265,
    "parameters": {
      "isin": "IE00B4L5Y983",
      "limit": "100"
    },
    "time": 48
  }
}
```

## Errors

| Status | Meaning |
|---|---|
| 400 | Invalid request parameters. Returned when required query parameters are missing, have invalid types, or violate constraints (e.g., providing both symbol and isin when they are mutually exclusive). |
| 401 | Missing or invalid API key. |
| 404 | Resource not found. |
| 429 | Rate limit exceeded. Retry after the `Retry-After` header interval. |
| 500 | An unexpected error occurred on the server. If the issue persists, contact support with the X-Request-Id header value. |
| 502 | Upstream data provider returned an error or is temporarily unavailable. Retry after a short delay. |
| 503 | Bavest cannot read its data store right now. The security may well have data; retry after the `Retry-After` header interval. |
| 504 | The request timed out waiting for a response from the upstream data provider. This may occur for complex queries or during peak load. |
| default | An unexpected error occurred on the server. If the issue persists, contact support with the X-Request-Id header value. |

- `403` from the gateway: the API key is invalid or switched off.
- `429` with message `Limit Exceeded`: the monthly quota of the key is used up. With `Too Many Requests`: the key is throttled, or this route is not in the key's plan. Wait for `Retry-After` when it is sent.

## Links

- HTML page: https://dashboard.bavest.co/docs/v2_etfs_holdings
- OpenAPI: https://dashboard.bavest.co/openapi.json (YAML: https://dashboard.bavest.co/openapi.yaml)
- Authentication: https://dashboard.bavest.co/docs/authentication.md
- MCP server for AI agents: https://dashboard.bavest.co/docs/mcp.md
- All routes: https://dashboard.bavest.co/llms.txt
