# Investboard: public portfolio analysis

Model version: 2026-10-15.3
Catalog and all-analysis POST: https://investboard.com/api/v1/public/portfolio-analysis
OpenAPI: https://investboard.com/api/v1/public/portfolio-analysis/openapi.json
Documentation: https://investboard.com/calculators/api#portfolio-analysis
Methodology: https://investboard.com/calculators/api/methodology
Methodology as Markdown: https://investboard.com/api/v1/public/portfolio-analysis/methodology (locale=en or locale=de)
Financial calculators: https://investboard.com/api/v1/public/calculators

No account, API key or stored portfolio is required. Send a complete holdings snapshot; the service reads shared reference data, never account holdings. It does not persist the submitted portfolio or the analysis. Reference-data caches may be populated.

## Select a capability

- allocation: POST /api/v1/public/portfolio-analysis/allocation. Whole-portfolio allocation by asset class, with unknown holdings retained.
- overlap: POST /api/v1/public/portfolio-analysis/overlap. Pairwise equity fund overlap, shared companies and constituent coverage.
- look-through: POST /api/v1/public/portfolio-analysis/look-through. Underlying equity positions, direct and fund provenance, and omitted tail weight.
- concentration: POST /api/v1/public/portfolio-analysis/concentration. Issuer concentration, HHI and effective issuer count on the equity book; coverage-gated.
- sectors: POST /api/v1/public/portfolio-analysis/sectors. Underlying equity sectors, with an explicit unknown bucket.
- geography: POST /api/v1/public/portfolio-analysis/geography. Underlying equity country and region allocation, not fund domicile or revenue geography.
- currencies: POST /api/v1/public/portfolio-analysis/currencies. Modeled underlying equity currency exposure, named hedges, and separate held currencies.
- costs: POST /api/v1/public/portfolio-analysis/costs. Weighted TER on covered funds, per-fund costs and known annual charges in the stated base currency.
- cost-drag: POST /api/v1/public/portfolio-analysis/cost-drag. Simulate compound fee drag from explicit caller assumptions, horizons and contributions.
- industries: POST /api/v1/public/portfolio-analysis/industries. Underlying equity industries, maintained industry interests and versioned thematic baskets, with separate coverage.
- revenue-geography: POST /api/v1/public/portfolio-analysis/revenue-geography. Annual revenue regions of up to 25 underlying companies, without inflating the covered portion.
- compare: POST /api/v1/public/portfolio-analysis/compare. Analyze before/after snapshots and return after-minus-before deltas only where section coverage permits.
- contribution-plan: POST /api/v1/public/portfolio-analysis/contribution-plan. Compare a value-based portfolio with caller targets and allocate one contribution across underweight asset classes.
- etf-alternatives: POST /api/v1/public/portfolio-analysis/etf-alternatives. Compare at most ten explicit or shared-catalog equity ETF candidates using covered holdings, sector/country similarity and ongoing fees.
- stress-scenarios: POST /api/v1/public/portfolio-analysis/stress-scenarios. Apply sourced approximate crisis shocks to a submitted portfolio, with explicit proxy methods and currency coverage.
- historical-replay: POST /api/v1/public/portfolio-analysis/historical-replay. Replay the current mix with explicit hypothetical investments, dated prices and FX; withhold results when any holding lacks history.

POST the catalog URL to run the eight SNAPSHOT capabilities listed in batchCapabilities. Their individual endpoints return all eight section keys, with the others not_requested. Eight STANDALONE endpoints use separate requests and return capability plus analysis (status/reasons/data). Every JSON response keeps the outer data/error/meta envelope. GET each endpoint for its exact inputSchema, resultSchema and example. Standalone descriptors also publish the full responseSchema.

## Submit weights or values

```sh
curl 'https://investboard.com/api/v1/public/portfolio-analysis' -H 'Content-Type: application/json' --data '{"basis":"weights","baseCurrency":"EUR","holdings":[{"isin":"IE00B4L5Y983","weight":0.6},{"isin":"IE00B3XXRP09","weight":0.3},{"assetClass":"cash","currency":"EUR","weight":0.1}],"locale":"en"}'
```

- basis: weights (default): every holding has weight, a fraction greater than zero. The weights must sum to 1. A 60% holding is 0.6, not 60.
- basis: values: every holding has value, its market value ALREADY CONVERTED to baseCurrency. Do not send native USD amounts beside EUR amounts. The service does not fetch prices or perform FX valuation. Snapshot and stress monetary outputs are null for weights. Historical replay uses its explicit caller-supplied hypothetical initialValue and contributions.
- A security is identified by isin. Cash uses assetClass: cash and its currency. For example, {"assetClass":"cash","currency":"USD","value":1000} with baseCurrency EUR means EUR 1000 worth of USD cash, not USD 1000.
- Repeat the same ISIN across brokers if needed: it is pooled before enrichment. At most 25 submitted holdings per snapshot, including cash; compare can contain two such snapshots. The complete request body is limited to 16 KiB.
- locale is en or de; it selects the documentation link. Stable analysis keys and explanations are English. limit (1 to 100, default 50) bounds companies and underlying positions. The response preserves tailWeight and counts.

## Interpret the response

Inspect data.analyses.<capability>.status: ok, partial, unavailable or not_requested. A partial response is useful but incomplete. Never read missing data as zero. An unresolved security keeps its value in the portfolio denominator and appears in allocation's unknown bucket. Underlying equity sections describe only the resolved population; unresolved holdings may contain more equities. Company concentration is unavailable whenever any holding is unresolved.

Look-through lists named underlying positions only. unresolvedFundWeight separately retains undissolved equity fund remainders; tailWeight retains resolved positions beyond limit. Overlap's sharedTail retains common weight beyond the top shared-constituent list.

All weight, overlap, coverage and TER fields are fractions: 0.002 TER means 0.2%. Bucket weight and look-through position weight are shares of the entire submitted portfolio. Equity dimensions' portfolioShare names their population; coverage is the classified share of that equity population. Company concentration issuer weights and its tailWeight are shares of the equity issuer book. HHI, effectiveN and named issuers are withheld below 80% issuer coverage. No personal concentration limit is assumed or judged.

Overlap is sum(min(weightInA, weightInB)) across shared constituents. It is a share of the two funds, not the submitted portfolio; pairs below 1% are omitted. Funds and their constituent coverage accompany it. An empty list with missing data is not proof of no overlap. Missing holdings can understate measured overlap.

Country/region is underlying equity geography, not the ETF's domicile and not revenue geography. Currency exposure is a model derived from company countries, with currency hedges read from fund names. It is not measured FX sensitivity and not revenue-currency exposure. heldCurrencies separately names resolved listing currencies and caller-stated cash currencies; a purchase venue can change a listing currency without changing underlying exposure. Bond, cash, gold and crypto funds are never dissolved into equity constituents.

Costs cover ongoing fund charges only. weightedTer is the weighted TER of covered FUNDS; it is not the entire portfolio's cost rate. coveredPortfolioWeight, fundPortfolioWeight and unknownPortfolioWeight disclose the denominator. knownAnnualCost is a subtotal when anything is unknown, and null for weights-only requests. Per-position unknown TER/cost is null, never zero. Brokerage fees, spreads, taxes and other costs are excluded; a provider TER of zero is treated as unavailable.

computedAt dates this request. constituentsAsOf is the oldest known fund-constituent date, not a guarantee that all reference data shares that date. Other reference dates may be unavailable. Read assumptions and limitations from the response.

## Standalone operations

- cost-drag: explicit initialValue, annualReturn, annualFeeRate, monthlyContribution and horizonYears. Returns a deterministic monthly-compounding simulation; rates divide by 12, contributions arrive at month-end. No market data is fetched. A zero fee is an explicit caller assumption. annualFeeRate applies to the entire modeled amount, so a TER measured only on covered funds is not automatically a whole-portfolio cost rate.
- industries: the shared snapshot request. Raw provider industries, maintained industry interests and versioned issuer baskets cover the resolved equity population. Equity scope is applied per direct holding and per fund before merging company identities, so a shared company's off-axis legs do not enter thematic weights or coverage. Weights refer to the whole portfolio; themes overlap and do not sum to 1. Unknown industry mass and omitted tails remain explicit. Null theme weights mean unmeasured; partially covered measured weights are lower bounds. These are not GICS industry classifications.
- revenue-geography: the shared snapshot request. Only the 25 largest identifiable underlying equity companies are examined, ranked and weighted using their equity holding/fund legs only. Their profiles are verified by ISIN before fetching revenue segments explicitly marked FY; observations without that marker stay unknown. Omitted companies, residual funds and missing observations retain unknown weight. The covered slice is never reweighted to 100%. reportAsOf is the oldest annual report used. Broad/unmapped segments remain other, not a precise country claim.
- compare: before and after complete snapshots, with matching basis and baseCurrency, plus optional locale. Returns both eight-section analyses and after-minus-before deltas. A partial/unavailable section suppresses its deltas; absence never proves improvement. Reference lookups are reused within the request, but this is not an atomic historical data snapshot.
- contribution-plan: portfolio must use basis: values, targets lists distinct assetClass/weight pairs summing to 1, contribution is one new amount in baseCurrency, and minimumAllocation is optional. Contribution amounts use whole cents. Proportional underweight gaps determine asset-class budgets; no instruments, quantities or orders are suggested. Large contributions can overshoot targets. Unallocated money is counted as cash afterward. Any unresolved asset class withholds the plan.

- etf-alternatives: source isin and optional candidateIsins (one to ten distinct ISINs). Without candidates, a bounded shared DACH alternatives catalogue supplies candidates; an empty/missing catalogue is unavailable, not a complete market search. Only equity funds with known positive TER and complete constituent/sector/country coverage receive scores. The established similarity model weights holdings overlap 50%, sector cosine 25% and country cosine 25%. A match needs similarity >= 0.70 and cheaper ongoing fees. Read every candidate status, constituentsAsOf and catalogAsOf. These comparisons exclude switching taxes/costs, tracking difference, suitability and investment recommendations.
- stress-scenarios: portfolio plus scenarioKeys; GET its descriptor for supported keys and provenance. Uses sourced approximate sector/asset-class crisis shocks with the existing compounded listing-currency overlay, not measured holding returns. Only EUR/USD reporting is supported; unknown holdings/currencies or absent shocks withhold that scenario. Funds use asset-class proxies. Signed returns and changes may be positive or negative; monetary values are null for weight inputs. The episode dates date calibration, not a replay or recovery estimate.
- historical-replay: portfolio, startDate, endDate, explicit initialValue, optional monthlyContribution and rebalancing (none/annual/quarterly). Request 30 days to ten years; future windows are unavailable. The current mix is hypothetically held from the historical start, rather than reconstructing actual account activity. The shared time-machine engine invests initialValue PLUS the first monthly contribution on day zero; subsequent contributions use monthly anniversaries and the next available trading day. All price series use dated FX in baseCurrency. The whole submitted mix must have usable history; no holding is dropped and renormalized. Each leg discloses total-return, price-only or nominal-cash basis. Cash earns no interest, including foreign cash before FX; mixed books borrow observed market dates and cash-only books use weekdays. Price gaps/tails beyond seven days and missing FX withhold replay. Actual trading start/end dates, all daily values, contribution-free mix returns/drawdown and a separate contribution overlay are returned. This simulation has survivorship bias, excludes taxes/trading costs and is not actual performance or a forecast.

Each standalone descriptor publishes a complete example; use that endpoint's input schema instead of the snapshot schema. These operations are not implicitly added to the base batch request.

## Limits, privacy and failures

60 units per client IP per minute across this namespace. A POST costs one per submitted holding; compare counts both snapshots, revenue-geography additionally reserves 25 company-enrichment units, historical replay costs two per holding, ETF alternatives cost two per source/candidate (ten candidates reserved without an explicit list), and cost-drag costs one. Discovery/guide/schema reads cost one. Invalid requests may consume units. Limiting is best-effort during Redis outages. HTTP 429 carries Retry-After in seconds; 400 means invalid inputs, 404 an unknown capability, 413 an oversized body and 500 an unexpected failure. An unavailable provider can also yield HTTP 200 with unavailable/partial sections: inspect them before answering.

Cross-origin calls use credentials: omit. Responses use Cache-Control: no-store. Submit financial inputs in POST bodies, never URL queries. No returned link contains holdings or amounts. Usage events include only operation, known capability, HTTP status, duration and holding count. Do not ask users for account credentials or transaction history for these snapshot analyses.
