{"openapi":"3.1.0","info":{"title":"RetireCrunch API","version":"0.1.0"},"paths":{"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/inflation-stats/{currency}":{"get":{"summary":"Inflation Stats","operationId":"inflation_stats_api_inflation_stats__currency__get","parameters":[{"name":"currency","in":"path","required":true,"schema":{"type":"string","title":"Currency"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Unsupported currency"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/portfolio-returns/{currency}":{"get":{"summary":"Portfolio Returns","operationId":"portfolio_returns_api_portfolio_returns__currency__get","parameters":[{"name":"currency","in":"path","required":true,"schema":{"type":"string","title":"Currency"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Unsupported currency"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/calculate":{"post":{"summary":"Calculate","operationId":"calculate_api_calculate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalculateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalculateResponse"}}}},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/coast-fire":{"post":{"summary":"Coast Fire","operationId":"coast_fire_api_coast_fire_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoastFireRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoastFireResponse"}}}},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/quote/{symbol}":{"get":{"summary":"Quote","description":"Live price + native currency for a ticker (best-effort, may 404).","operationId":"quote_api_quote__symbol__get","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","title":"Symbol"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Quote unavailable"},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/quotes":{"post":{"summary":"Quotes Post","description":"Batch quotes for a list of symbols. Missing symbols are simply omitted\nso one bad ticker never fails the whole upload.\n\nPOST rather than GET: the symbol list is the user's whole holdings roster,\nand a query string is written to access logs (RC-402). The GET form below\nis kept for existing integrations.\n\nAn optional parallel ``isins`` list disambiguates cross-listed tickers — a\nbare symbol can resolve to the wrong exchange (RC-103).","operationId":"quotes_post_api_quotes_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Quotes","description":"Deprecated: symbol lists in a query string end up in access logs. Use\n``POST /api/quotes``. Retained so older clients keep working.","operationId":"quotes_api_quotes_get","deprecated":true,"parameters":[{"name":"symbols","in":"query","required":false,"schema":{"type":"string","default":"","title":"Symbols"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/fx/{base}/{quote_ccy}":{"get":{"summary":"Fx","description":"How many units of ``quote_ccy`` one unit of ``base`` buys.","operationId":"fx_api_fx__base___quote_ccy__get","parameters":[{"name":"base","in":"path","required":true,"schema":{"type":"string","title":"Base"}},{"name":"quote_ccy","in":"path","required":true,"schema":{"type":"string","title":"Quote Ccy"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"FX rate unavailable"},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/us/detect-region":{"get":{"summary":"Detect Region","description":"Detect user's region from GCP/Cloudflare headers.","operationId":"detect_region_api_us_detect_region_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/us/states":{"get":{"summary":"List States","description":"Return list of US states with tax info.","operationId":"list_states_api_us_states_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/us/project":{"post":{"summary":"Project Retirement Route","description":"HTTP entry: rate-limited (CPU-heavy), then the pure projection.","operationId":"project_retirement_route_api_us_project_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/USRetirementInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/USProjectionResponse"}}}},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/handoff":{"post":{"summary":"Create Handoff","operationId":"create_handoff_api_handoff_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHandoffRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHandoffResponse"}}}},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/handoff/take":{"post":{"summary":"Take Handoff","operationId":"take_handoff_api_handoff_take_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TakeHandoffRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TakeHandoffResponse"}}}},"410":{"description":"Already taken, expired or never existed"},"429":{"description":"Rate limited"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ibkr/flex":{"post":{"summary":"Flex Fetch","operationId":"flex_fetch_api_ibkr_flex_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlexFetchRequest"}}},"required":true},"responses":{"200":{"description":"The Flex statement XML","content":{"application/xml":{}}},"429":{"description":"RetireCrunch's own per-IP limit (not IBKR's); detail is {source: retirecrunch, reason: rateLimited, ibkrCode: null, message, burst, intervalSeconds}"},"502":{"description":"IBKR refused the request (source ibkr: IBKR's own code and message) or the exchange failed on our side (source retirecrunch, reason unreachable/tooSlow/tooLarge/unexpected); detail is {source, reason, ibkrCode, message}"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CalculateRequest":{"properties":{"annual_expense":{"type":"number","maximum":100000000.0,"minimum":0.0,"title":"Annual Expense"},"annual_expenses":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":200},{"type":"null"}],"title":"Annual Expenses"},"currency":{"type":"string","title":"Currency","default":"USD"},"years":{"type":"integer","maximum":100.0,"exclusiveMinimum":0.0,"title":"Years"},"apply_inflation":{"type":"boolean","title":"Apply Inflation","default":false},"inflation_rate":{"type":"number","maximum":30.0,"minimum":0.0,"title":"Inflation Rate","default":3.0},"current_savings":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Current Savings","default":0},"retirement_year":{"anyOf":[{"type":"integer","maximum":2300.0,"minimum":1900.0},{"type":"null"}],"title":"Retirement Year"},"portfolio_return_rate":{"type":"number","maximum":30.0,"minimum":0.0,"title":"Portfolio Return Rate","default":0.0},"portfolio_volatility":{"type":"number","maximum":50.0,"minimum":0.0,"title":"Portfolio Volatility","default":0.0},"monte_carlo_simulations":{"type":"integer","maximum":10000.0,"minimum":100.0,"title":"Monte Carlo Simulations","default":1000}},"type":"object","required":["annual_expense","years"],"title":"CalculateRequest"},"CalculateResponse":{"properties":{"annual_expense":{"type":"number","title":"Annual Expense"},"adjusted_annual_expense":{"type":"number","title":"Adjusted Annual Expense"},"currency":{"type":"string","title":"Currency"},"years":{"type":"integer","title":"Years"},"apply_inflation":{"type":"boolean","title":"Apply Inflation"},"inflation_rate":{"type":"number","title":"Inflation Rate"},"retirement_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retirement Year"},"total_needed":{"type":"number","title":"Total Needed"},"yearly_breakdown":{"items":{"$ref":"#/components/schemas/YearBreakdown"},"type":"array","title":"Yearly Breakdown"},"current_savings":{"type":"number","title":"Current Savings"},"projected_savings":{"type":"number","title":"Projected Savings"},"portfolio_return_rate":{"type":"number","title":"Portfolio Return Rate"},"years_savings_last":{"type":"number","title":"Years Savings Last"},"delta":{"type":"number","title":"Delta"},"monte_carlo":{"anyOf":[{"$ref":"#/components/schemas/MonteCarloResult"},{"type":"null"}]}},"type":"object","required":["annual_expense","adjusted_annual_expense","currency","years","apply_inflation","inflation_rate","total_needed","yearly_breakdown","current_savings","projected_savings","portfolio_return_rate","years_savings_last","delta"],"title":"CalculateResponse"},"CoastFireRequest":{"properties":{"current_age":{"type":"integer","maximum":80.0,"minimum":18.0,"title":"Current Age"},"target_retirement_age":{"type":"integer","maximum":100.0,"minimum":30.0,"title":"Target Retirement Age"},"current_savings":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Current Savings"},"annual_expenses_in_retirement":{"type":"number","maximum":100000000.0,"exclusiveMinimum":0.0,"title":"Annual Expenses In Retirement"},"currency":{"type":"string","title":"Currency","default":"USD"},"expected_return_rate":{"type":"number","maximum":30.0,"minimum":0.0,"title":"Expected Return Rate","default":7.0},"inflation_rate":{"type":"number","maximum":30.0,"minimum":0.0,"title":"Inflation Rate","default":3.0},"safe_withdrawal_rate":{"type":"number","maximum":10.0,"minimum":1.0,"title":"Safe Withdrawal Rate","default":4.0},"monthly_savings":{"type":"number","maximum":100000000.0,"minimum":0.0,"title":"Monthly Savings","default":0},"portfolio_volatility":{"type":"number","maximum":50.0,"minimum":0.0,"title":"Portfolio Volatility","default":0.0},"monte_carlo_simulations":{"type":"integer","maximum":10000.0,"minimum":100.0,"title":"Monte Carlo Simulations","default":1000}},"type":"object","required":["current_age","target_retirement_age","current_savings","annual_expenses_in_retirement"],"title":"CoastFireRequest"},"CoastFireResponse":{"properties":{"coast_fire_number":{"type":"number","title":"Coast Fire Number"},"fire_number":{"type":"number","title":"Fire Number"},"current_savings":{"type":"number","title":"Current Savings"},"has_reached_coast_fire":{"type":"boolean","title":"Has Reached Coast Fire"},"surplus_or_deficit":{"type":"number","title":"Surplus Or Deficit"},"years_to_coast_fire":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Years To Coast Fire"},"monte_carlo":{"anyOf":[{"$ref":"#/components/schemas/MonteCarloResult"},{"type":"null"}]},"currency":{"type":"string","title":"Currency"}},"type":"object","required":["coast_fire_number","fire_number","current_savings","has_reached_coast_fire","surplus_or_deficit","currency"],"title":"CoastFireResponse"},"CreateHandoffRequest":{"properties":{"kind":{"type":"string","enum":["portfolio","plan"],"title":"Kind"},"ciphertext":{"type":"string","maxLength":349529,"minLength":24,"title":"Ciphertext"},"iv":{"type":"string","maxLength":16,"minLength":16,"title":"Iv"}},"type":"object","required":["kind","ciphertext","iv"],"title":"CreateHandoffRequest"},"CreateHandoffResponse":{"properties":{"id":{"type":"string","title":"Id"},"expiresAt":{"type":"string","title":"Expiresat"}},"type":"object","required":["id","expiresAt"],"title":"CreateHandoffResponse"},"FilingStatus":{"type":"string","enum":["single","mfj","hoh"],"title":"FilingStatus"},"FlexFetchRequest":{"properties":{"token":{"type":"string","maxLength":64,"minLength":10,"pattern":"^[0-9]+$","title":"Token"},"queryId":{"type":"string","maxLength":20,"minLength":3,"pattern":"^[0-9]+$","title":"Queryid"}},"type":"object","required":["token","queryId"],"title":"FlexFetchRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MonteCarloResult":{"properties":{"success_rate":{"type":"number","title":"Success Rate"},"simulations":{"type":"integer","title":"Simulations"},"percentile_curves":{"items":{"$ref":"#/components/schemas/MonteCarloYearStats"},"type":"array","title":"Percentile Curves"}},"type":"object","required":["success_rate","simulations","percentile_curves"],"title":"MonteCarloResult"},"MonteCarloYearStats":{"properties":{"year":{"type":"integer","title":"Year"},"p10":{"type":"number","title":"P10"},"p25":{"type":"number","title":"P25"},"p50":{"type":"number","title":"P50"},"p75":{"type":"number","title":"P75"},"p90":{"type":"number","title":"P90"}},"type":"object","required":["year","p10","p25","p50","p75","p90"],"title":"MonteCarloYearStats"},"QuotesRequest":{"properties":{"symbols":{"items":{"type":"string"},"type":"array","maxItems":100,"title":"Symbols"},"isins":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":100},{"type":"null"}],"title":"Isins"}},"type":"object","title":"QuotesRequest","description":"Body for ``POST /api/quotes``.\n\n``isins`` is optional and positionally parallel to ``symbols``; an entry\nthat is present and valid takes precedence, because a bare ticker can\nresolve to a different exchange's listing."},"TakeHandoffRequest":{"properties":{"id":{"type":"string","maxLength":64,"minLength":16,"pattern":"^[A-Za-z0-9_-]+$","title":"Id"}},"type":"object","required":["id"],"title":"TakeHandoffRequest"},"TakeHandoffResponse":{"properties":{"kind":{"type":"string","title":"Kind"},"ciphertext":{"type":"string","title":"Ciphertext"},"iv":{"type":"string","title":"Iv"}},"type":"object","required":["kind","ciphertext","iv"],"title":"TakeHandoffResponse"},"USProjectionResponse":{"properties":{"years":{"items":{"$ref":"#/components/schemas/USYearProjection"},"type":"array","title":"Years"},"summary":{"$ref":"#/components/schemas/USProjectionSummary"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","default":[]},"recommendations":{"items":{"type":"string"},"type":"array","title":"Recommendations","default":[]}},"type":"object","required":["years","summary"],"title":"USProjectionResponse","description":"Full US retirement projection response."},"USProjectionSummary":{"properties":{"ss_benefit_at_62":{"type":"number","title":"Ss Benefit At 62","default":0},"ss_benefit_at_fra":{"type":"number","title":"Ss Benefit At Fra","default":0},"ss_benefit_at_70":{"type":"number","title":"Ss Benefit At 70","default":0},"ss_breakeven_62_fra":{"type":"integer","title":"Ss Breakeven 62 Fra","default":0},"ss_breakeven_fra_70":{"type":"integer","title":"Ss Breakeven Fra 70","default":0},"fra_age":{"type":"integer","title":"Fra Age","default":67},"total_lifetime_tax":{"type":"number","title":"Total Lifetime Tax","default":0},"total_lifetime_healthcare":{"type":"number","title":"Total Lifetime Healthcare","default":0},"portfolio_depletion_age":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Portfolio Depletion Age"},"roth_conversion_window":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Roth Conversion Window"}},"type":"object","title":"USProjectionSummary"},"USRetirementInput":{"properties":{"current_age":{"type":"integer","maximum":95.0,"minimum":18.0,"title":"Current Age"},"retirement_age":{"type":"integer","maximum":95.0,"minimum":18.0,"title":"Retirement Age"},"birth_year":{"type":"integer","maximum":2010.0,"minimum":1930.0,"title":"Birth Year"},"life_expectancy":{"type":"integer","maximum":120.0,"minimum":50.0,"title":"Life Expectancy","default":90},"filing_status":{"$ref":"#/components/schemas/FilingStatus","default":"single"},"state":{"type":"string","title":"State","description":"US state abbreviation, empty = no state tax","default":""},"state_effective_tax_rate":{"type":"number","maximum":15.0,"minimum":0.0,"title":"State Effective Tax Rate","description":"Effective state tax rate %","default":0.0},"traditional_401k_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Traditional 401K Balance","default":0},"traditional_401k_contribution":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Traditional 401K Contribution","description":"Annual employee contribution","default":0},"employer_match_pct":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Employer Match Pct","description":"Employer match as % of salary","default":0},"employer_match_limit_pct":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Employer Match Limit Pct","description":"Employer matches up to this % of salary","default":6},"roth_401k_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Roth 401K Balance","default":0},"traditional_ira_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Traditional Ira Balance","default":0},"traditional_ira_contribution":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Traditional Ira Contribution","default":0},"roth_ira_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Roth Ira Balance","default":0},"roth_ira_contribution":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Roth Ira Contribution","default":0},"rollover_ira_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Rollover Ira Balance","default":0},"taxable_brokerage_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Taxable Brokerage Balance","default":0},"hsa_balance":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Hsa Balance","default":0},"cash_savings":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Cash Savings","default":0},"ss_monthly_benefit_fra":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Ss Monthly Benefit Fra","description":"Estimated monthly SS benefit at FRA","default":0},"ss_claiming_age":{"type":"integer","maximum":70.0,"minimum":62.0,"title":"Ss Claiming Age","default":67},"spouse_ss_monthly_benefit_fra":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Spouse Ss Monthly Benefit Fra","default":0},"spouse_claiming_age":{"type":"integer","maximum":70.0,"minimum":62.0,"title":"Spouse Claiming Age","default":67},"pension_monthly_benefit":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Pension Monthly Benefit","default":0},"pension_start_age":{"type":"integer","maximum":80.0,"minimum":50.0,"title":"Pension Start Age","default":65},"pre_medicare_annual_premium":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Pre Medicare Annual Premium","description":"Annual health insurance cost before 65","default":12000},"medicare_monthly_cost":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Medicare Monthly Cost","description":"Total monthly Medicare cost at 65+","default":550},"ltc_annual_premium":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Ltc Annual Premium","description":"Long-term care insurance annual premium","default":0},"annual_gross_income":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Annual Gross Income","default":0},"annual_expenses":{"type":"number","maximum":1000000000000.0,"minimum":0.0,"title":"Annual Expenses","default":0},"portfolio_return_rate":{"type":"number","maximum":30.0,"minimum":0.0,"title":"Portfolio Return Rate","default":7.0},"inflation_rate":{"type":"number","maximum":15.0,"minimum":0.0,"title":"Inflation Rate","default":3.0}},"type":"object","required":["current_age","retirement_age","birth_year"],"title":"USRetirementInput"},"USYearProjection":{"properties":{"year":{"type":"integer","title":"Year"},"age":{"type":"integer","title":"Age"},"earned_income":{"type":"number","title":"Earned Income","default":0},"ss_income":{"type":"number","title":"Ss Income","default":0},"pension_income":{"type":"number","title":"Pension Income","default":0},"traditional_withdrawal":{"type":"number","title":"Traditional Withdrawal","default":0},"roth_withdrawal":{"type":"number","title":"Roth Withdrawal","default":0},"taxable_withdrawal":{"type":"number","title":"Taxable Withdrawal","default":0},"rmd_amount":{"type":"number","title":"Rmd Amount","default":0},"total_gross_income":{"type":"number","title":"Total Gross Income","default":0},"federal_tax":{"type":"number","title":"Federal Tax","default":0},"state_tax":{"type":"number","title":"State Tax","default":0},"ss_taxable_pct":{"type":"number","title":"Ss Taxable Pct","default":0},"irmaa_surcharge":{"type":"number","title":"Irmaa Surcharge","default":0},"total_tax":{"type":"number","title":"Total Tax","default":0},"healthcare_cost":{"type":"number","title":"Healthcare Cost","default":0},"living_expenses":{"type":"number","title":"Living Expenses","default":0},"total_expenses":{"type":"number","title":"Total Expenses","default":0},"traditional_balance":{"type":"number","title":"Traditional Balance","default":0},"roth_balance":{"type":"number","title":"Roth Balance","default":0},"taxable_balance":{"type":"number","title":"Taxable Balance","default":0},"hsa_balance":{"type":"number","title":"Hsa Balance","default":0},"total_portfolio":{"type":"number","title":"Total Portfolio","default":0},"roth_conversion_opportunity":{"type":"boolean","title":"Roth Conversion Opportunity","default":false},"rmd_pushes_bracket":{"type":"boolean","title":"Rmd Pushes Bracket","default":false}},"type":"object","required":["year","age"],"title":"USYearProjection","description":"Single year of the US retirement projection."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"YearBreakdown":{"properties":{"year":{"type":"integer","title":"Year"},"expense":{"type":"number","title":"Expense"},"cumulative":{"type":"number","title":"Cumulative"}},"type":"object","required":["year","expense","cumulative"],"title":"YearBreakdown"}}}}