{"openapi":"3.1.0","info":{"title":"FundFacts API","version":"2026-09-09","description":"FundFacts API turns any ISIN into a complete, structured fund factsheet: key facts, holdings, sector and country exposure, risk metrics, performance and fees. One REST call, JSON out, refreshed every 24 hours. Ships with an AI companion kit (AGENTS.md, Cursor rule, Claude Code skill, OpenAPI) so Cursor, Claude Code or Codex build your fund tool from a single prompt.\n\nCredits: one per ISIN answered by /funds, POST /funds, /portfolio and /overlap, one per call on /scpi/{idOrIsin}, one (HTML) or two (PDF) per generated /factsheets one-pager; /search, /scpi?q= and /me are free. Plans — Free $0: 150 credits / month, batch 1; Starter $9/mo: 1,500 credits / month, batch 10; Pro $49/mo: 9,000 credits / month, batch 50; Scale $249/mo: 60,000 credits / month, batch 200. Get a key at https://fundfactsapi.com/signup.","contact":{"email":"hello@fundfactsapi.com","url":"https://fundfactsapi.com"},"termsOfService":"https://fundfactsapi.com/terms"},"externalDocs":{"url":"https://fundfactsapi.com/docs","description":"Human-readable documentation"},"servers":[{"url":"https://fundfactsapi.com/api/v1"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"tags":[{"name":"Funds","description":"Structured factsheets from ISINs"},{"name":"Portfolio","description":"Aggregation across several funds"},{"name":"Monitoring","description":"Change feed and webhooks"},{"name":"Account","description":"Plan and credits"},{"name":"Demo","description":"Keyless, store-only reads for evaluation"},{"name":"SCPI","description":"French SCPIs (sociétés civiles de placement immobilier) from their management companies' documents"}],"paths":{"/funds/{isin}":{"get":{"tags":["Funds"],"operationId":"getFund","summary":"Structured factsheet for one ISIN","description":"Returns the fund's latest published figures as one JSON document. Payloads are refreshed at most once per 24 hours per ISIN; a cold ISIN can take 15 seconds to 3 minutes (server limit 300 s), so use a long client timeout and never issue the same request twice in parallel. One credit per call.","parameters":[{"name":"isin","in":"path","required":true,"description":"12-character ISIN, case-insensitive.","schema":{"type":"string","pattern":"^[A-Za-z]{2}[A-Za-z0-9]{9}[0-9]$","example":"IE00B4L5Y983"}}],"responses":{"200":{"description":"The factsheet envelope.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"upstream_error: The fund data could not be retrieved (temporary upstream outage). Retry later; the request is counted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/funds":{"post":{"tags":["Funds"],"operationId":"getFundsBatch","summary":"Batch lookup of several ISINs","description":"Up to the plan's batch size per call. Warm ISINs are answered from the store; cold ones are loaded a few at a time within the request budget and the rest come back with status `pending` while they are warmed in the background — re-send those later. One credit per ISIN with status `ok` or `not_found`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["isins"],"properties":{"isins":{"type":"array","items":{"type":"string"},"minItems":1,"example":["IE00B4L5Y983","IE00B3RBWM25"]},"wait":{"type":"boolean","default":true,"description":"false = store only; cold ISINs are returned as pending immediately."}}}}}},"responses":{"200":{"description":"One result per input, in input order.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/search":{"get":{"tags":["Funds"],"operationId":"searchFunds","summary":"Find ISINs by fund name, issuer or ISIN prefix","description":"Full-text search over funds that have already been loaded. Free; subject to the per-minute burst limit.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"example":"msci world"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"Matching funds.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/portfolio":{"post":{"tags":["Portfolio"],"operationId":"analyzePortfolio","summary":"Portfolio look-through","description":"Weighted aggregation across funds: blended TER, weighted risk indicator, asset / sector / country / region / credit exposure, currency split and aggregated top holdings, each with the share of the portfolio that discloses it. Weights are normalised to 100. One credit per position answered.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["positions"],"properties":{"positions":{"type":"array","minItems":1,"items":{"type":"object","required":["isin","weight"],"properties":{"isin":{"type":"string"},"weight":{"type":"number","minimum":0}}},"example":[{"isin":"IE00B4L5Y983","weight":60},{"isin":"IE00B3RBWM25","weight":40}]},"wait":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"Aggregated exposure.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/overlap":{"get":{"tags":["Portfolio"],"operationId":"fundOverlap","summary":"Holdings overlap between funds","description":"Pairwise overlap (sum of the smaller weight of every shared holding) over the holdings each fund discloses. One credit per ISIN answered.","parameters":[{"name":"isins","in":"query","required":true,"description":"Comma-separated ISINs, at least two.","schema":{"type":"string","example":"IE00B4L5Y983,IE00B3RBWM25"}},{"name":"wait","in":"query","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"Pairwise overlap.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverlapResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/changes":{"get":{"tags":["Monitoring"],"operationId":"listChanges","summary":"Change feed (Scale and Enterprise)","description":"Tracked fields that moved between refreshes (fund.changed) and as-of date moves (fund.refreshed). Free; burst-limited.","parameters":[{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Default: 7 days ago."},{"name":"isins","in":"query","schema":{"type":"string"},"description":"Comma-separated ISINs."},{"name":"event","in":"query","schema":{"type":"string","enum":["fund.changed","fund.refreshed"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":200}}],"responses":{"200":{"description":"Changes in ascending order.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangesResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"plan_required: Scale or Enterprise.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks":{"get":{"tags":["Monitoring"],"operationId":"listWebhooks","summary":"List webhook endpoints (Scale and Enterprise)","responses":{"200":{"description":"Endpoints without secrets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Monitoring"],"operationId":"createWebhook","summary":"Register a webhook endpoint (Scale and Enterprise)","description":"Returns the signing secret once. Deliveries carry X-FundFacts-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, `${t}.${body}`)>.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["fund.changed","fund.refreshed"]}},"isins":{"type":"array","items":{"type":"string"},"description":"Omit for every fund."}}}}}},"responses":{"201":{"description":"The endpoint and its secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}":{"delete":{"tags":["Monitoring"],"operationId":"deleteWebhook","summary":"Delete a webhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Monitoring"],"operationId":"webhookAction","summary":"Test, enable or disable a webhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["test","enable","disable"],"default":"test"}}}}}},"responses":{"200":{"description":"Result.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"delivered":{"type":"boolean"},"status":{"type":["integer","null"]},"active":{"type":"boolean"}}}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/export":{"get":{"tags":["Funds"],"operationId":"exportFunds","summary":"Bulk NDJSON export (Scale and Enterprise)","description":"Streams one envelope per line for every stored fund matching the filter. One credit per call.","parameters":[{"name":"issuer","in":"query","schema":{"type":"string"}},{"name":"assetClass","in":"query","schema":{"type":"string"}},{"name":"currency","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"gzip","in":"query","schema":{"type":"string","enum":["0","1"]}}],"responses":{"200":{"description":"application/x-ndjson stream.","content":{"application/x-ndjson":{"schema":{"type":"string"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/extract":{"post":{"tags":["Funds"],"operationId":"extractDocument","summary":"Extract a KID / KIID / factsheet into the FundData shape (Pro and up)","description":"Send a PDF (multipart `file`), a `url` or raw `text`; optional `isin` and `kind` (kid | factsheet). Five credits per document.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"},"isin":{"type":"string"},"kind":{"type":"string","enum":["kid","factsheet"]}}}},"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"text":{"type":"string"},"isin":{"type":"string"},"kind":{"type":"string","enum":["kid","factsheet"]}}}}}},"responses":{"200":{"description":"The extracted factsheet.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"upstream_error: The fund data could not be retrieved (temporary upstream outage). Retry later; the request is counted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/factsheets":{"post":{"tags":["Funds"],"operationId":"createFactsheet","summary":"One-page factsheet as HTML or PDF","description":"Renders the fund with the @fundfactsapi/widgets components. Returns the document (text/html or application/pdf; share links in the X-Factsheet-Url and X-Factsheet-Pdf-Url headers) or, with deliver: link, JSON with the saved sheet and its keyless URLs (html, pdf, embed iframe). One credit for HTML, two for PDF.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FactsheetRequest"}}}},"responses":{"200":{"description":"The factsheet document, or its links when deliver is link.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-Factsheet-Id":{"schema":{"type":"string"}},"X-Factsheet-Url":{"schema":{"type":"string","format":"uri"}},"X-Factsheet-Pdf-Url":{"schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FactsheetResponse"}},"text/html":{"schema":{"type":"string"}},"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"upstream_error: The fund data could not be retrieved (temporary upstream outage). Retry later; the request is counted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"pdf_unavailable: the PDF renderer is down; the HTML sheet was saved and its urls are in the error body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Funds"],"operationId":"listFactsheets","summary":"The account's generated factsheets (free)","parameters":[{"name":"issuer","in":"query","schema":{"type":"string"}},{"name":"favorites","in":"query","schema":{"type":"string","enum":["1"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FactsheetList"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/factsheets/{id}":{"get":{"tags":["Funds"],"operationId":"getFactsheet","summary":"One saved factsheet: metadata, or the document re-rendered from its snapshot (free)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"format","in":"query","schema":{"type":"string","enum":["json","html","pdf"],"default":"json"}}],"responses":{"200":{"description":"The sheet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Factsheet"}},"text/html":{"schema":{"type":"string"}},"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Funds"],"operationId":"updateFactsheet","summary":"Star or unstar a factsheet","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["favorite"],"properties":{"favorite":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated sheet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Factsheet"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Funds"],"operationId":"deleteFactsheet","summary":"Delete a factsheet; its share links stop working","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"},"id":{"type":"string"}}}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/me":{"get":{"tags":["Account"],"operationId":"getMe","summary":"Account, plan and credits for the key","responses":{"200":{"description":"Account state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/demo/funds/{isin}":{"get":{"tags":["Demo"],"operationId":"getDemoFund","summary":"Keyless read of an already-loaded fund","description":"No API key. Serves only funds already in the store (30 requests per minute per IP) and never triggers a load; use it to inspect the payload shape before signing up.","security":[],"parameters":[{"name":"isin","in":"path","required":true,"description":"12-character ISIN, case-insensitive.","schema":{"type":"string","pattern":"^[A-Za-z]{2}[A-Za-z0-9]{9}[0-9]$","example":"IE00B4L5Y983"}}],"responses":{"200":{"description":"The factsheet envelope without plan / quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemoFundResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/scpi/{idOrIsin}":{"get":{"tags":["SCPI"],"operationId":"getScpi","summary":"Structured data for one French SCPI","description":"Identify the SCPI by slug (perial-o2, corum-origin, epargne-pierre), ISIN or name. Figures are read from the management company's bulletin trimestriel, DIC, rapport annuel and note d'information; payloads are refreshed at most once per 24 hours (a cold SCPI takes 10-60 seconds). One credit per call.","parameters":[{"name":"idOrIsin","in":"path","required":true,"schema":{"type":"string","example":"perial-o2"},"description":"SCPI slug, ISIN or URL-encoded name."}],"responses":{"200":{"description":"The SCPI envelope.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScpiResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"fund_not_found: No public data could be retrieved for this ISIN (not a fund/ETF, delisted, or not covered yet). The response still contains the empty `data` skeleton. not_cached: Demo endpoint only: the ISIN has not been loaded yet. Use an API key to load it. not_found: Webhooks: no such endpoint on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"upstream_error: The fund data could not be retrieved (temporary upstream outage). Retry later; the request is counted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/scpi":{"get":{"tags":["SCPI"],"operationId":"searchScpi","summary":"Find SCPIs by name, management company or ISIN prefix","description":"Search over the known SCPI universe. Free; subject to the per-minute burst limit.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"example":"epargne pierre"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"Matching SCPIs.","headers":{"X-RateLimit-Limit":{"description":"Credits per month.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Credits left this month after this call.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix time (seconds) of the next monthly reset.","schema":{"type":"integer"}},"X-Burst-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-Burst-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScpiSearchResponse"}}}},"400":{"description":"invalid_isin: The ISIN is not syntactically valid (format + checksum), or a batch / portfolio / overlap call contained no valid ISIN. invalid_body: POST body is not the expected JSON shape (batch: { isins: [] }; portfolio: { positions: [{ isin, weight }] }). invalid_query: Search: ?q= is missing or shorter than two characters. batch_too_large: More ISINs than the plan's batch size (Free 1, Starter 10, Pro 50, Scale 200, Enterprise 1,000). Includes batchMax.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"missing_api_key: No Authorization: Bearer header (or X-Api-Key) was sent. invalid_api_key: The key is malformed or unknown. revoked_api_key: The key exists but was revoked from the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: Monthly credits (and overage cap) exhausted, or the per-minute burst limit hit. `reason` is credits_exhausted | overage_cap | burst; includes retryAfter (seconds) and resetAt; the Retry-After header is also set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer ffk_..."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-Api-Key"}},"schemas":{"FundResponse":{"type":"object","properties":{"isin":{"type":"string","description":"Canonical upper-case ISIN that was resolved."},"name":{"type":["string","null"],"description":"Fund / share-class name."},"cached":{"type":"boolean","description":"true when the payload was served from the 24-hour cache, false when it was refreshed for this request."},"generatedAt":{"type":"string","description":"When the payload was produced."},"expiresAt":{"type":"string","description":"When the payload will be considered stale and refreshed on the next request."},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"],"description":"Plan of the API key used for the request."},"quota":{"$ref":"#/components/schemas/Quota"},"data":{"$ref":"#/components/schemas/FundData"}}},"FundData":{"type":"object","properties":{"investmentObjective":{"type":"string","description":"The fund's stated investment objective / strategy paragraph."},"securityType":{"type":"string","description":"Security-type label of the share class."},"structure":{"type":"string","description":"Normalized structure token derived from securityType."},"shareClass":{"type":["string","null"],"description":"Share-class letter/label when it can be inferred (e.g. from the fund name)."},"keyFacts":{"type":"object","properties":{"assetClass":{"type":"string","description":"Broad asset class."},"subAsset":{"type":"string","description":"FundFacts category, identical to profile.category (composed from the disclosed exposures; see the profile group)."},"currency":{"type":"string","description":"Share-class base currency (ISO 4217)."},"aum":{"type":"string","description":"Fund size / net assets, formatted as reported, with unit and currency."},"inception":{"type":"string","description":"Inception date of the share class."},"distribution":{"type":"string","description":"Income treatment."},"holdings":{"oneOf":[{"type":"string"},{"type":"number"}],"description":"Number of holdings in the portfolio."},"manager":{"type":"string","description":"Portfolio manager(s) or management company."}}},"managerTenure":{"type":"string","description":"Tenure of the longest-serving manager, when disclosed."},"benchmarkName":{"type":"string","description":"Primary prospectus benchmark / index tracked."},"riskRating":{"type":["number","null"],"description":"SRRI / SRI risk indicator on a 1 (lowest) to 7 (highest) scale. Falls back to an asset-class heuristic when not disclosed."},"profile":{"type":"object","properties":{"kind":{"type":"string","enum":["equity","fixedIncome","moneyMarket","allocation","alternative","other"],"description":"Broad kind, derived from keyFacts.assetClass."},"category":{"type":"string","description":"Composed label: region + valuation (or sector for sector funds) for equity; currency + credit grade + duration for bonds; equity share for allocation funds."},"riskBand":{"type":["string","null"],"enum":["low","medium","high",null],"description":"SRRI 1–2 low, 3–4 medium, 5–7 high."},"concentration":{"type":["string","null"],"enum":["concentrated","balanced","diversified",null],"description":"Weight of the ten largest holdings: ≥50% concentrated, 30–50% balanced, <30% diversified."},"regionFocus":{"type":["string","null"],"description":"Largest region (or country) when it is ≥80% of the portfolio; otherwise \"Global\"."},"regionTilt":{"type":["string","null"],"description":"For Global funds, the largest region when it is 50–80% of the portfolio."},"sectorTilt":{"type":["string","null"],"description":"Equity only. Largest sector when ≥30%, otherwise \"Broad\". A fund with ≥50% in one sector is categorised as a sector fund."},"valuation":{"type":["string","null"],"enum":["value","blend","growth",null],"description":"Equity only, from the portfolio P/E: <15 value, 15–22 blend, >22 growth."},"creditQuality":{"type":["string","null"],"enum":["high","medium","low",null],"description":"Bonds and money market, from the credit buckets: AAA–A ≥60% high; investment grade (≥BBB) ≥80% medium; otherwise low."},"rateSensitivity":{"type":["string","null"],"enum":["limited","moderate","extensive",null],"description":"Bonds, from effective or modified duration: <3.5 years limited, 3.5–6 moderate, >6 extensive."},"equityShare":{"type":["number","null"],"description":"Allocation funds: equity weight of the asset allocation, in percent."},"rules":{"type":"string","description":"Version of the rule set that produced the profile."}}},"topHoldings":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"weight":{"type":"number"}}},"description":"Largest positions with their portfolio weight in percent."},"geography":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Country exposure."},"region":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Regional exposure. Mirrors geography when no distinct regional panel exists."},"sector":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Sector exposure (GICS-style for equity; instrument type for fixed income)."},"creditQuality":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Credit-rating buckets for fixed income and money-market funds."},"assetAllocation":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Asset-class split (equity / bond / cash / other) for allocation funds."},"instrument":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Instrument-type breakdown, mostly for money-market funds."},"maturity":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number"}}},"description":"Maturity buckets for fixed income / money-market funds."},"strategy":{"type":"array","items":{},"description":"Strategy allocation (e.g. for multi-strategy / alternative funds). Usually empty."},"exposure":{"type":"array","items":{},"description":"Additional exposure panel when available. Usually empty."},"calendarReturns":{"type":"object","properties":{"years":{"type":"array","items":{"type":"string"},"description":"Calendar years covered, oldest first, clamped to the inception year. Partial (current) years are excluded."},"fund":{"type":"array","items":{"type":"number"},"description":"Fund total return per calendar year, in percent, aligned with years."},"benchmark":{"type":"array","items":{"type":["number","null"]},"description":"Benchmark return per calendar year, in percent, when the factsheet states it (null otherwise)."}}},"cumulativePerformance":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"fund":{"type":["number","null"]},"benchmark":{"type":["number","null"]}}},"description":"Monthly cumulative return series (percent from the first point, rebased at the share-class inception)."},"indexedPerformance":{"type":"object","properties":{"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"fund":{"type":["number","null"]},"index":{"type":["number","null"]}}},"description":"Same series rebased to 100 at the first point, ready to plot."},"hasIndex":{"type":"boolean","description":"Whether the index series is populated."}}},"annualisedReturns":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"fund":{"type":["number","null"]},"index":{"type":["number","null"]}}},"description":"Trailing returns: 1 Year, 3/5/10 Years p.a. and Since Inception. Multi-year figures are annualised."},"headlineMetrics":{"type":"object","properties":{"ter":{"type":"string","description":"Total expense ratio / ongoing charge, as stated in the KID or factsheet."},"aum":{"type":"string","description":"Fund size (duplicate of keyFacts.aum for factsheet layouts)."},"volatility3y":{"type":"string","description":"3-year annualised standard deviation of monthly returns."},"sharpe3y":{"type":"string","description":"3-year Sharpe ratio (annualised return over annualised volatility, 0% risk-free rate)."},"yieldToMaturity":{"type":"string","description":"Yield to maturity (fixed income)."},"modifiedDuration":{"type":"string","description":"Modified duration in years (fixed income)."}}},"metrics":{"type":"object","properties":{"peRatio":{"type":"string","description":"Portfolio price/earnings ratio (equity)."},"incomeYield":{"type":"string","description":"Distribution / dividend yield."},"volatility3y":{"type":"string","description":"3-year volatility (per-asset-class metric slot)."},"sharpe3y":{"type":"string","description":"3-year Sharpe ratio (per-asset-class metric slot)."},"yieldToMaturity":{"type":"string","description":"Yield to maturity (fixed income slot)."},"effectiveDuration":{"type":"string","description":"Effective duration in years."},"effectiveMaturity":{"type":"string","description":"Effective / average maturity in years."},"averageRating":{"type":"string","description":"Average credit rating of the portfolio."},"sevenDayYield":{"type":"string","description":"7-day yield (money market)."},"wam":{"type":"string","description":"Weighted average maturity in days (money market)."},"wal":{"type":"string","description":"Weighted average life in days (money market)."},"maxDrawdown":{"type":"string","description":"Maximum peak-to-trough drawdown over the trailing 3 years."},"equityCorrelation":{"type":"string","description":"Correlation to equities (alternatives / allocation)."},"equityBondSplit":{"type":"string","description":"Equity/bond split summary for allocation funds."}}},"sfdrArticle":{"type":["number","null"],"description":"SFDR classification stated in the fund's documents: 6 (no sustainability objective), 8 (promotes E/S characteristics) or 9 (sustainable investment objective). null when not disclosed."},"costs":{"type":"object","properties":{"entry":{"type":"string","description":"Entry costs (one-off), as printed in the KID."},"exit":{"type":"string","description":"Exit costs (one-off)."},"ongoing":{"type":"string","description":"Management fees and other administrative or operating costs per year (the KID's ongoing-cost line). Falls back to headlineMetrics.ter."},"transaction":{"type":"string","description":"Portfolio transaction costs per year."},"performanceFee":{"type":"string","description":"Performance fee, when the fund charges one."},"riy1y":{"type":"string","description":"Annual cost impact if you exit after one year (reduction in yield)."},"riyRhp":{"type":"string","description":"Annual cost impact at the recommended holding period."},"recommendedHoldingPeriod":{"type":"string","description":"Recommended holding period stated in the KID."}}},"dataAsOf":{"type":"string","description":"'As of' date of the underlying figures: the latest NAV observation when a NAV history is used, otherwise the factsheet's reporting date."},"generatedAt":{"type":"string","description":"Timestamp of the refresh that produced this payload. Payloads are refreshed when older than 24 hours."}}},"DemoFundResponse":{"type":"object","properties":{"isin":{"type":"string"},"name":{"type":["string","null"]},"demo":{"type":"boolean","const":true},"cached":{"type":"boolean"},"generatedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"data":{"$ref":"#/components/schemas/FundData"}}},"Quota":{"type":"object","description":"Credit state after the call.","properties":{"limit":{"type":["integer","null"],"description":"Credits per month; null = metered."},"remaining":{"type":["integer","null"],"description":"Credits left this month (0 while on overage)."},"used":{"type":"integer","description":"Billable requests this month, including this call."},"overageUsed":{"type":"integer"},"resetAt":{"type":"string","format":"date-time","description":"Next monthly reset (UTC)."},"burst":{"type":"object","properties":{"limit":{"type":["integer","null"]},"remaining":{"type":["integer","null"]}}}}},"BatchItem":{"type":"object","properties":{"input":{"type":"string"},"isin":{"type":["string","null"]},"status":{"type":"string","enum":["ok","not_found","pending","invalid","error"]},"name":{"type":["string","null"]},"cached":{"type":"boolean"},"generatedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"data":{"oneOf":[{"$ref":"#/components/schemas/FundData"},{"type":"null"}]}}},"BatchResponse":{"type":"object","properties":{"count":{"type":"integer"},"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchItem"}},"pending":{"type":"array","items":{"type":"string"}},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"SearchHit":{"type":"object","properties":{"isin":{"type":"string"},"name":{"type":["string","null"]},"issuer":{"type":["string","null"]},"currency":{"type":["string","null"]},"assetClass":{"type":["string","null"]},"shareClass":{"type":["string","null"]},"income":{"type":["string","null"]},"category":{"type":["string","null"]},"dataAsOf":{"type":["string","null"]},"url":{"type":["string","null"],"format":"uri","description":"Public fund page, or null when fund pages are not published."}}},"SearchResponse":{"type":"object","properties":{"query":{"type":"string"},"count":{"type":"integer"},"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchHit"}},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"Weighted":{"type":"object","properties":{"label":{"type":"string"},"weight":{"type":"number","description":"Percent."}}},"YearValue":{"type":"object","properties":{"year":{"type":"string","example":"2025"},"value":{"type":"number"}}},"ScpiData":{"type":"object","description":"Structured SCPI payload; scalars are null and arrays empty when the documents do not state the value. See /docs/scpi.","properties":{"keyFacts":{"type":"object","properties":{"name":{"type":"string"},"managementCompany":{"type":"string"},"isin":{"type":["string","null"]},"category":{"type":["string","null"],"enum":["bureaux","commerces","santé","logistique","diversifiée","résidentiel","européenne","autre",null]},"capitalType":{"type":["string","null"],"enum":["fixe","variable",null]},"creationYear":{"type":["integer","null"]},"capitalisationEur":{"type":["number","null"]},"sharePriceEur":{"type":["number","null"],"description":"Prix de souscription, EUR per share."},"withdrawalPriceEur":{"type":["number","null"],"description":"Prix de retrait, EUR per share."},"subscriptionFeesPct":{"type":["number","null"]},"managementFeesPct":{"type":["number","null"]},"minimumSubscriptionShares":{"type":["number","null"]},"minimumSubscriptionEur":{"type":["number","null"]},"delayOfJouissance":{"type":["string","null"]},"riskIndicator":{"type":["integer","null"],"minimum":1,"maximum":7},"sfdrArticle":{"type":["integer","null"]},"labelIsr":{"type":["boolean","null"]}}},"performance":{"type":"object","properties":{"distributionRateByYear":{"type":"array","items":{"$ref":"#/components/schemas/YearValue"},"description":"Taux de distribution, percent, per calendar year."},"distributionPerShareByYear":{"type":"array","items":{"$ref":"#/components/schemas/YearValue"},"description":"Dividende brut par part, EUR."},"tri":{"type":"object","properties":{"y5":{"type":["number","null"]},"y10":{"type":["number","null"]},"y15":{"type":["number","null"]}}},"reconstitutionValueEur":{"type":["number","null"]},"realisationValueEur":{"type":["number","null"]},"sharePriceHistory":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"priceEur":{"type":"number"}}}},"lastQuarterDistributionPerShareEur":{"type":["number","null"]}}},"portfolio":{"type":"object","properties":{"numberOfProperties":{"type":["number","null"]},"surfaceSqm":{"type":["number","null"]},"numberOfTenants":{"type":["number","null"]},"financialOccupancyRatePct":{"type":["number","null"],"description":"TOF, percent."},"physicalOccupancyRatePct":{"type":["number","null"],"description":"TOP, percent."},"walbYears":{"type":["number","null"]},"waltYears":{"type":["number","null"]},"sectorSplit":{"type":"array","items":{"$ref":"#/components/schemas/Weighted"}},"geographicSplit":{"type":"array","items":{"$ref":"#/components/schemas/Weighted"}},"topTenants":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"weight":{"type":["number","null"]}}}}}},"liquidity":{"type":"object","properties":{"sharesAwaitingWithdrawal":{"type":["number","null"]},"netInflowLastQuarterEur":{"type":["number","null"]},"sharesOutstanding":{"type":["number","null"]},"numberOfAssociates":{"type":["number","null"]}}},"documents":{"type":"object","properties":{"productUrl":{"type":["string","null"]},"bulletinUrl":{"type":["string","null"]},"annualReportUrl":{"type":["string","null"]},"kidUrl":{"type":["string","null"]},"noteInformationUrl":{"type":["string","null"]},"statutsUrl":{"type":["string","null"]},"factsheetUrl":{"type":["string","null"]}}},"dataAsOf":{"type":"string","description":"ISO date of the latest bulletin's figures; empty when unknown."},"bulletinPeriod":{"type":["string","null"],"example":"T2 2026"},"generatedAt":{"type":"string","format":"date-time"}}},"ScpiResponse":{"type":"object","properties":{"slug":{"type":"string"},"isin":{"type":["string","null"]},"name":{"type":["string","null"]},"manager":{"type":["string","null"],"description":"Management-company adapter id."},"cached":{"type":"boolean"},"generatedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"},"data":{"$ref":"#/components/schemas/ScpiData"}}},"ScpiSearchResponse":{"type":"object","properties":{"query":{"type":"string"},"count":{"type":"integer"},"results":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"isin":{"type":["string","null"]},"name":{"type":"string"},"manager":{"type":"string"},"managerName":{"type":"string"},"category":{"type":["string","null"]},"loaded":{"type":"boolean","description":"True when a payload is already in the store."},"dataAsOf":{"type":["string","null"]},"url":{"type":"string"}}}},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"Breakdown":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Weighted"}},"coverage":{"type":"number","description":"Share of the portfolio (percent) whose funds disclose this breakdown."}}},"PortfolioResponse":{"type":"object","properties":{"positions":{"type":"array","items":{"type":"object","properties":{"isin":{"type":"string"},"name":{"type":["string","null"]},"weight":{"type":"number","description":"Normalised weight, percent."},"covered":{"type":"boolean"},"ter":{"type":["number","null"]},"riskRating":{"type":["integer","null"]},"category":{"type":["string","null"]},"kind":{"type":["string","null"]}}}},"coverage":{"type":"number"},"fees":{"type":"object","properties":{"weightedTer":{"type":["number","null"]},"coverage":{"type":"number"},"annualCostPer10k":{"type":["number","null"]}}},"risk":{"type":"object","properties":{"weightedSrri":{"type":["number","null"]},"band":{"type":["string","null"],"enum":["low","medium","high",null]},"coverage":{"type":"number"}}},"kinds":{"type":"array","items":{"$ref":"#/components/schemas/Weighted"}},"assetAllocation":{"$ref":"#/components/schemas/Breakdown"},"sector":{"$ref":"#/components/schemas/Breakdown"},"geography":{"$ref":"#/components/schemas/Breakdown"},"region":{"$ref":"#/components/schemas/Breakdown"},"creditQuality":{"$ref":"#/components/schemas/Breakdown"},"currency":{"type":"array","items":{"$ref":"#/components/schemas/Weighted"}},"topHoldings":{"allOf":[{"$ref":"#/components/schemas/Breakdown"},{"type":"object","properties":{"note":{"type":"string"}}}]},"pending":{"type":"array","items":{"type":"string"}},"invalid":{"type":"array","items":{"type":"string"}},"rules":{"type":"string"},"generatedAt":{"type":"string","format":"date-time"},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"OverlapResponse":{"type":"object","properties":{"funds":{"type":"array","items":{"type":"object","properties":{"isin":{"type":"string"},"name":{"type":["string","null"]},"holdings":{"type":"integer"}}}},"pairs":{"type":"array","items":{"type":"object","properties":{"a":{"type":"string"},"b":{"type":"string"},"overlap":{"type":"number","description":"Percent of portfolio held in common."},"sharedCount":{"type":"integer"},"shared":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"a":{"type":"number"},"b":{"type":"number"}}}},"disclosed":{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}}}}}},"pending":{"type":"array","items":{"type":"string"}},"notFound":{"type":"array","items":{"type":"string"}},"note":{"type":"string"},"rules":{"type":"string"},"generatedAt":{"type":"string","format":"date-time"},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"ChangesResponse":{"type":"object","properties":{"since":{"type":"string","format":"date-time"},"count":{"type":"integer"},"hasMore":{"type":"boolean"},"nextSince":{"type":"string","format":"date-time"},"changes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"isin":{"type":"string"},"name":{"type":["string","null"]},"event":{"type":"string","enum":["fund.changed","fund.refreshed"]},"field":{"type":"string"},"old":{},"new":{},"dataAsOf":{"type":["string","null"]},"changedAt":{"type":"string","format":"date-time"}}}},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"Webhook":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"isins":{"type":["array","null"],"items":{"type":"string"}},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"lastDeliveryAt":{"type":["string","null"],"format":"date-time"},"lastStatus":{"type":["integer","null"]}}},"WebhookList":{"type":"object","properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}},"WebhookCreated":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string"},"signature":{"type":"string"}}}]},"FactsheetRequest":{"type":"object","required":["isin"],"properties":{"isin":{"type":"string","pattern":"^[A-Za-z]{2}[A-Za-z0-9]{9}[0-9]$","example":"IE00B4L5Y983"},"format":{"type":"string","enum":["html","pdf"],"default":"html"},"deliver":{"type":"string","enum":["file","link"],"default":"file","description":"file: the document itself; link: JSON with the saved sheet and its URLs."},"theme":{"type":"string","enum":["light","dark"],"default":"light"},"accent":{"type":"string","pattern":"^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","description":"Hex colour for charts, tiles and the header rule."},"title":{"type":"string","maxLength":80,"description":"Your firm or product name in the header, instead of the FundFacts wordmark."},"branding":{"type":"boolean","default":true,"description":"The Powered-by line in the footer; can only be turned off on Pro and above."}}},"Factsheet":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"isin":{"type":"string"},"name":{"type":["string","null"]},"issuer":{"type":["string","null"]},"format":{"type":"string","enum":["html","pdf"]},"options":{"type":"object","properties":{"theme":{"type":"string","enum":["light","dark"]},"accent":{"type":["string","null"]},"title":{"type":["string","null"]},"branding":{"type":"boolean"}}},"favorite":{"type":"boolean"},"views":{"type":"integer","description":"Opens of the public share links."},"createdAt":{"type":"string","format":"date-time"},"dataAsOf":{"type":["string","null"]},"generatedAt":{"type":["string","null"],"description":"When the underlying fund payload was generated."},"urls":{"type":"object","description":"Keyless links; no API key needed to open or embed them.","properties":{"html":{"type":"string","format":"uri"},"pdf":{"type":"string","format":"uri"},"embed":{"type":"string","description":"Ready-to-paste <iframe> snippet."}}}}},"FactsheetResponse":{"allOf":[{"$ref":"#/components/schemas/Factsheet"},{"type":"object","properties":{"credits":{"type":"integer"},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}}]},"FactsheetList":{"type":"object","properties":{"count":{"type":"integer"},"factsheets":{"type":"array","items":{"$ref":"#/components/schemas/Factsheet"}}}},"ExtractResponse":{"type":"object","properties":{"document":{"type":"object","properties":{"label":{"type":"string"},"kind":{"type":"string","enum":["kid","factsheet"]},"pages":{"type":["integer","null"]},"chars":{"type":"integer"}}},"isin":{"type":["string","null"]},"name":{"type":["string","null"]},"fieldsFilled":{"type":"integer"},"credits":{"type":"integer"},"data":{"$ref":"#/components/schemas/FundData"},"plan":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_isin","invalid_body","invalid_query","batch_too_large","missing_api_key","invalid_api_key","revoked_api_key","fund_not_found","plan_required","not_cached","not_found","rate_limited","upstream_error","plan_required","not_found"]},"message":{"type":"string"},"reason":{"type":"string","enum":["credits_exhausted","overage_cap","burst"],"description":"429 only."},"retryAfter":{"type":"integer","description":"429 only: seconds to wait."},"resetAt":{"type":["string","null"],"format":"date-time"},"batchMax":{"type":"integer","description":"batch_too_large only."}}},"isin":{"type":"string"},"cached":{"type":"boolean"},"generatedAt":{"type":["string","null"],"format":"date-time"},"data":{"$ref":"#/components/schemas/FundData","description":"404 fund_not_found only: empty skeleton."}}},"Me":{"type":"object","properties":{"email":{"type":["string","null"]},"plan":{"type":"object","properties":{"id":{"type":"string","enum":["free","starter","pro","scale","enterprise"]},"name":{"type":"string"},"credits":{"type":["integer","null"]},"burstPerMinute":{"type":["integer","null"]},"batchMax":{"type":"integer"},"overageUsd":{"type":["number","null"]},"quota":{"type":"string"}}},"quota":{"$ref":"#/components/schemas/Quota"},"usage":{"type":"object","properties":{"thisMonth":{"type":"integer"},"monthStart":{"type":"string","format":"date-time"}}}}}}}}