Short answer
Call GET https://fundfactsapi.com/api/v1/funds/{isin} with a bearer API key and read name (envelope) in the JSON response (related fields: data.shareClass, data.keyFacts.manager / currency). The name is read from the fund house's product page and matches the share-class name in the prospectus. The Free plan gives 5 lookups a month with no card, and the keyless demo endpoint shows the shape for an already-loaded fund.
See it on a real fund page: the IE00B4L5Y983 page shows the figures this answer describes, with their as-of date.
Where it is in the response
| Path | Type | Meaning |
|---|---|---|
name (envelope) | string or null | Official share-class name, e.g. "iShares Core MSCI World UCITS ETF". |
data.shareClass | string or undefined | Share-class label when it can be inferred. |
data.keyFacts.manager / currency | string | Manager and share-class currency. |
GET /search?q= | results[] | Name → { isin, name, issuer, currency, assetClass, shareClass, income, category }; free. |
Sample for iShares Core MSCI World UCITS ETF (IE00B4L5Y983):
json{"isin": "IE00B4L5Y983","name": "iShares Core MSCI World UCITS ETF","data": { "shareClass": "USD Acc", "keyFacts": { "currency": "USD", "manager": "ETF" }, "structure": "ETF" }}
Where the figure comes from
The name is read from the fund house's product page and matches the share-class name in the prospectus. The reverse direction, name to ISIN, is GET /search?q=msci world; it is free and returns issuer, currency, share class and distribution policy per result so you can pick the right class before spending a request.
The request
bashcurl -s --max-time 300 https://fundfactsapi.com/api/v1/funds/IE00B4L5Y983 \-H "Authorization: Bearer $FUNDFACTS_API_KEY" | jq '.name'
pythonimport os, requestsr = requests.get("https://fundfactsapi.com/api/v1/funds/IE00B4L5Y983",headers={"Authorization": f"Bearer {os.environ['FUNDFACTS_API_KEY']}"}, timeout=300)fund = r.json()print(fund["name"], fund['name'])
javascriptconst res = await fetch("https://fundfactsapi.com/api/v1/funds/IE00B4L5Y983", {headers: { Authorization: `Bearer ${process.env.FUNDFACTS_API_KEY}` },signal: AbortSignal.timeout(300_000),});const fund = await res.json();console.log(fund.name, fund.name);
Sign up at fundfactsapi.com/signup for a key; the Free plan is 5 lookups a month with no card. Without a key, GET https://fundfactsapi.com/api/v1/demo/funds/IE00B4L5Y983 returns the same payload for funds already in the store (30 calls a minute per IP; it never loads a new fund).
Caveats
- Search covers funds that have already been loaded by someone; a fund nobody has requested yet is found by ISIN, not by name.
- For a stock, bond or index ISIN the answer is 404 fund_not_found: the API only knows funds.
Several funds 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. One request is counted per fund found. X-RateLimit-Remaining on every response tells you how many are left this month; a 429 rate_limited response carries Retry-After. Search and /me are free.
A fund never loaded before is read 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 returns from the store in well under a second with cached: true; past 24 hours the payload comes back flagged stale: true while a refresh runs in the background, and nothing older than 7 days is served without a new read.
Everything else in the payload is listed in the field reference.
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]}'