{"openapi":"3.1.0","info":{"title":"Portfolio Optimizer Pro agent API","version":"1.0.0","description":"Free, read-only portfolio checkup tools for AI assistants and developers. No authentication. Holdings are processed to compute the result and are not stored. Results are derived (grades, scores, fees, findings), never raw prices. Educational and hypothetical only; not advice or a forecast. Rate limits: 60 calls a minute and 2,000 a day per network, 30 a minute per session id when one is sent. An overall daily limit also applies; when it is reached the tools reply \"temporarily busy\" until the next UTC day. The same tools are available over MCP at https://portfoliooptimizerpro.com/mcp.","contact":{"email":"portfoliooptimizerpro@gmail.com","url":"https://portfoliooptimizerpro.com/ai"}},"servers":[{"url":"https://portfoliooptimizerpro.com/api/public/agent"}],"externalDocs":{"url":"https://portfoliooptimizerpro.com/methodology","description":"Grading methodology"},"paths":{"/grade_portfolio":{"post":{"operationId":"grade_portfolio","summary":"Grade a portfolio","description":"A+ to F structural grade, score, ceiling applied, factor breakdown, top findings, data dates, disclaimer and full_breakdown_url (opens the same graded checkup on the website).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"holdings":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string","minLength":1,"maxLength":11,"pattern":"^[A-Za-z0-9]{1,6}(?:[.\\-][A-Za-z0-9]{1,4})?$","description":"Fund or company ticker symbol as listed on a US exchange, e.g. \"VTI\"."},"weight":{"type":"number","exclusiveMinimum":0,"maximum":100,"description":"Share of the portfolio. Percent (60 = 60%) or fraction (0.6); weights are normalized to total 100%."}},"required":["ticker","weight"],"additionalProperties":false},"minItems":1,"maxItems":30,"description":"The portfolio: 1 to 30 holdings, each ticker once, with its weight."}},"required":["holdings"],"additionalProperties":false},"example":{"holdings":[{"ticker":"VTI","weight":60},{"ticker":"VXUS","weight":30},{"ticker":"BND","weight":10}]}}}},"responses":{"200":{"description":"Derived result.","content":{"application/json":{"schema":{"type":"object","properties":{"grade":{"type":"string","description":"Letter grade A+ to F, or \"Not graded\"."},"score":{"type":["number","null"],"description":"0–100 structural score."},"risk_profile":{"type":"string"},"cap_applied":{"anyOf":[{"type":"object","properties":{"ceiling_score":{"type":"number"},"ceiling_grade":{"type":"string"},"label":{"type":"string"},"reason":{"type":"string"},"binding":{"type":"boolean","description":"True when the score would have been higher without this ceiling."},"score_before_ceiling":{"type":["number","null"]}},"required":["ceiling_score","ceiling_grade","label","reason","binding","score_before_ceiling"],"additionalProperties":false},{"type":"null"}],"description":"Lowest structural ceiling that applies, or null."},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"measures":{"type":"string"},"sub_score":{"type":["number","null"]},"status":{"type":"string","enum":["strong","fair","weak","unmeasured"]},"a_range_min":{"type":"number"},"measured_fact":{"type":"string"},"not_measured_reason":{"type":["string","null"]}},"required":["key","name","measures","sub_score","status","a_range_min","measured_fact","not_measured_reason"],"additionalProperties":false},"description":"Each graded factor, worst first."},"top_findings":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"points_lost":{"type":"number"},"finding":{"type":"string"},"factor":{"type":["string","null"]},"higher_scoring_portfolios":{"type":"string"}},"required":["label","points_lost","finding","factor","higher_scoring_portfolios"],"additionalProperties":false},"description":"Top 1–3 things that held the grade down."},"holdings_graded":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string"},"weight_pct":{"type":"number"}},"required":["ticker","weight_pct"],"additionalProperties":false}},"unknown_tickers":{"type":"array","items":{"type":"string"},"description":"Tickers with no usable price history; they were left out and the grade is capped as partial."},"notices":{"type":"array","items":{"type":"string"}},"data":{"type":"object","properties":{"source":{"type":"string"},"history_start":{"type":["string","null"]},"history_end":{"type":["string","null"]},"months":{"type":"number"},"data_as_of":{"type":["string","null"]}},"required":["source","history_start","history_end","months","data_as_of"],"additionalProperties":false},"methodology_url":{"type":"string"},"full_breakdown_url":{"type":"string","description":"Opens the free checkup already graded for these holdings, with the full explanation."},"disclaimer":{"type":"string"}},"required":["grade","score","risk_profile","cap_applied","factors","top_findings","holdings_graded","unknown_tickers","notices","data","methodology_url","full_breakdown_url","disclaimer"],"additionalProperties":false}}}},"400":{"description":"Invalid input (unknown keys, bad tickers or weights, duplicates, or no usable history). The message names the problem.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit reached.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporarily unavailable.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/fund_fee_cost":{"post":{"operationId":"fund_fee_cost","summary":"Fund fee cost","description":"Weighted expense ratio and 10/30-year fee cost on a flat $100,000 balance, same formula as the site calculator.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"holdings":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string","minLength":1,"maxLength":11,"pattern":"^[A-Za-z0-9]{1,6}(?:[.\\-][A-Za-z0-9]{1,4})?$","description":"Fund or company ticker symbol as listed on a US exchange, e.g. \"VTI\"."},"weight":{"type":"number","exclusiveMinimum":0,"maximum":100,"description":"Share of the portfolio. Percent (60 = 60%) or fraction (0.6); weights are normalized to total 100%."}},"required":["ticker","weight"],"additionalProperties":false},"minItems":1,"maxItems":30,"description":"The portfolio: 1 to 30 holdings, each ticker once, with its weight."}},"required":["holdings"],"additionalProperties":false},"example":{"holdings":[{"ticker":"VTI","weight":60},{"ticker":"VXUS","weight":30},{"ticker":"BND","weight":10}]}}}},"responses":{"200":{"description":"Derived result.","content":{"application/json":{"schema":{"type":"object","properties":{"holdings":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string"},"weight_pct":{"type":"number"},"kind":{"type":"string"},"fund_name":{"type":["string","null"]},"expense_ratio_pct":{"type":["number","null"],"description":"Annual expense ratio in percent; 0 for a single company; null when not verified."},"source_url":{"type":["string","null"]},"as_of":{"type":["string","null"]}},"required":["ticker","weight_pct","kind","fund_name","expense_ratio_pct","source_url","as_of"],"additionalProperties":false}},"weighted_expense_ratio_pct":{"type":["number","null"],"description":"Null when any fund fee is not verified."},"fee_cost_10y_on_100k_usd":{"type":["number","null"]},"fee_cost_30y_on_100k_usd":{"type":["number","null"]},"formula":{"type":"string"},"unverified_tickers":{"type":"array","items":{"type":"string"}},"unknown_tickers":{"type":"array","items":{"type":"string"}},"notices":{"type":"array","items":{"type":"string"}},"disclaimer":{"type":"string"}},"required":["holdings","weighted_expense_ratio_pct","fee_cost_10y_on_100k_usd","fee_cost_30y_on_100k_usd","formula","unverified_tickers","unknown_tickers","notices","disclaimer"],"additionalProperties":false}}}},"400":{"description":"Invalid input (unknown keys, bad tickers or weights, duplicates, or no usable history). The message names the problem.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit reached.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporarily unavailable.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/check_overlap":{"post":{"operationId":"check_overlap","summary":"Check fund overlap","description":"Known index overlap and related fund mandates (category-based, not measured shared holdings).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"holdings":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string","minLength":1,"maxLength":11,"pattern":"^[A-Za-z0-9]{1,6}(?:[.\\-][A-Za-z0-9]{1,4})?$","description":"Fund or company ticker symbol as listed on a US exchange, e.g. \"VTI\"."},"weight":{"type":"number","exclusiveMinimum":0,"maximum":100,"description":"Share of the portfolio. Percent (60 = 60%) or fraction (0.6); weights are normalized to total 100%."}},"required":["ticker","weight"],"additionalProperties":false},"minItems":1,"maxItems":30,"description":"The portfolio: 1 to 30 holdings, each ticker once, with its weight."}},"required":["holdings"],"additionalProperties":false},"example":{"holdings":[{"ticker":"VTI","weight":60},{"ticker":"VXUS","weight":30},{"ticker":"BND","weight":10}]}}}},"responses":{"200":{"description":"Derived result.","content":{"application/json":{"schema":{"type":"object","properties":{"mandates":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string"},"weight_pct":{"type":"number"},"kind":{"type":"string"},"fund_name":{"type":["string","null"]},"asset_class":{"type":["string","null"]},"region":{"type":["string","null"]},"structure":{"type":["string","null"]},"source_url":{"type":["string","null"]},"as_of":{"type":["string","null"]}},"required":["ticker","weight_pct","kind","fund_name","asset_class","region","structure","source_url","as_of"],"additionalProperties":false}},"known_index_overlap":{"type":"array","items":{"type":"string"},"description":"Fund-overlap findings exactly as the grade states them; any one caps the grade."},"related_categories":{"type":"array","items":{"type":"object","properties":{"funds":{"type":"array","items":{"type":"string"}},"label":{"type":"string"}},"required":["funds","label"],"additionalProperties":false}},"method_note":{"type":"string"},"unknown_tickers":{"type":"array","items":{"type":"string"}},"notices":{"type":"array","items":{"type":"string"}},"disclaimer":{"type":"string"}},"required":["mandates","known_index_overlap","related_categories","method_note","unknown_tickers","notices","disclaimer"],"additionalProperties":false}}}},"400":{"description":"Invalid input (unknown keys, bad tickers or weights, duplicates, or no usable history). The message names the problem.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit reached.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporarily unavailable.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/explain_grading":{"get":{"operationId":"explain_grading","summary":"Explain the grading method","description":"Factors, scoring rules, caps, thresholds, A-range criteria, letter bands, data source and pricing.","responses":{"200":{"description":"Methodology.","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"string"},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"measures":{"type":"string"},"scoring_rule":{"type":"string"},"a_range_min":{"type":"number"}},"required":["key","name","measures","scoring_rule","a_range_min"],"additionalProperties":false}},"combining_rule":{"type":"string"},"caps":{"type":"array","items":{"type":"object","properties":{"rule":{"type":"string"},"ceiling":{"type":"string"}},"required":["rule","ceiling"],"additionalProperties":false}},"a_range_criteria":{"type":"array","items":{"type":"string"}},"grade_bands":{"type":"array","items":{"type":"object","properties":{"letter":{"type":"string"},"min":{"type":"number"},"max":{"type":"number"}},"required":["letter","min","max"],"additionalProperties":false}},"risk_reference_bands":{"type":"array","items":{"type":"object","properties":{"risk_profile":{"type":"string"},"volatility_pct":{"type":"number"},"worst_drop_pct":{"type":"number"}},"required":["risk_profile","volatility_pct","worst_drop_pct"],"additionalProperties":false}},"data_source":{"type":"string"},"limitations":{"type":"array","items":{"type":"string"}},"pricing":{"type":"string"},"methodology_url":{"type":"string"},"disclaimer":{"type":"string"}},"required":["summary","factors","combining_rule","caps","a_range_criteria","grade_bands","risk_reference_bands","data_source","limitations","pricing","methodology_url","disclaimer"],"additionalProperties":false}}}},"429":{"description":"Rate limit reached.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}}}}