TutorialAPIISIN

How to get fund data from an ISIN with a REST API (curl, JavaScript, Python)

Step-by-step: call a fund data API with an ISIN and get key facts, holdings, risk and performance as JSON. Includes curl, fetch and requests examples and error handling.Published 19 August 2026 · 2 min read · by FundFacts API

Getting reliable fund data used to mean either an enterprise data licence or a fragile PDF scraper. This tutorial shows the third option: one HTTP request that takes an ISIN and returns a complete, structured factsheet as JSON. We will use FundFacts API, but the patterns — bearer auth, a long timeout for cold requests, quota headers — apply to any fund data API.

1. Get an API key

Sign up for a free account, open the dashboard and create a key. Keys start with ffk_ and are shown once; store them in an environment variable, never in client-side code. The free plan gives you ten requests per day, enough to explore the schema; paid plans raise that to 100 or 1,000 requests per day (see pricing).

2. Make your first request

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

Note --max-time 300. The first request for an ISIN nobody has asked for yet triggers a live refresh, which takes one to three minutes. Every request in the following 24 hours is served from cache in a few hundred milliseconds. If you cannot wait that long in a request cycle, pre-warm the ISINs you care about in a background job (more on that below).

3. Read the response

The envelope is the same for every fund:

json
{
"isin": "IE00B4L5Y983",
"name": "iShares Core MSCI World ETF USD Acc",
"cached": true,
"generatedAt": "2026-09-02T13:41:07.112Z",
"expiresAt": "2026-09-03T13:41:07.112Z",
"plan": "pro",
"quota": { "limit": 100, "remaining": 87, "resetAt": "2026-09-03T09:12:44.000Z" },
"data": {
"keyFacts": { "assetClass": "Equities", "currency": "USD", "aum": "USD 151.7bn", "inception": "Sep 25, 2009", "holdings": 1344 },
"riskRating": 4,
"topHoldings": [{ "name": "NVIDIA Corp", "weight": 5.43 }],
"sector": [{ "label": "Technology", "weight": 30.5 }],
"calendarReturns": { "years": ["2021", "2022"], "fund": [21.9, -18] },
"headlineMetrics": { "ter": "0.20%", "volatility3y": "11.9%", "sharpe3y": "1.21" }
}
}

Three things worth internalising:

  • data has the same keys for every fund. Panels that do not apply (credit quality for an equity ETF, say) are empty arrays or empty strings, never missing. You can write one renderer.
  • Breakdowns are arrays of { label, weight } with weights in percent. Holdings use { name, weight }.
  • Formatted metrics stay strings with their unit ("0.20%", "USD 151.7bn") so you never lose the currency or the scale. Numbers you will chart (returns, weights) are numbers.

The full list of fields is in the documentation.

4. JavaScript / TypeScript

typescript
const BASE = "https://fundfactsapi.com/api/v1";
​
export async function getFund(isin: string) {
const res = await fetch(`${BASE}/funds/${isin}`, {
headers: { Authorization: `Bearer ${process.env.FUNDFACTS_API_KEY}` },
signal: AbortSignal.timeout(300_000),
});
​
if (res.status === 429) {
const { error } = await res.json();
throw new Error(`Quota exceeded, retry in ${error.retryAfter}s`);
}
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
return res.json();
}
​
const fund = await getFund("IE00B4L5Y983");
console.log(fund.name, fund.data.headlineMetrics.ter, fund.quota.remaining);

5. Python

python
import os
import requests
​
BASE = "https://fundfactsapi.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['FUNDFACTS_API_KEY']}"}
​
def get_fund(isin: str) -> dict:
r = requests.get(f"{BASE}/funds/{isin}", headers=HEADERS, timeout=300)
if r.status_code == 429:
retry = r.json()["error"]["retryAfter"]
raise RuntimeError(f"Quota exceeded, retry in {retry}s")
r.raise_for_status()
return r.json()
​
fund = get_fund("IE00B4L5Y983")
top = fund["data"]["topHoldings"][:5]
for h in top:
print(f"{h['name']:<30} {h['weight']:>6.2f}%")

6. Handle errors properly

Every error uses one envelope: { "error": { "code", "message", ... } }.

StatusCodeWhat to do
400invalid_isinShow a validation message; the request was not counted
401missing_api_key / invalid_api_keyCheck the header and the key
404fund_not_foundThe ISIN is valid but is not a fund/ETF we can cover; data is an empty skeleton
429rate_limitedWait retryAfter seconds (also in the Retry-After header)
502upstream_errorTemporary upstream issue; retry with back-off

The X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers let you throttle before you hit 429.

7. Pre-warm your universe

For a screener or a portfolio tool you know the ISINs in advance. Run a nightly job that requests each one; the first run is slow, every subsequent run and every user request is a cache hit. With a Scale plan (10,000 requests a month) that covers a universe of about two hundred funds with headroom for ad-hoc lookups.

typescript
for (const isin of universe) {
await getFund(isin); // populates the 24h cache
await new Promise((r) => setTimeout(r, 500));
}

Next steps

Try it on your own ISINs

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

Questions this answers

Getting started

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.
By language & tool

How do I get fund or ETF data by ISIN in curl?

curl fund data by ISIN: one curl call with --max-time 300 and jq filters for TER, risk, holdings and returns; the same call works in any HTTP client.
By language & tool

How do I get fund or ETF data by ISIN in JavaScript (Node.js)?

JavaScript (Node.js) fund data by ISIN: native fetch (undici) example, no dependency, AbortSignal.timeout(300000) for the slow first load of a cold ISIN.
By language & tool

How do I get fund or ETF data by ISIN in Python?

Python fund data by ISIN: requests (or httpx) example returning name, TER, risk, holdings and returns; timeout=300 so a cold ISIN does not fail.
Getting started

What is FundFacts API?

FundFacts API is a REST and MCP API that turns any fund or ETF ISIN into one structured JSON factsheet (fees, risk indicator, holdings, exposures, returns, as-of date) read from the fund house's own documents and refreshed daily. What it returns, what it is for, what it is not, and the plans.
Getting started

Is there a free API for fund and ETF data?

Yes. FundFacts API has a free plan with 5 lookups a month and no card: any UCITS fund or ETF ISIN returns TER, risk indicator, holdings, exposures and returns as JSON. What it includes and where paid plans start.
For your project

What fund data API can I use for a fintech MVP or hackathon this weekend?

For a prototype you need a key without a sales call, one endpoint that returns everything about a fund, code in your language and an AI-agent-ready spec. FundFacts API: free key, 5 lookups, keyless demo endpoint, SDKs, MCP server, OpenAPI. Start here.
Choosing a data source

Where can I get mutual fund data as JSON?

Mutual funds have no ticker feed; their data lives in factsheets and KIDs. FundFacts API returns it as JSON per ISIN for UCITS and other open-end funds from 60+ managers: fees, risk indicator, holdings, exposures, returns, objective, as-of date. Coverage and code.
By language & tool

How do I get fund or ETF data by ISIN in TypeScript?

TypeScript fund data by ISIN: typed client with the SDK's FundResponse and FundData types, so headlineMetrics.ter autocompletes and nulls are explicit.
By language & tool

How do I get fund or ETF data by ISIN in Go?

Go fund data by ISIN: net/http and encoding/json example that decodes only the fields you use, with a 300-second client timeout for cold ISINs.
By language & tool

How do I get fund or ETF data by ISIN in Java?

Java fund data by ISIN: java.net.http.HttpClient (Java 11+) and Jackson example with a 300-second request timeout for the first load of a cold ISIN.
By language & tool

How do I get fund or ETF data by ISIN in PHP?

PHP fund data by ISIN: curl extension example (Guzzle works the same in Laravel or Symfony) with CURLOPT_TIMEOUT 300 for the first load of a cold ISIN.