{
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "$id": "https://quantcalc.app/docs/federal-tax/federal-tax-api-schema.json",
 "title": "QuantCalc federal income tax API",
 "description": "POST /api/federal-tax: validate a request against #/$defs/request; a 200 body has the shape of #/$defs/response and a 400 body that of #/$defs/error. Generated from the request parser's field table. Keys are matched case-insensitively by the API; this schema lists the documented spellings. Checks that relate two fields (spouseAge with filingStatus mfj) are listed under x-errors with the exact 400 message. Reference: https://quantcalc.app/docs/federal-tax/api/",
 "engineVersion": "1.2.0",
 "taxYear": 2026,
 "$defs": {
  "request": {
   "type": "object",
   "description": "The request body: one 2026 federal return. All amounts are annual US dollars. A key that is not listed here is refused with 400: the engine does not model it, and a figure that silently left it out would look complete.",
   "properties": {
    "filingStatus": {
     "type": [
      "string",
      "null"
     ],
     "pattern": "^(?:[sS][iI][nN][gG][lL][eE]|[mM][fF][jJ]|[mM][aA][rR][rR][iI][eE][dD]_[fF][iI][lL][iI][nN][gG]_[jJ][oO][iI][nN][tT][lL][yY]|[mM][fF][sS]|[mM][aA][rR][rR][iI][eE][dD]_[fF][iI][lL][iI][nN][gG]_[sS][eE][pP][aA][rR][aA][tT][eE][lL][yY]|[hH][oO][hH]|[hH][eE][aA][dD]_[oO][fF]_[hH][oO][uU][sS][eE][hH][oO][lL][dD]|[qQ][sS][sS]|[qQ][uU][aA][lL][iI][fF][yY][iI][nN][gG]_[sS][uU][rR][vV][iI][vV][iI][nN][gG]_[sS][pP][oO][uU][sS][eE])$",
     "examples": [
      "single",
      "mfj",
      "married_filing_jointly",
      "mfs",
      "married_filing_separately",
      "hoh",
      "head_of_household",
      "qss",
      "qualifying_surviving_spouse"
     ],
     "description": "single, mfj or married_filing_jointly, mfs or married_filing_separately, hoh or head_of_household, qss or qualifying_surviving_spouse (any case). A qualifying surviving spouse (§2(a): the spouse died in 2024 or 2025, a dependent child lives with the filer, not remarried; the caller asserts it) files on the joint brackets and standard deduction with the single Social Security base amounts and senior-deduction threshold, and has no spouseAge.",
     "x-whenAbsent": "single",
     "x-relation": "The return's filing status: the brackets, the standard deduction, the thresholds.",
     "x-limits": "One of the nine strings, any case; null = absent. Anything else: 400 naming the field."
    },
    "filing_status": {
     "type": [
      "string",
      "null"
     ],
     "pattern": "^(?:[sS][iI][nN][gG][lL][eE]|[mM][fF][jJ]|[mM][aA][rR][rR][iI][eE][dD]_[fF][iI][lL][iI][nN][gG]_[jJ][oO][iI][nN][tT][lL][yY]|[mM][fF][sS]|[mM][aA][rR][rR][iI][eE][dD]_[fF][iI][lL][iI][nN][gG]_[sS][eE][pP][aA][rR][aA][tT][eE][lL][yY]|[hH][oO][hH]|[hH][eE][aA][dD]_[oO][fF]_[hH][oO][uU][sS][eE][hH][oO][lL][dD]|[qQ][sS][sS]|[qQ][uU][aA][lL][iI][fF][yY][iI][nN][gG]_[sS][uU][rR][vV][iI][vV][iI][nN][gG]_[sS][pP][oO][uU][sS][eE])$",
     "examples": [
      "single",
      "mfj",
      "married_filing_jointly",
      "mfs",
      "married_filing_separately",
      "hoh",
      "head_of_household",
      "qss",
      "qualifying_surviving_spouse"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "single",
     "x-relation": "The return's filing status: the brackets, the standard deduction, the thresholds.",
     "x-limits": "One of the nine strings, any case; null = absent. Anything else: 400 naming the field."
    },
    "age": {
     "type": "integer",
     "minimum": 0,
     "maximum": 120,
     "description": "The age the filer reaches in 2026 (the age clock: the birth year is 2026 minus age). The §72(t) additional tax applies through the year the filer reaches 59 (with birthMonth, only to the part of the year before 59½); the §63(f) aged amount and the senior deduction from the year the filer reaches 65.",
     "x-whenAbsent": "(none: 400)",
     "x-relation": "The primary filer (the owner of iraDistributions).",
     "x-limits": "Whole number 0 to 120. Absent: 400 \"age is required\"."
    },
    "spouseAge": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1,
     "maximum": 120,
     "description": "The spouse's age at the end of 2026, on a joint return: a spouse 65 or older adds the §63(f) married amount and their own senior deduction.",
     "x-whenAbsent": "(none: 400 on a joint return)",
     "x-relation": "Joint returns only.",
     "x-limits": "Whole number 1 to 120. Required when filingStatus is mfj; refused on any other status."
    },
    "spouse_age": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1,
     "maximum": 120,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "(none: 400 on a joint return)",
     "x-relation": "Joint returns only.",
     "x-limits": "Whole number 1 to 120. Required when filingStatus is mfj; refused on any other status."
    },
    "mfsLivedApart": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "true: a separate filer who lived apart from the spouse all year, so the Social Security test uses the single base amounts ($25,000 and $34,000) instead of $0 (Pub 915).",
     "x-whenAbsent": "false",
     "x-relation": "Separate returns only.",
     "x-limits": "true or false; null = absent. true on any other status: 400."
    },
    "mfs_lived_apart": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "false",
     "x-relation": "Separate returns only.",
     "x-limits": "true or false; null = absent. true on any other status: 400."
    },
    "iraDistributions": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Taxable distributions from traditional IRAs and employer plans (Form 1040 line 4b). The §72(t) additional tax applies to them by the filer's age.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once. Does not contain rothConversion.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "ira_distributions": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once. Does not contain rothConversion.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "rothConversion": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Amounts converted from a traditional account to a Roth IRA this year: ordinary income on line 4b, never charged the §72(t) additional tax.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once. Not part of iraDistributions.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "roth_conversion": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once. Not part of iraDistributions.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "pension": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Taxable pension and annuity income (Form 1040 line 5b), including Railroad Retirement Tier 2.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "otherOrdinaryIncome": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Other ordinary income that is not net investment income (Form 1040 line 8). Not interest or dividends: the engine does not model those yet, and they would change the NIIT.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "other_ordinary_income": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Component: added to income once.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "shortTermGains": {
     "type": [
      "number",
      "null"
     ],
     "minimum": -100000000000,
     "maximum": 100000000000,
     "description": "The year's net short-term capital gain, or loss as a negative number (Schedule D line 7).",
     "x-whenAbsent": "0",
     "x-relation": "Component; netted against longTermGains.",
     "x-limits": "Finite, from -$100 billion to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "short_term_gains": {
     "type": [
      "number",
      "null"
     ],
     "minimum": -100000000000,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Component; netted against longTermGains.",
     "x-limits": "Finite, from -$100 billion to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "longTermGains": {
     "type": [
      "number",
      "null"
     ],
     "minimum": -100000000000,
     "maximum": 100000000000,
     "description": "The year's net long-term capital gain, or loss as a negative number (Schedule D line 15).",
     "x-whenAbsent": "0",
     "x-relation": "Component; netted against shortTermGains.",
     "x-limits": "Finite, from -$100 billion to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "long_term_gains": {
     "type": [
      "number",
      "null"
     ],
     "minimum": -100000000000,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Component; netted against shortTermGains.",
     "x-limits": "Finite, from -$100 billion to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "socialSecurityGross": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Gross Social Security benefits received (with any Railroad Retirement Tier 1), Form 1040 line 6a. The engine computes the taxable part.",
     "x-whenAbsent": "0",
     "x-relation": "Gross benefits; the taxable part (line 6b) is computed, not sent.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "social_security_gross": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Gross benefits; the taxable part (line 6b) is computed, not sent.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "taxExemptInterest": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Tax-exempt interest (Form 1040 line 2a): not taxed, but counted in provisional income for Social Security.",
     "x-whenAbsent": "0",
     "x-relation": "Not added to AGI.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "tax_exempt_interest": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Not added to AGI.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "includeSources": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "false leaves rules.sources and rules.unsourced out of the response; the result is the same.",
     "x-whenAbsent": "true",
     "x-relation": "Not an engine input: shapes the response only.",
     "x-limits": "true or false; null = true. Anything else: 400."
    },
    "include_sources": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "true",
     "x-relation": "Not an engine input: shapes the response only.",
     "x-limits": "true or false; null = true. Anything else: 400."
    },
    "birthMonth": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1,
     "maximum": 12,
     "description": "The filer's birth month (1 to 12). With it, the §72(t) additional tax applies only to the share of the year before 59½ (the month of 59½ counts as before it), the Roth 59½ test uses the same share, and the split-interest QCD 70½ test is exact. Without it the whole-year rules apply: the additional tax through the year the filer reaches 59.",
     "x-whenAbsent": "(none: the whole-year rules)",
     "x-relation": "The age clock: age is the age reached in 2026, so the birth year is 2026 minus age.",
     "x-limits": "Whole number 1 to 12; null = absent."
    },
    "birth_month": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1,
     "maximum": 12,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "(none: the whole-year rules)",
     "x-relation": "The age clock: age is the age reached in 2026, so the birth year is 2026 minus age.",
     "x-limits": "Whole number 1 to 12; null = absent."
    },
    "blindCount": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 0,
     "maximum": 2,
     "description": "How many people on the return are blind at the end of 2026 (§63(f)(2)): the filer, and on a joint return the spouse. Each adds the §63(f) amount to the standard deduction.",
     "x-whenAbsent": "0",
     "x-relation": "Joint returns only for 2.",
     "x-limits": "Whole number 0 to 2; 2 needs filingStatus mfj (400 otherwise)."
    },
    "blind_count": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 0,
     "maximum": 2,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Joint returns only for 2.",
     "x-limits": "Whole number 0 to 2; 2 needs filingStatus mfj (400 otherwise)."
    },
    "saltIncomeOrSalesTax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "State and local income tax, or general sales tax instead (Schedule A line 5a).",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "salt_income_or_sales_tax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "saltRealEstateTax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "State and local real estate tax (Schedule A line 5b).",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "salt_real_estate_tax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "saltPersonalPropertyTax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "State and local personal property tax (Schedule A line 5c).",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "salt_personal_property_tax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "otherTaxes": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Other deductible taxes, such as foreign income tax (Schedule A line 6); not under the SALT cap.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "other_taxes": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "mortgageInterest": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Deductible home mortgage interest and points (Schedule A lines 8a to 8c), already limited to the qualified-residence debt limit.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "mortgage_interest": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "investmentInterest": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Deductible investment interest from Form 4952 (Schedule A line 9).",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "investment_interest": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "charityCash": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Cash gifts to public charities (§170(b)(1)(A) organizations), including any to donor-advised funds.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "charity_cash": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "charityCashDaf": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The part of charityCash given to a donor-advised fund or a supporting organization: deductible when itemizing, not for the non-itemizer deduction.",
     "x-whenAbsent": "0",
     "x-relation": "Part of charityCash; cannot exceed it (400).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "charity_cash_daf": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Part of charityCash; cannot exceed it (400).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "charityCapitalGainProperty": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Fair market value of long-term capital-gain property given to public charities (the 30% limit).",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "charity_capital_gain_property": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "medicalExpenses": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Unreimbursed medical and dental expenses (Schedule A line 1).",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "medical_expenses": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "otherItemized": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Other itemized deductions (Schedule A line 16), with no floor or cap.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "other_itemized": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Schedule A amount paid in 2026.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "itemizeMode": {
     "type": [
      "string",
      "null"
     ],
     "pattern": "^(?:[aA][uU][tT][oO]|[iI][tT][eE][mM][iI][zZ][eE]|[sS][tT][aA][nN][dD][aA][rR][dD])$",
     "examples": [
      "auto",
      "itemize",
      "standard"
     ],
     "description": "auto takes the larger of Schedule A (after §68) and the standard deduction plus the non-itemizer charitable deduction; itemize elects Schedule A even when smaller (Schedule A line 18); standard never itemizes.",
     "x-whenAbsent": "auto",
     "x-relation": "The §63(e) election.",
     "x-limits": "auto, itemize or standard, any case; null = absent."
    },
    "itemize_mode": {
     "type": [
      "string",
      "null"
     ],
     "pattern": "^(?:[aA][uU][tT][oO]|[iI][tT][eE][mM][iI][zZ][eE]|[sS][tT][aA][nN][dD][aA][rR][dD])$",
     "examples": [
      "auto",
      "itemize",
      "standard"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "auto",
     "x-relation": "The §63(e) election.",
     "x-limits": "auto, itemize or standard, any case; null = absent."
    },
    "mfsSpouseItemizes": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "On a separate return: the spouse itemizes, so this filer's standard deduction is zero and the return itemizes (§63(c)(6)(A)).",
     "x-whenAbsent": "false",
     "x-relation": "filingStatus mfs only (true on another status: 400).",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "mfs_spouse_itemizes": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "false",
     "x-relation": "filingStatus mfs only (true on another status: 400).",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "employerPlanDistribution": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The part of iraDistributions paid by a qualified employer plan (401(k), 403(b), governmental plan), not an IRA: the only dollars the separation-from-service exception covers.",
     "x-whenAbsent": "0",
     "x-relation": "Part of iraDistributions; cannot exceed it (400).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "employer_plan_distribution": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Part of iraDistributions; cannot exceed it (400).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "separationYearAge": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1,
     "maximum": 120,
     "description": "The age the filer reached in the year they left the employer that maintains the plan. At 55 or more (50 for a public safety employee) employerPlanDistribution is excepted from the §72(t) additional tax.",
     "x-whenAbsent": "(none: not separated)",
     "x-relation": "At most age (400 otherwise).",
     "x-limits": "Whole number 1 to 120; null = absent."
    },
    "separation_year_age": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1,
     "maximum": 120,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "(none: not separated)",
     "x-relation": "At most age (400 otherwise).",
     "x-limits": "Whole number 1 to 120; null = absent."
    },
    "publicSafetyEmployee": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "A qualified public safety employee (§72(t)(10)): the separation age is 50.",
     "x-whenAbsent": "false",
     "x-relation": "Read with separationYearAge.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "public_safety_employee": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "false",
     "x-relation": "Read with separationYearAge.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "seppDistribution": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The part of iraDistributions that is an installment of substantially equal periodic payments (§72(t)(2)(A)(iv)); its taxable part is excepted. The engine does not compute the payment schedule.",
     "x-whenAbsent": "0",
     "x-relation": "Part of iraDistributions; cannot exceed it (400).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "sepp_distribution": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Part of iraDistributions; cannot exceed it (400).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "disabled": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The filer is disabled (§72(m)(7)): no §72(t) additional tax, and a Roth distribution can be qualified before 59½.",
     "x-whenAbsent": "false",
     "x-relation": "The primary filer.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "iraBasis": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Total nondeductible basis in traditional IRAs (Form 8606 line 5: prior-year basis plus this year's nondeductible contributions).",
     "x-whenAbsent": "0",
     "x-relation": "Read with iraYearEndValue.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "ira_basis": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Read with iraYearEndValue.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "iraYearEndValue": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The value of all traditional, SEP and SIMPLE IRAs on December 31, 2026, plus outstanding rollovers (Form 8606 line 6).",
     "x-whenAbsent": "0",
     "x-relation": "Read with iraBasis.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "ira_year_end_value": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Read with iraBasis.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "rothDistribution": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Gross Roth IRA distributions in 2026.",
     "x-whenAbsent": "0",
     "x-relation": "Not part of iraDistributions.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "roth_distribution": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Not part of iraDistributions.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "rothContributions": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Regular Roth contributions still in the Roth at the start of 2026 (distributed first).",
     "x-whenAbsent": "0",
     "x-relation": "Read with rothDistribution.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "roth_contributions": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Read with rothDistribution.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "rothFirstContributionYear": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1998,
     "maximum": 2026,
     "description": "The first tax year a contribution was made to any Roth IRA for the filer (the qualified-distribution 5-year clock).",
     "x-whenAbsent": "(none: the 5-year clock is taken as not met)",
     "x-relation": "Read with rothDistribution.",
     "x-limits": "Whole number 1998 to 2026; null = absent."
    },
    "roth_first_contribution_year": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 1998,
     "maximum": 2026,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "(none: the 5-year clock is taken as not met)",
     "x-relation": "Read with rothDistribution.",
     "x-limits": "Whole number 1998 to 2026; null = absent."
    },
    "rothConversions": {
     "type": [
      "array",
      "null"
     ],
     "maxItems": 16,
     "items": {
      "type": "object",
      "properties": {
       "year": {
        "type": "integer",
        "minimum": 1998,
        "maximum": 2026
       },
       "taxable": {
        "type": "number",
        "minimum": 0,
        "maximum": 100000000000
       },
       "nontaxable": {
        "type": "number",
        "minimum": 0,
        "maximum": 100000000000
       }
      },
      "required": [
       "year",
       "taxable"
      ],
      "additionalProperties": false
     },
     "description": "The conversions still in the Roth at the start of 2026: [{year, taxable, nontaxable}], any order. They come out oldest first, each one's taxable part first; a taxable part taken within 5 years of its conversion carries the §72(t) additional tax under 59½.",
     "x-whenAbsent": "[] (none)",
     "x-relation": "Read with rothDistribution.",
     "x-limits": "At most 16 objects: year a whole number 1998 to 2026, taxable and nontaxable dollars 0 to $100 billion (nontaxable may be left out); no other key. Otherwise 400."
    },
    "roth_conversions": {
     "type": [
      "array",
      "null"
     ],
     "maxItems": 16,
     "items": {
      "type": "object",
      "properties": {
       "year": {
        "type": "integer",
        "minimum": 1998,
        "maximum": 2026
       },
       "taxable": {
        "type": "number",
        "minimum": 0,
        "maximum": 100000000000
       },
       "nontaxable": {
        "type": "number",
        "minimum": 0,
        "maximum": 100000000000
       }
      },
      "required": [
       "year",
       "taxable"
      ],
      "additionalProperties": false
     },
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "[] (none)",
     "x-relation": "Read with rothDistribution.",
     "x-limits": "At most 16 objects: year a whole number 1998 to 2026, taxable and nontaxable dollars 0 to $100 billion (nontaxable may be left out); no other key. Otherwise 400."
    },
    "iraBalancePriorYearEnd": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The traditional IRA balance on December 31, 2025: with it the response carries the 2026 required minimum distribution (schedules.rmd).",
     "x-whenAbsent": "0",
     "x-relation": "The account owner is the filer (age, birth year 2026 minus age).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "ira_balance_prior_year_end": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "The account owner is the filer (age, birth year 2026 minus age).",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "spouseSoleBeneficiary": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The spouse is the sole beneficiary all year: when more than 10 years younger, the RMD uses the Joint and Last Survivor Table.",
     "x-whenAbsent": "false",
     "x-relation": "Needs iraBalancePriorYearEnd; the spouse's age is spouseAge on a joint return, else beneficiarySpouseAge. Refused for a qualifying surviving spouse.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "spouse_sole_beneficiary": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "false",
     "x-relation": "Needs iraBalancePriorYearEnd; the spouse's age is spouseAge on a joint return, else beneficiarySpouseAge. Refused for a qualifying surviving spouse.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "beneficiarySpouseAge": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 0,
     "maximum": 120,
     "description": "The spouse's age reached in 2026 when the spouse is not on the return (a separate return).",
     "x-whenAbsent": "(none)",
     "x-relation": "Needs spouseSoleBeneficiary true; refused on a joint return (spouseAge is used).",
     "x-limits": "Whole number 0 to 120; null = absent."
    },
    "beneficiary_spouse_age": {
     "type": [
      "integer",
      "null"
     ],
     "minimum": 0,
     "maximum": 120,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "(none)",
     "x-relation": "Needs spouseSoleBeneficiary true; refused on a joint return (spouseAge is used).",
     "x-limits": "Whole number 0 to 120; null = absent."
    },
    "rmdShortfall": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The part of a required minimum distribution not taken: the §4974 excise, 25%.",
     "x-whenAbsent": "0",
     "x-relation": "Form 5329 Part IX.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "rmd_shortfall": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Form 5329 Part IX.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "rmdShortfallCorrected": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The shortfall was distributed within the correction window: the excise is 10%.",
     "x-whenAbsent": "false",
     "x-relation": "Read with rmdShortfall.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "rmd_shortfall_corrected": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "false",
     "x-relation": "Read with rmdShortfall.",
     "x-limits": "true or false; null = absent (false). Anything else: 400."
    },
    "priorYearTax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The tax on the 2025 return (Form 2210 line 8). With it the response carries Form 2210 (schedules.form2210) on this return's tax.",
     "x-whenAbsent": "0",
     "x-relation": "Turns on Form 2210.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "prior_year_tax": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Turns on Form 2210.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "priorYearAgi": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The 2025 AGI: above $150,000 ($75,000 on a separate return) the prior-year safe harbor is 110%.",
     "x-whenAbsent": "0",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "prior_year_agi": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "0",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "priorYearFullYearReturn": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "false when 2025 was not a full 12-month year with a return filed: the prior-year safe harbor and the no-liability rule do not apply.",
     "x-whenAbsent": "true",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "true or false; null = absent (true). Anything else: 400."
    },
    "prior_year_full_year_return": {
     "type": [
      "boolean",
      "null"
     ],
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "true",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "true or false; null = absent (true). Anything else: 400."
    },
    "withholding": {
     "type": [
      "number",
      "null"
     ],
     "minimum": 0,
     "maximum": 100000000000,
     "description": "Income tax withheld in 2026: counted as paid in four equal parts on the due dates.",
     "x-whenAbsent": "0",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Finite, from 0 to $100 billion; null = absent. Otherwise 400 naming the field."
    },
    "estimatedPayments": {
     "type": [
      "array",
      "null"
     ],
     "maxItems": 4,
     "items": {
      "type": "number",
      "minimum": 0,
      "maximum": 100000000000
     },
     "description": "The four 2026 estimated tax payments, in installment order.",
     "x-whenAbsent": "[0, 0, 0, 0]",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Up to 4 amounts, dollars 0 to $100 billion. Otherwise 400."
    },
    "estimated_payments": {
     "type": [
      "array",
      "null"
     ],
     "maxItems": 4,
     "items": {
      "type": "number",
      "minimum": 0,
      "maximum": 100000000000
     },
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "[0, 0, 0, 0]",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Up to 4 amounts, dollars 0 to $100 billion. Otherwise 400."
    },
    "estimatedPaymentDates": {
     "type": [
      "array",
      "null"
     ],
     "maxItems": 4,
     "items": {
      "type": [
       "string",
       "null"
      ],
      "pattern": "^202[678]-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$"
     },
     "description": "The date each estimated payment was made; null for one paid on its due date. Accrual stops at the earlier of the payment date and April 15, 2027.",
     "x-whenAbsent": "each installment's due date",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Up to 4 dates YYYY-MM-DD from 2026-01-01 to 2028-12-31, or null. Otherwise 400."
    },
    "estimated_payment_dates": {
     "type": [
      "array",
      "null"
     ],
     "maxItems": 4,
     "items": {
      "type": [
       "string",
       "null"
      ],
      "pattern": "^202[678]-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$"
     },
     "description": "The same field under its snake_case spelling.",
     "x-whenAbsent": "each installment's due date",
     "x-relation": "Needs priorYearTax.",
     "x-limits": "Up to 4 dates YYYY-MM-DD from 2026-01-01 to 2028-12-31, or null. Otherwise 400."
    }
   },
   "required": [
    "age"
   ],
   "additionalProperties": false,
   "x-errors": [
    {
     "message": "Invalid JSON body",
     "when": "The body is not JSON (or is empty)."
    },
    {
     "message": "The request body must be a JSON object",
     "when": "The body is JSON but not an object."
    },
    {
     "message": "{1} is not a field of the federal tax API: the engine models only the fields listed at https://quantcalc.app/docs/federal-tax/api/ (income it does not model must not be sent as if it were counted)",
     "when": "A key that is not a request field. {1} = the key, as sent."
    },
    {
     "message": "{1} is given more than once (as two spellings or two cases of the key)",
     "when": "Two keys name the same field (camelCase and snake_case, or two cases)."
    },
    {
     "message": "{1} must be a string, one of: {2}",
     "when": "filingStatus is not a string."
    },
    {
     "message": "{1} \"{2}\" is not recognised — use one of: {3}",
     "when": "filingStatus is not one of the accepted values."
    },
    {
     "message": "{1} must be a number (annual dollars)",
     "when": "An amount is not a number."
    },
    {
     "message": "{1} must be a whole number between {2} and {3}",
     "when": "age or spouseAge is not a whole number in range."
    },
    {
     "message": "{1} must be true or false",
     "when": "mfsLivedApart or includeSources is not a boolean."
    },
    {
     "message": "{1} is required ({2})",
     "when": "A required field is absent or null. Only age is required: {2} says why (the filer's age at the end of the year decides the §72(t) additional tax, the §63(f) aged amount and the senior deduction)."
    },
    {
     "message": "{1} must be a finite number",
     "when": "An amount is not finite (a number too large for a double)."
    },
    {
     "message": "{1} cannot be negative",
     "when": "An amount other than the gains is below 0."
    },
    {
     "message": "{1} is below the engine's range (-$100 billion)",
     "when": "A gain is below -$100 billion."
    },
    {
     "message": "{1} is larger than the engine accepts ($100 billion)",
     "when": "An amount is above $100 billion."
    },
    {
     "message": "spouseAge applies only to filingStatus mfj (the spouse's §63(f) aged amount and senior deduction are claimed on a joint return)",
     "when": "spouseAge on a status other than mfj."
    },
    {
     "message": "spouseAge is required when filingStatus is mfj (the spouse's age at the end of the year decides their §63(f) aged amount and senior deduction)",
     "when": "A joint return without spouseAge."
    },
    {
     "message": "mfsLivedApart applies only to filingStatus mfs (Pub 915: a separate filer who lived apart from their spouse all year)",
     "when": "mfsLivedApart: true on a status other than mfs."
    },
    {
     "message": "{1} must be an array of at most {2} objects {year, taxable, nontaxable}: year a whole number {3} to {4}, the amounts dollars 0 or more (nontaxable may be left out)",
     "when": "rothConversions is not a list of conversions."
    },
    {
     "message": "{1} must be an array of up to 4 amounts (dollars, 0 or more), one per installment",
     "when": "estimatedPayments is not a list of up to 4 amounts."
    },
    {
     "message": "{1} must be an array of up to 4 dates \"YYYY-MM-DD\" from 2026-01-01 to 2028-12-31 (null = paid on the installment's due date)",
     "when": "estimatedPaymentDates holds something that is not such a date."
    },
    {
     "message": "blindCount 2 needs filingStatus mfj (a spouse's §63(f) amount for blindness is claimed on a joint return)",
     "when": "blindCount 2 on another status."
    },
    {
     "message": "mfsSpouseItemizes applies only to filingStatus mfs (§63(c)(6)(A): a separate filer whose spouse itemizes has no standard deduction)",
     "when": "mfsSpouseItemizes true on another status."
    },
    {
     "message": "{1} is part of iraDistributions and cannot exceed it",
     "when": "employerPlanDistribution or seppDistribution above iraDistributions."
    },
    {
     "message": "charityCashDaf is part of charityCash and cannot exceed it",
     "when": "charityCashDaf above charityCash."
    },
    {
     "message": "separationYearAge cannot exceed age (it is the age reached in the year the filer left the employer)",
     "when": "separationYearAge above age."
    },
    {
     "message": "beneficiarySpouseAge needs spouseSoleBeneficiary true (it only picks the RMD table)",
     "when": "beneficiarySpouseAge without spouseSoleBeneficiary."
    },
    {
     "message": "spouseSoleBeneficiary needs iraBalancePriorYearEnd (it picks the table the RMD is figured with)",
     "when": "spouseSoleBeneficiary without a balance."
    },
    {
     "message": "spouseSoleBeneficiary cannot apply to a qualifying surviving spouse (there is no spouse)",
     "when": "spouseSoleBeneficiary with filingStatus qss."
    },
    {
     "message": "beneficiarySpouseAge is for a spouse who is not on the return: on a joint return the RMD reads spouseAge",
     "when": "beneficiarySpouseAge on a joint return."
    },
    {
     "message": "spouseSoleBeneficiary needs beneficiarySpouseAge (the spouse's age reached in 2026) unless filingStatus is mfj",
     "when": "spouseSoleBeneficiary on a non-joint return without beneficiarySpouseAge."
    },
    {
     "message": "{1} needs priorYearTax (Form 2210 runs only with last year's tax)",
     "when": "A Form 2210 field without priorYearTax."
    }
   ]
  },
  "response": {
   "type": "object",
   "properties": {
    "engineVersion": {
     "type": "string",
     "description": "The federal engine version (FEDERAL_TAX_ENGINE_VERSION)."
    },
    "taxYear": {
     "type": "integer",
     "description": "2026."
    },
    "filingStatus": {
     "type": "string",
     "description": "single, mfj, mfs, hoh or qss: the status the return was computed on."
    },
    "inputs": {
     "type": "object",
     "description": "Every field that was sent, under its camelCase name.",
     "properties": {}
    },
    "result": {
     "type": "object",
     "description": "The year's return.",
     "properties": {
      "shortTermGain": {
       "type": "number",
       "description": "Short-term gain after netting, at least 0 (taxed as ordinary income)."
      },
      "longTermGain": {
       "type": "number",
       "description": "Long-term gain after netting, at least 0."
      },
      "socialSecurityTaxable": {
       "type": "number",
       "description": "The taxable part of the benefits (line 6b)."
      },
      "grossOrdinaryIncome": {
       "type": "number",
       "description": "Ordinary income: IRA distributions, conversions, pension, other income, taxable Social Security and the short-term gain."
      },
      "agi": {
       "type": "number",
       "description": "Adjusted gross income (line 11a); also the NIIT's and the senior deduction's MAGI."
      },
      "magiIrmaa": {
       "type": "number",
       "description": "AGI plus tax-exempt interest: the income the engine's Medicare IRMAA tiers read."
      },
      "standardDeduction": {
       "type": "number",
       "description": "The standard deduction with the §63(f) aged amounts (line 12e)."
      },
      "seniorDeduction": {
       "type": "number",
       "description": "The senior deduction after its phase-out (line 13b)."
      },
      "taxableOrdinaryIncome": {
       "type": "number",
       "description": "The ordinary part of taxable income."
      },
      "unusedDeduction": {
       "type": "number",
       "description": "Deductions left after ordinary income, which reduce the long-term gain in the worksheet."
      },
      "taxableLongTermGain": {
       "type": "number",
       "description": "The long-term gain in taxable income (the worksheet's base)."
      },
      "ordinaryTax": {
       "type": "number",
       "description": "Bracket tax on the ordinary part."
      },
      "capitalGainsTax": {
       "type": "number",
       "description": "Worksheet tax on the long-term gain plus the NIIT."
      },
      "niit": {
       "type": "number",
       "description": "The net investment income tax (Schedule 2 line 12)."
      },
      "incomeTax": {
       "type": "number",
       "description": "ordinaryTax + capitalGainsTax: income tax with the NIIT, without the §72(t) additional tax."
      },
      "incomeTaxExcludingNiit": {
       "type": "number",
       "description": "incomeTax less the NIIT: line 16 (and, with no credits modelled, line 22)."
      },
      "earlyWithdrawalTax": {
       "type": "number",
       "description": "The §72(t) additional tax (Schedule 2 line 8)."
      },
      "totalTax": {
       "type": "number",
       "description": "incomeTax + earlyWithdrawalTax: line 24. With extended fields it also carries the missed-RMD excise (Form 5329 line 55)."
      }
     }
    },
    "lines": {
     "type": "array",
     "description": "One entry per Form 1040 or schedule line the composition fills, in form order.",
     "items": {
      "type": "object",
      "properties": {
       "line": {
        "type": "string",
        "description": "The line id: 1040.<n>, 1040sd.<n> (Schedule D), 1040s1a.<n> (Schedule 1-A), 1040s2.<n> (Schedule 2); TY2025 form numbering."
       },
       "form": {
        "type": "string",
        "description": "The form or schedule."
       },
       "lineNumber": {
        "type": "string",
        "description": "The line number on it."
       },
       "label": {
        "type": "string",
        "description": "The line's name."
       },
       "rule": {
        "type": "string",
        "description": "The calculation step that produced the value (a section of the calculation-order page)."
       },
       "value": {
        "type": "number",
        "description": "The amount."
       },
       "docs": {
        "type": "string",
        "description": "The step's documentation."
       }
      }
     }
    },
    "rules": {
     "type": "object",
     "description": "What the figure rests on.",
     "properties": {
      "docs": {
       "type": "string",
       "description": "The engine documentation."
      },
      "sources": {
       "type": "object",
       "description": "Per calculation step on the return: its official sources (absent with includeSources: false).",
       "additionalProperties": {
        "type": "array",
        "items": {
         "type": "object",
         "properties": {
          "rule": {
           "type": "string",
           "description": "The provenance record (research/data/federal-tax-provenance.json)."
          },
          "url": {
           "type": "string",
           "description": "The source."
          },
          "title": {
           "type": "string",
           "description": "Its title."
          },
          "publisher": {
           "type": "string",
           "description": "Its publisher."
          },
          "kind": {
           "type": "string",
           "description": "statute, guidance, instructions, agency_page, ..."
          },
          "official": {
           "type": "boolean",
           "description": "Published by the body that sets the rule, or the text of the law."
          },
          "quote": {
           "type": "string",
           "description": "The first passage checked on the source."
          },
          "checked": {
           "type": "string",
           "description": "The date the quote was last found on the source."
          }
         }
        }
       }
      },
      "unsourced": {
       "type": "array",
       "description": "Steps on the return with no official source, with the reason (absent with includeSources: false).",
       "items": {
        "type": "object",
        "properties": {
         "rule": {
          "type": "string",
          "description": "The step."
         },
         "reason": {
          "type": "string",
          "description": "Why."
         }
        }
       }
      },
      "notModeled": {
       "type": "array",
       "description": "What the engine does not compute.",
       "items": {
        "type": "string"
       }
      }
     }
    },
    "schedules": {
     "type": "object",
     "description": "On a request with any extended field (or filingStatus qss): the forms behind the return.",
     "properties": {
      "scheduleA": {
       "type": "object",
       "description": "Schedule A, the §68 limitation, the standard deduction and the non-itemizer charitable deduction.",
       "properties": {
        "itemizes": {
         "type": "boolean",
         "description": "true when line 12e carries Schedule A."
        },
        "deduction": {
         "type": "number",
         "description": "Form 1040 line 12e as filed (equals result.standardDeduction)."
        },
        "standardDeduction": {
         "type": "number",
         "description": "The standard deduction available, with the §63(f) aged and blind amounts (0 under §63(c)(6)(A))."
        },
        "blindAddition": {
         "type": "number",
         "description": "The §63(f)(2) amount for blindness included in it."
        },
        "itemizedBeforeSection68": {
         "type": "number",
         "description": "Schedule A lines 4 to 16 before §68."
        },
        "section68Reduction": {
         "type": "number",
         "description": "The 2/37 limitation of §68."
        },
        "itemized": {
         "type": "number",
         "description": "Schedule A line 17 after §68: the figure an itemized-conformity state reads."
        },
        "medicalDeducted": {
         "type": "number",
         "description": "Line 4."
        },
        "saltPaid": {
         "type": "number",
         "description": "Line 5d."
        },
        "saltCap": {
         "type": "number",
         "description": "The SALT cap after the phase-down (half on a separate return)."
        },
        "saltDeducted": {
         "type": "number",
         "description": "Line 5e."
        },
        "interestDeducted": {
         "type": "number",
         "description": "Line 10."
        },
        "charityFloor": {
         "type": "number",
         "description": "0.5% of AGI (2026)."
        },
        "charityDeducted": {
         "type": "number",
         "description": "Line 14 after the percentage limits and the floor."
        },
        "nonitemizerCharity": {
         "type": "number",
         "description": "The §170(p) deduction (0 when itemizing)."
        }
       }
      },
      "form8606": {
       "type": "object",
       "description": "IRA basis and Roth distributions.",
       "properties": {
        "basisRatio": {
         "type": "number",
         "description": "Line 10 (0 without basis)."
        },
        "nontaxableConversion": {
         "type": "number",
         "description": "Line 11."
        },
        "nontaxableTotal": {
         "type": "number",
         "description": "Line 13."
        },
        "basisRemaining": {
         "type": "number",
         "description": "Line 14."
        },
        "rothQualified": {
         "type": "boolean",
         "description": "true when the Roth distribution is qualified."
        },
        "rothTaxableEarnings": {
         "type": "number",
         "description": "Line 25c: taxable Roth earnings."
        },
        "rothConversionsWithinFiveYears": {
         "type": "number",
         "description": "Converted amounts taken within 5 years of their conversion (subject to the additional tax, not taxable)."
        },
        "rothContributionsRemaining": {
         "type": "number",
         "description": "Regular contributions left in the Roth."
        }
       }
      },
      "form5329": {
       "type": "object",
       "description": "The additional taxes on retirement accounts.",
       "properties": {
        "earlyDistributions": {
         "type": "number",
         "description": "Line 1."
        },
        "exceptions": {
         "type": "number",
         "description": "Line 2."
        },
        "missedRmdExcise": {
         "type": "number",
         "description": "Line 55: the §4974 excise (in result.totalTax)."
        }
       }
      },
      "rmd": {
       "type": "object",
       "description": "With iraBalancePriorYearEnd: the 2026 required minimum distribution.",
       "properties": {
        "startAge": {
         "type": "integer",
         "description": "The SECURE 2.0 applicable age for the birth year."
        },
        "divisor": {
         "type": "number",
         "description": "The divisor (0 before the start age)."
        },
        "jointLifeTable": {
         "type": "boolean",
         "description": "true when the Joint and Last Survivor Table applies."
        },
        "required": {
         "type": "number",
         "description": "The required minimum distribution."
        }
       }
      },
      "form2210": {
       "type": "object",
       "description": "With priorYearTax: Form 2210 (regular method) on this return's tax.",
       "properties": {
        "tax": {
         "type": "number",
         "description": "The tax Form 2210 uses: income tax plus the additional tax on distributions."
        },
        "requiredAnnualPayment": {
         "type": "number",
         "description": "Line 9."
        },
        "requiredInstallment": {
         "type": "number",
         "description": "Line 10, each installment."
        },
        "priorYearSafeHarbor": {
         "type": "boolean",
         "description": "true when the prior-year harbor sets the requirement."
        },
        "underThousandDollars": {
         "type": "boolean",
         "description": "true when the tax less withholding is under the §6654(e)(1) threshold: no penalty."
        },
        "noPriorYearLiability": {
         "type": "boolean",
         "description": "true when last year's full-year return showed no tax: no penalty."
        },
        "underpayment": {
         "type": "array",
         "description": "Line 17 per installment.",
         "items": {
          "type": "number"
         }
        },
        "penaltyByInstallment": {
         "type": "array",
         "description": "The penalty attributable to each installment.",
         "items": {
          "type": "number"
         }
        },
        "totalUnderpayment": {
         "type": "number",
         "description": "The sum of line 17."
        },
        "penalty": {
         "type": "number",
         "description": "Line 19."
        },
        "usesUnannouncedRate": {
         "type": "boolean",
         "description": "true when some accrual falls in a quarter whose rate is carried forward, not announced."
        }
       }
      }
     }
    }
   }
  },
  "error": {
   "type": "object",
   "properties": {
    "error": {
     "type": "string",
     "description": "One of the messages under #/$defs/request/x-errors, with the parts taken from the request filled in."
    }
   },
   "required": [
    "error"
   ]
  }
 }
}
