What happens if I send a stock, bond or index ISIN?
The API only knows funds. A valid ISIN that is a stock, bond, certificate or index returns 404 fund_not_found with reason not_a_fund and an empty data skeleton, and is not counted. How to tell the cases apart.Published September 12, 2026 · Updated October 1, 2026 · by FundFacts APIShort answer
A syntactically valid ISIN that is not a covered fund (a share, bond, certificate, index or a delisted fund) returns 404 fund_not_found with the empty data skeleton and an error.reason: not_a_fund for a share or bond, issuer_not_covered or documents_unreadable for a fund FundFacts cannot read yet. It is not counted (up to 15 misses a month or the plan's allowance if larger), and neither is a malformed ISIN, which returns 400 invalid_isin. Validate the format locally first, treat not_a_fund as final, and let FundFacts recheck the others: it e-mails you when they are covered.
The two errors
| Status | error.code | When | Counted |
|---|---|---|---|
| 400 | invalid_isin | Not 12 characters, wrong pattern or bad check digit | No |
| 404 | fund_not_found | Valid ISIN, but no fund data: stock, bond, index, structured product, delisted or not-yet-covered fund | No, up to 15 misses a month (or the plan's allowance if larger) |
json{ "error": { "code": "fund_not_found", "reason": "not_a_fund", "instrument": "common stock", "message": "This ISIN is a common stock, not a fund or ETF. FundFacts only covers funds. This lookup was not counted." }, "isin": "US0378331005", "billed": false }
Why a 404 is free
The API cannot know an ISIN is a stock without trying, and a fund it cannot read yet is a gap on FundFacts' side, not a use of the data. So a miss is not counted, up to 15 a month or the plan's allowance if larger; past that, misses count like answers, so they cannot be used to run the loader without limit. Pending and invalid entries are never counted.
Avoiding it
- Validate locally. 12 characters, two letters, nine alphanumerics, one Luhn check digit; the ISIN validator page shows the algorithm and the SDKs include it.
- Know the prefixes. Fund ISINs are mostly IE, LU, FR, DE, GB, CH, AT, NL, BE, DK, FI, SE, NO, IT, ES; a US-prefixed ISIN is usually a stock, though US-listed ETFs also exist.
- Search first.
GET /search?q=(free) confirms a fund is in the store before you spend a request. - Remember the answer. Store the 404 with its
reasonand do not re-send anot_a_fundISIN. Coverage gaps are rechecked for you, and you get an e-mail when one loads.
A real fund that returns 404
It happens when the fund house is not yet covered (reason: issuer_not_covered), its documents cannot be read (documents_unreadable) or the share class is delisted. The ISIN is queued automatically: FundFacts reloads it regularly and e-mails you when it has data. Reporting it speeds that up; adapters are added by demand. For a PDF you already have, POST /extract (Pro and above) returns the same JSON shape.
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]}'