How do I look up a fund or ETF by its ISIN?
One GET request per ISIN returns the fund's name, key facts, fees, risk indicator, holdings, exposures, returns and as-of date as JSON. The request, the response and the rules.Updated 12 September 2026 · by FundFacts APIShort answer
Send GET https://fundfactsapi.com/api/v1/funds/{isin} with the header Authorization: Bearer <api key>. The response is the fund's name plus a data object with key facts, TER, the 1–7 risk indicator, a classification profile, top holdings, sector, country and asset weights, calendar and annualised returns, a monthly series, risk statistics and the as-of date of the figures. A free key (15 lookups a month) is enough; the keyless demo endpoint shows the shape for already-loaded funds.
The request
bashcurl -s --max-time 300 https://fundfactsapi.com/api/v1/funds/IE00B4L5Y983 -H "Authorization: Bearer $FUNDFACTS_API_KEY"
The ISIN is case-insensitive; the response echoes it in upper case. X-Api-Key: <key> is accepted instead of the bearer header.
The response
json{"isin": "IE00B4L5Y983","name": "iShares Core MSCI World UCITS ETF","cached": true,"generatedAt": "2026-09-12T06:00:00.000Z","expiresAt": "2026-09-13T06:00:00.000Z","plan": "free","quota": { "limit": 15, "remaining": 14, "used": 1, "resetAt": "2026-10-01T00:00:00.000Z" },"data": {"keyFacts": { "assetClass": "Equities", "currency": "USD", "aum": "USD 151.7bn", "inception": "2009-09-25", "distribution": "Accumulating", "holdings": 1253 },"headlineMetrics": { "ter": "0.20%", "volatility3y": "11.8%", "sharpe3y": "1.68" },"riskRating": 6,"profile": { "kind": "equity", "category": "Global Equity", "riskBand": "high", "regionFocus": "Global" },"topHoldings": [ { "name": "NVIDIA", "weight": 5.48 } ],"sector": [ { "label": "Information Technology", "weight": 29.8 } ],"geography": [ { "label": "United States", "weight": 72.07 } ],"calendarReturns": { "years": ["2024", "2025"], "fund": [18.7, 21.2], "benchmark": [18.7, 21.1] },"dataAsOf": "2026-09-01"}}
The response is one JSON envelope: isin, name, cached, generatedAt, expiresAt, plan, quota and a data object. Inside data you get keyFacts (asset class, currency, fund size, inception date, distribution policy, number of holdings), headlineMetrics (TER, AUM, 3-year volatility and Sharpe, yield to maturity and duration for bond funds), riskRating (the 1–7 KID indicator), profile (a rule-based classification: kind, category, risk band, region focus, sector tilt), topHoldings, sector, geography, region, assetAllocation, creditQuality, maturity, calendarReturns, annualisedReturns, cumulativePerformance, indexedPerformance, metrics (max drawdown, P/E, income yield…), sfdrArticle, costs (PRIIPs entry, exit, ongoing, transaction and performance fees, reduction in yield) and dataAsOf, the date of the underlying figures.
Money and percentages arrive as the fund house prints them, as strings such as "0.20%" or "USD 151.7bn". Breakdown weights and return series are plain numbers in percent. Fields that do not apply to the fund's asset class are empty strings, null or empty arrays, never missing keys; treat empty as "not disclosed", not as zero.
Rules that save you requests
- Each share class is its own ISIN. The accumulating USD class, the distributing EUR class and the hedged class of one fund are three ISINs with three payloads.
GET /search?q=(free) lists them with currency and distribution policy so you can pick before you spend a request. - Not every ISIN is a fund. A stock, bond or index ISIN returns
404 fund_not_found. Validate the format first with the ISIN validator rules. - First call is slow. A fund nobody has requested in the last 24 hours is loaded on demand from the documents the fund house publishes. That first call takes 15 seconds to about 3 minutes; set your client timeout to 300 seconds and do not fire a second request for the same ISIN while the first is running. Every later call within 24 hours returns from the store in well under a second with
cached: true. - Cache it. One request is counted per ISIN answered.
X-RateLimit-Remainingon every response tells you how many are left this month; a429 rate_limitedresponse carriesRetry-After. Search and/meare free.
Several at once
POST /funds with { "isins": [...], "wait": true } returns the same payload for up to 10 ISINs per call on Starter, 50 on Pro and 200 on Scale.
Verify it yourself
The demo endpoint returns the live payload for a fund that is already in the store, without a key. Everything on this page can be checked against it.bashcurl -s https://fundfactsapi.com/api/v1/demo/funds/IE00B4L5Y983 | jq '{name, asOf: .data.dataAsOf, ter: .data.headlineMetrics.ter, risk: .data.riskRating, top: .data.topHoldings[:3]}'