# ETF Metrics

> Returns a paginated list of all ETF metrics — performance, risk, volatility, and fund characteristics — with full lineage/traceability.

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

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

## Description

Returns a paginated list of all ETF metrics — performance, risk, volatility,
and fund characteristics — with full lineage/traceability.

**Metric groups:**
- **Returns:** 1M, 3M, YTD, 1Y, 3Y, 5Y, 10Y; annualized 5Y; since inception
  (cumulative and annualized). Returns are total returns: distributions are added back
  to the closes (an accumulating share class is used as quoted).
- **Risk (security & category):** beta, alpha, sharpe ratio, treynor ratio,
  R-squared, standard deviation, mean annual return (1Y/3Y/5Y/10Y)
- **Volatility:** YTD, 1Y, 3Y, 5Y, 10Y
- **Risk indicators:** SRI (price-based, 1-7), SRRI (document-based, 1-7)
- **Fund:** tracking error, net management fee
- **Dividends:** dividend_yield (trailing 12-month distributions / latest close,
  percent; 0.0 for accumulating share classes)

Pass `trace=true` to include computation lineage (formula, inputs, explanation)
for each metric.


Check each metric's `date` for freshness. `latestDate` is the newest date across metrics and does not mean every metric (including AUM) is current.

## 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`. |
| `fields` | query | string | no | Comma-separated list of metric names to include in the response. Valid names are served by `/v2/etfs/metrics/names`. Example when explicitly filtering: `nav,aum,expense_ratio`. |
| `limit` | query | integer (int32) | no | Maximum number of metrics to return per page (default 50, max 200) Default `50`. |
| `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. |
| `trace` | query | boolean | no | Include computation lineage (formula, inputs, explanation) for each metric. Default `false`. |

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

## Response

200 Successful response (`application/json`).

| Field | Type | Always present | Description |
|---|---|---|---|
| `data` | object | no |  |
| `data.latestDate` | string (date) \| null | no | Most recent observation date across all metrics. Example: `2026-10-02`. |
| `data.metrics` | array of ETFMetricItem | no |  |
| `data.metrics[].metricId` | string | yes | Machine-readable metric identifier (lowercase, e.g. beta_3y, return_1y) Example: `beta_3y`. |
| `data.metrics[].metricName` | string | yes | Metric name as stored in the database (uppercase) Example: `BETA_3Y`. |
| `data.metrics[].date` | string (date) \| null | no | Observation date of this metric value. Example: `2026-03-31`. |
| `data.metrics[].value` | number (double) \| null | yes | Computed metric value. Null when computation failed. Example: `1.03`. |
| `data.metrics[].valid` | boolean | yes | Whether the metric was successfully computed. Example: `true`. |
| `data.metrics[].unit` | string \| null | no | Unit of measurement (MetricUnitModel value, uppercase) Example: `RATIO`. |
| `data.metrics[].currency` | string \| null | no | Currency code if the metric is currency-denominated (null for ratios/percentages) |
| `data.metrics[].trace` | object \| null | no | Computation lineage (only included when trace=true is passed) |
| `data.metrics[].trace.formula` | string \| null | no | Formula template used for computation. Example: `cov(R_etf, R_bench) / var(R_bench)`. |
| `data.metrics[].trace.formula_computed` | string \| null | no | Formula with actual computed values substituted. |
| `data.metrics[].trace.inputs` | object \| null | no | Input values used in the calculation. |
| `data.metrics[].trace.explanation` | string \| null | no | Natural language explanation of the computation result. Example: `Beta (3Y) = 1.03 for 3Y vs ^GSPC. Inputs: beta=1.0300`. |
| `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/metrics?isin=IE00B4L5Y983' \
  -H "x-api-key: $BAVEST_API_KEY"
```

## Example response

```json
{
  "data": {
    "latestDate": "2026-10-02",
    "metrics": [
      {
        "metricId": "aum",
        "metricName": "aum",
        "value": 147022599924.06,
        "date": "2026-10-01",
        "valid": true,
        "unit": "CURRENCY",
        "currency": "USD"
      },
      {
        "metricId": "nav",
        "metricName": "nav",
        "value": 145.4398,
        "date": "2026-10-01",
        "valid": true,
        "unit": "CURRENCY",
        "currency": "USD"
      }
    ]
  },
  "meta": {
    "page": 1,
    "pageSize": 50,
    "totalPages": 3,
    "totalCount": 101,
    "parameters": {
      "isin": "IE00B4L5Y983",
      "limit": "50"
    },
    "time": 68
  }
}
```

## 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_metrics
- 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
