Getting started

Why does the first request for a fund take so long?

A fund nobody has requested in 24 hours is read live from the fund house's documents, which takes 15 seconds to a few minutes. Later calls are instant. Timeouts, batches and pre-warming.Updated 12 September 2026 · by FundFacts API

Short answer

Because the data is read from the fund house at that moment. A cold ISIN (nobody has requested it in the last 24 hours) triggers a read of the product page, factsheet PDF, KID and holdings / NAV files, which takes 15 seconds to about 3 minutes. The server allows 300 seconds; set that timeout and do not send a second request for the same ISIN while the first runs. Every later call within 24 hours returns from the store in well under a second with cached: true.

What happens on a cold load

  1. The issuer adapter resolves the ISIN to the fund house's product page.
  2. The page, the monthly factsheet, the KID and (where published) the holdings and NAV files are fetched and parsed.
  3. Figures are normalised into the data shape, the profile is derived, series are computed.
  4. The payload is stored for 24 hours and returned.

PDF parsing and per-issuer sites set the pace. Two callers asking for the same cold ISIN at once share one load.

Design rules

  • Timeout 300 s on GET /funds/{isin} and POST /funds. Show "loading fund data, first load can take a couple of minutes" in a UI.
  • Never retry in flight. A second request for the same ISIN waits on the same load and, once it completes, is counted too.
  • Batch and let pending work for you. POST /funds with wait: true returns what fits the time budget and marks the rest pending; they finish in the background and the next call finds them warm.
  • Pre-warm in a job, not a request handler. Seed your universe overnight, a few ISINs in parallel at most, and your users only ever hit warm payloads.
  • Cache locally until `expiresAt`. Then even the warm call is saved.

The demo endpoint never loads

GET /demo/funds/{isin} only returns funds already in the store (404 not_cached otherwise), which is why it is instant and keyless.

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.
bash
curl -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]}'

Frequently asked questions

Is a slow call counted more than once?

No: one request per ISIN answered, regardless of whether it took 50 milliseconds from the store or two minutes from the fund house.

Does the 24-hour store expire per fund?

Yes, per ISIN, 24 hours after it was produced; expiresAt in the payload is exact.

Try it on your own ISINs

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