ETF data API

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

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.Published October 6, 2026
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

DataFieldWhat you get
TER, ongoing chargesheadlineMetrics.terThe KID's ongoing charge first, otherwise the fund house's TER.
KID costscostsEntry, exit, ongoing, transaction and performance fees, cost impact.
Risk indicator (SRI 1–7)riskRatingAs the KID states it; null when no document does, never estimated.
Replicationreplicationphysical, synthetic or null when not stated.
Distribution policykeyFacts.distributionAccumulating or Distributing.
Fund size, currency, inceptionkeyFacts.aum, keyFacts.currency, keyFacts.inceptionAs reported, per share class.
BenchmarkbenchmarkNameThe index tracked.
HoldingstopHoldings, keyFacts.holdingsLargest positions and their count (details).
Exposuresector, geography, region, assetAllocationWeights in percent.
ReturnscalendarReturns, annualisedReturnsEach full year with the benchmark; 1, 3, 5, 10 years and since inception.
Monthly seriescumulativePerformance, indexedPerformanceFrom the fund house's NAV history where it publishes one.
Risk statisticsheadlineMetrics.volatility3y, headlineMetrics.sharpe3y, metrics.maxDrawdownThe issuer's figures, otherwise computed over 36 months.
SFDRsfdrArticle6, 8 or 9 when disclosed.
CategoryprofileDerived 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.

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 from GitHub, and React widgets that render the payload.
  • MCP: the 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 APIStock-market data API
KeyISIN, one call per share classExchange ticker, often US-centric; ISIN support varies
UniverseUCITS funds and ETFs with public document setsListed equities and ETFs, mostly US exchanges
PricesNo quotes or intraday prices; monthly return series from the NAV historyIntraday and end-of-day prices, the core product
Fund fieldsKID risk indicator, ongoing charges and KID costs, distribution policy, share class, benchmark, calendar returns vs benchmarkOften limited to expense ratio and top holdings for US ETFs
HoldingsLargest positions, with sector and country weights for the whole portfolioTop holdings for major US ETFs on some plans; European ETFs often missing
RefreshEach ISIN at most every 24 hours, with dataAsOfReal-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.

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 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. The quickstart has curl, TypeScript and Python.

Frequently asked questions

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, Xtrackers, Amundi, Vanguard, SPDR, Invesco and the other fund houses on the coverage pages, 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.

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.

Try it on your own ISINs

One request returns key facts, holdings, risk and performance as JSON. Free plan, no card.