{ "openapi": "3.1.0",
  "info": { "title": "Läpivalaisu API", "version": "0.1.0", "description": "Stateless look-through analysis for Finnish portfolios. The server never fetches, stores or logs issuer holdings: the caller downloads the issuer file itself (see GET /api/analyze or the MCP server), parses it, and sends parsed holdings in the request. Estimate only, not investment advice (ei sijoitusneuvontaa)." },
  "servers": [{ "url": "https://lapivalaisu.pages.dev" }],
  "paths": { "/api/analyze": {
    "get": { "summary": "Usage and supported funds with official download URLs", "responses": { "200": { "description": "Info" } } },
    "post": { "summary": "Analyze portfolio (look-through)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Request" },
      "example": { "account": "aot", "funds": [{ "id": "EUNL", "asOf": "2026-10-19", "source": "https://www.ishares.com/...", "holdings": [{ "n": "APPLE", "w": 4.8, "s": "Teknologia", "c": "United States", "cur": "USD", "px": 230.1 }] }], "positions": [{ "id": "EUNL", "eur": 20000 }, { "id": "Nordea", "eur": 2000 }] } } } },
      "responses": { "200": { "description": "Analysis: summary, topHoldings, sectors, countries, currencies, overlap, dividends (estimate + Finnish tax note), dataDates, disclaimer" }, "400": { "description": "Invalid input" }, "413": { "description": "Too large" } } } } },
  "components": { "schemas": {
    "Holding": { "type": "object", "required": ["n", "w"], "properties": { "n": { "type": "string", "description": "Company name" }, "w": { "type": "number", "description": "Weight in fund, %" }, "s": { "type": "string", "description": "Sector; 'Käteinen/johdannaiset' for cash/derivatives" }, "c": { "type": "string", "description": "Country (English)" }, "cur": { "type": "string" }, "px": { "type": "number", "description": "Price in market currency (used for Helsinki dividend yield when EUR)" } } },
    "Fund": { "type": "object", "required": ["id", "holdings"], "properties": { "id": { "type": "string", "description": "Fund id/ticker/ISIN" }, "name": { "type": "string" }, "asOf": { "type": "string" }, "source": { "type": "string", "description": "URL/file the caller fetched" }, "holdings": { "type": "array", "maxItems": 20000, "items": { "$ref": "#/components/schemas/Holding" } } } },
    "Request": { "type": "object", "required": ["funds", "positions"], "properties": { "funds": { "type": "array", "maxItems": 30, "items": { "$ref": "#/components/schemas/Fund" } }, "positions": { "type": "array", "items": { "type": "object", "required": ["id", "eur"], "properties": { "id": { "type": "string", "description": "Fund id/ticker/ISIN, or direct stock name" }, "eur": { "type": "number" } } } }, "account": { "type": "string", "enum": ["aot", "ost"], "description": "aot = arvo-osuustili, ost = osakesäästötili" }, "top": { "type": "integer", "maximum": 200 } } } } } }
