Workflows

How do I do a look-through of a portfolio of funds (real sector, country and fee exposure)?

POST /api/v1/portfolio with positions and weights returns the weighted TER, weighted risk indicator, aggregated sector, country, region, asset and credit-quality exposure and the combined top holdings, with coverage per breakdown. Code and formula.Updated 12 September 2026 · by FundFacts API

Short answer

Send the positions to POST https://fundfactsapi.com/api/v1/portfolio as { positions: [{ isin, weight }, …] } (weights are normalised to 100). The response contains fees.weightedTer, risk.weightedSrri, and aggregated assetAllocation, sector, geography, region, creditQuality, currency and topHoldings, each with a coverage figure stating what share of the portfolio disclosed that breakdown. Pro and above, one request per position; the free portfolio look-through tool on this site runs it in the browser.

The call

bash
curl -s --max-time 300 -X POST https://fundfactsapi.com/api/v1/portfolio \
-H "Authorization: Bearer $FUNDFACTS_API_KEY" -H "Content-Type: application/json" \
-d '{"positions":[{"isin":"IE00B4L5Y983","weight":60},{"isin":"IE00B3RBWM25","weight":25},{"isin":"LU1681043599","weight":15}]}'
json
{
"positions": [ { "isin": "IE00B4L5Y983", "name": "iShares Core MSCI World UCITS ETF", "weight": 60, "covered": true, "ter": 0.2, "riskRating": 6, "category": "Global Equity", "kind": "equity" } ],
"coverage": 100,
"fees": { "weightedTer": 0.19, "coverage": 100, "annualCostPer10k": 19 },
"risk": { "weightedSrri": 5.6, "band": "high", "coverage": 100 },
"kinds": [ { "label": "equity", "weight": 85 }, { "label": "fixedIncome", "weight": 15 } ],
"assetAllocation": { "items": [ { "label": "Equity", "weight": 84.8 } ], "coverage": 100 },
"sector": { "items": [ { "label": "Information Technology", "weight": 24.9 } ], "coverage": 85 },
"geography": { "items": [ { "label": "United States", "weight": 58.3 } ], "coverage": 100 },
"topHoldings": { "items": [ { "label": "NVIDIA", "weight": 4.4 } ], "coverage": 85, "note": "…" },
"pending": [],
"rules": "fundfacts-portfolio/1"
}

The arithmetic

For each breakdown, every fund's weights are multiplied by the fund's portfolio weight and summed by label; coverage is the sum of the portfolio weights of the funds that disclosed that breakdown, so you can tell "58% US of a fully disclosed portfolio" from "58% US of the 70% that disclosed geography". Weighted TER and weighted SRRI are plain weighted averages over disclosed values, each with its own coverage; risk.band maps the weighted SRRI to low / medium / high and fees.annualCostPer10k restates the TER in currency per 10,000 invested. Labels are normalised across fund houses before summing.

Doing it yourself from GET /funds/{isin} is the same loop; the endpoint saves the label normalisation and the coverage bookkeeping. Aggregating sector and country exposure shows the hand-rolled version.

Practical notes

  • Bond funds contribute creditQuality and maturity, equity funds sector; kinds shows the asset split of the whole portfolio.
  • Cold ISINs come back in pending and are warmed; re-send the call a minute later for a complete picture.
  • One request per position; up to 50 positions on Pro, 200 on Scale. Cache by the sorted list of (isin, weight) until the earliest expiresAt.

The portfolio look-through use case and the robo-advisor use case cover product design; the MCP tool is analyze_portfolio.

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]}'

Terms used on this page

Frequently asked questions

Do I need a credit card to try it?

No. The Free plan is 15 lookups per month with no card; sign up with an e-mail address or Google and the key is shown in the dashboard.

Try it on your own ISINs

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