---
title: "ETF data API for UCITS ETFs: TER, risk, holdings, returns by ISIN"
description: "One GET by ISIN returns a UCITS ETF's TER and KID costs, SRI 1–7, holdings, sector and country weights, returns and risk stats as dated JSON. Free plan."
canonical: https://fundfactsapi.com/etf-data-api
published: 2026-10-06
updated: 2026-10-06
publisher: FundFacts API
---

# ETF data API for UCITS ETFs: TER, risk, holdings, returns by ISIN

> One GET by ISIN returns a UCITS ETF's TER and KID costs, SRI 1–7, holdings, sector and country weights, returns and risk stats as dated JSON. Free plan.

FundFacts API is an ETF data API keyed on the ISIN: one request returns a UCITS ETF's TER and KID costs, its 1–7 risk indicator, holdings, sector and country exposure, calendar and annualised returns and risk statistics, read from the fund house's own documents and dated. It covers funds as well as ETFs, re-reads each ISIN at most every 24 hours, and has a free plan with 15 lookups a month.

> FundFacts API turns any fund or ETF ISIN into one dated, structured factsheet (fees and KID costs, the 1–7 risk indicator, holdings, sector and country exposure, returns) read from the fund house's own documents: as JSON for your code, inside ChatGPT and Claude through its MCP server, or as a client-ready PDF factsheet.

## The fields an ETF data API should return

| Data | Field | What you get |
| --- | --- | --- |
| TER, ongoing charges | `headlineMetrics.ter` | The KID's ongoing charge first, otherwise the fund house's TER. |
| KID costs | `costs` | Entry, exit, ongoing, transaction and performance fees, cost impact. |
| Risk indicator (SRI 1–7) | `riskRating` | As the KID states it; `null` when no document does, never estimated. |
| Replication | `replication` | `physical`, `synthetic` or `null` when not stated. |
| Distribution policy | `keyFacts.distribution` | Accumulating or Distributing. |
| Fund size, currency, inception | `keyFacts.aum`, `keyFacts.currency`, `keyFacts.inception` | As reported, per share class. |
| Benchmark | `benchmarkName` | The index tracked. |
| Holdings | `topHoldings`, `keyFacts.holdings` | Largest positions and their count ([details](https://fundfactsapi.com/etf-holdings-api)). |
| Exposure | `sector`, `geography`, `region`, `assetAllocation` | Weights in percent. |
| Returns | `calendarReturns`, `annualisedReturns` | Each full year with the benchmark; 1, 3, 5, 10 years and since inception. |
| Monthly series | `cumulativePerformance`, `indexedPerformance` | From the fund house's NAV history where it publishes one. |
| Risk statistics | `headlineMetrics.volatility3y`, `headlineMetrics.sharpe3y`, `metrics.maxDrawdown` | The issuer's figures, otherwise computed over 36 months. |
| SFDR | `sfdrArticle` | 6, 8 or 9 when disclosed. |
| Category | `profile` | Derived from the disclosed data with published rules. |

There is no domicile or ticker field: the ISIN's prefix (IE, LU, DE) usually tells the domicile, and `GET /search` resolves a ticker. Every key is in the [field reference](https://fundfactsapi.com/docs/fields).

## One request, one dated payload

```bash
curl -s https://fundfactsapi.com/api/v1/funds/IE00B4L5Y983 \
  -H "Authorization: Bearer $FUNDFACTS_API_KEY"
```

```json
{
  "isin": "IE00B4L5Y983",
  "name": "iShares Core MSCI World UCITS ETF",
  "cached": true,
  "generatedAt": "2026-09-02T20:32:58.872Z",
  "expiresAt": "2026-09-03T20:32:58.872Z",
  "data": {
    "keyFacts": {
      "currency": "USD",
      "aum": "USD 151.7bn",
      "inception": "2009-09-25",
      "distribution": "Accumulating",
      "holdings": 1253
    },
    "riskRating": 6,
    "benchmarkName": "MSCI World Index (Net)",
    "headlineMetrics": {
      "ter": "0.20%",
      "volatility3y": "11.8%",
      "sharpe3y": "1.68"
    },
    "metrics": {
      "maxDrawdown": "-16.5%"
    },
    "calendarReturns": {
      "years": ["2023", "2024", "2025"],
      "fund": [23.9, 18.7, 21.2],
      "benchmark": [23.8, 18.7, 21.1]
    },
    "annualisedReturns": [
      { "label": "1 Year", "fund": 19.57, "index": 19.55 },
      { "label": "3 Years p.a.", "fund": 19.82, "index": 19.78 },
      { "label": "5 Years p.a.", "fund": 11.05, "index": 10.98 }
    ],
    "dataAsOf": "2026-09-01"
  }
}
```

This is the real payload for iShares Core MSCI World UCITS ETF, trimmed. Money and percentages arrive as printed (`"0.20%"`, `"USD 151.7bn"`); weights and returns are numbers in percent.

## Identifiers: ISIN first

`GET /funds/{isin}` takes a 12-character ISIN, case-insensitive. Each share class has its own: an accumulating and a distributing class of the same ETF return different key facts, fees and returns. `GET /search?q=` finds ISINs by exchange ticker (VWCE, EUNL), name, issuer or ISIN prefix among funds already loaded, and is not counted.

## Freshness

Each payload is stored for 24 hours: within that window a fund returns in well under a second with `cached: true`. A cold one is read from the fund house's documents in 15 seconds to 3 minutes, so allow 300 seconds. `expiresAt` says when the payload goes stale, and `data.dataAsOf` dates the figures: show that one to your users.

## Batch, SDKs and MCP

- **Batch:** `POST /funds` with `{ "isins": [...] }` takes up to the plan's batch size (1 on Free, 10 on Starter, 50 on Pro, 200 on Scale, 1,000 on Enterprise). Each fund found counts one request.
- **SDKs:** `npm install @fundfactsapi/sdk`, a [Python client](https://fundfactsapi.com/docs/sdks) from GitHub, and React widgets that render the payload.
- **MCP:** the [MCP server](https://fundfactsapi.com/mcp-server) puts the same data inside Claude, ChatGPT, Cursor and Claude Code, on every plan, Free included.

## What you get vs a stock-market data API

| | FundFacts API | Stock-market data API |
| --- | --- | --- |
| Key | ISIN, one call per share class | Exchange ticker, often US-centric; ISIN support varies |
| Universe | UCITS funds and ETFs with public document sets | Listed equities and ETFs, mostly US exchanges |
| Prices | No quotes or intraday prices; monthly return series from the NAV history | Intraday and end-of-day prices, the core product |
| Fund fields | KID risk indicator, ongoing charges and KID costs, distribution policy, share class, benchmark, calendar returns vs benchmark | Often limited to expense ratio and top holdings for US ETFs |
| Holdings | Largest positions, with sector and country weights for the whole portfolio | Top holdings for major US ETFs on some plans; European ETFs often missing |
| Refresh | Each ISIN at most every 24 hours, with `dataAsOf` | Real-time to daily for prices |

## What it is not for

Prices, quotes, intraday NAV (iNAV), volume and corporate actions belong to a market-data API keyed on the ticker. Use one alongside: it says what the ETF trades at, FundFacts API says what the ETF is. Stocks, bonds and indices are not funds and return `404 fund_not_found`, free up to as many misses a month as the plan's allowance.

## Price

Free is $0: 15 lookups a month, no card, personal use. Starter is $9.99 a month for 500 requests, Pro $49 for 9,000, Scale $249 for 60,000 (VAT included). Commercial use of the data comes with Pro, Scale and Enterprise. One request is counted per fund found. See [pricing](https://fundfactsapi.com/pricing).

## Get started in three steps

1. **Check the shape without a key.** `curl -s https://fundfactsapi.com/api/v1/demo/funds/IE00B4L5Y983` returns the full payload of any fund already loaded.
2. **Create a free key.** [Sign up](https://fundfactsapi.com/signup) with an e-mail address or Google. The Free plan gives 15 lookups a month without a card, and the key is in the dashboard.
3. **Call it from your code or your assistant.** Send `GET /api/v1/funds/{isin}` with `Authorization: Bearer <key>`, batch from Starter with `POST /funds`, or connect the [MCP server](https://fundfactsapi.com/mcp-server). The [quickstart](https://fundfactsapi.com/docs/quickstart) has curl, TypeScript and Python.

## FAQ

### Is there a free ETF data API for UCITS ETFs?

Yes. The FundFacts API Free plan gives 15 lookups a month without a card, with every field of the payload, for personal, non-commercial use. The demo endpoint `/api/v1/demo/funds/{isin}` needs no key for funds already loaded.

### Does it cover European UCITS ETFs?

Yes. UCITS ETFs and funds are the core of the coverage, from [iShares](https://fundfactsapi.com/coverage/ishares), [Xtrackers](https://fundfactsapi.com/coverage/xtrackers), [Amundi](https://fundfactsapi.com/coverage/amundi), [Vanguard](https://fundfactsapi.com/coverage/vanguard), [SPDR](https://fundfactsapi.com/coverage/spdr), [Invesco](https://fundfactsapi.com/coverage/invesco) and the other fund houses on the [coverage pages](https://fundfactsapi.com/coverage), each with the sections its documents fill.

### Can I look up an ETF by ticker instead of ISIN?

Yes, in two steps: `GET /search?q=VWCE` returns the ISIN of a fund already loaded (a ticker, a name or an ISIN prefix works, and search is not counted), then `GET /funds/{isin}` returns the data.

### Does it return ETF prices or intraday NAV?

No. There are no quotes, intraday prices or iNAV; the payload carries returns and monthly series built from the fund house's NAV history. Pair it with a market-data API for prices.

### How fresh is the data?

Each ISIN is re-read from the fund house's documents when its payload is older than 24 hours. `data.dataAsOf` is the as-of date of the figures, typically the last month end for a factsheet.

### Where does the TER come from?

From the KID's ongoing-charge figure when there is one, otherwise from the TER the fund house's other documents state, as printed. The full KID cost table is in `costs`; see [TER by ISIN](https://fundfactsapi.com/answers/get-ter-of-an-etf-or-fund).

### Can I use the data in a commercial product?

Yes, from Pro ($49 a month): commercial use comes with Pro, Scale and Enterprise. Free and Starter are for personal, non-commercial use.

### Does it say whether an ETF is physical or synthetic?

Yes. `replication` is `physical` or `synthetic` when the fund house states it, `null` otherwise. For a synthetic ETF, `holdingsBasis` marks the listed holdings as the swap's substitute basket.

## Related

- [Field reference](https://fundfactsapi.com/docs/fields)
- [Endpoints](https://fundfactsapi.com/docs/endpoints)
- [SDKs](https://fundfactsapi.com/docs/sdks)
- [MCP server](https://fundfactsapi.com/mcp-server)
- [ETF holdings API](https://fundfactsapi.com/etf-holdings-api)
- [Coverage by fund house](https://fundfactsapi.com/coverage)
- [TER by ISIN](https://fundfactsapi.com/answers/get-ter-of-an-etf-or-fund)
- [Stock APIs and UCITS funds](https://fundfactsapi.com/answers/stock-market-apis-do-not-cover-ucits-funds-what-does)
- [FundFacts vs stock market data APIs](https://fundfactsapi.com/compare/fundfacts-api-vs-stock-market-data-apis)
- [Best free ETF data API](https://fundfactsapi.com/answers/best-free-etf-data-api)
- [Pricing](https://fundfactsapi.com/pricing)

## About FundFacts API

FundFacts API turns any fund or ETF ISIN into one dated, structured factsheet (fees and KID costs, the 1–7 risk indicator, holdings, sector and country exposure, returns) read from the fund house's own documents: as JSON for your code, inside ChatGPT and Claude through its MCP server, or as a client-ready PDF factsheet.

FundFacts works inside ChatGPT and Claude as a connector (a remote MCP server): ask about any fund or ETF by ISIN, ticker or name and the assistant answers from FundFacts' dated figures, fees, risk, holdings, exposure and returns, with fund cards, side-by-side comparisons, holdings overlap and portfolio look-through.

- Free API key, no card: https://fundfactsapi.com/signup
- Documentation: https://fundfactsapi.com/docs (OpenAPI: https://fundfactsapi.com/openapi.json)
- MCP server: https://fundfactsapi.com/api/mcp (set-up for every client: https://fundfactsapi.com/mcp-server)
- Pricing: https://fundfactsapi.com/pricing
- Site index for AI assistants: https://fundfactsapi.com/llms.txt
- Informational data, not investment advice.
