---
title: "Run a model"
method: POST
path: "/api/v1/models/{model}"
tags: ["models"]
---

# Run a model

`POST /api/v1/models/{model}`

## Request

- Base URL: `https://worthune.com`
- URL: `https://worthune.com/api/v1/models/{model}`
- Auth: one of:
  - none
  - HTTP bearer
  - API key in header `X-Api-Key`

Validates the inputs against the contract (unknown keys, missing inputs and out-of-domain values are rejected — never clamped) and runs the verified engine. Keyless for emergency-fund, relocation, side-business; every other model requires a paid key (402 otherwise) when billing is enforced.

## Request body

- union: A JSON object of inputs per the model's contract — one schema per catalog model, selected by the {model} path parameter.
  - ModelInputsRelocation: Inputs for model spec relocation v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `currentSalary` number, required
    - `newSalary` number, required
    - `currentMonthlyExpenses` number, required
    - `newMonthlyExpenses` number, required
    - `movingCosts` number, required
    - `currentSavings` number, required
    - `annualReturn` number, required
    - `yearsHorizon` integer, required
  - ModelInputsRentVsBuy: Inputs for model spec rent-vs-buy v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `homePrice` number, required
    - `downPaymentPct` number, required
    - `mortgageRate` number, required
    - `mortgageTermYears` integer, required
    - `propertyTaxRate` number, required
    - `maintenanceRate` number, required
    - `homeAppreciationRate` number, required
    - `monthlyRent` number, required
    - `rentIncreaseRate` number, required
    - `investmentReturn` number, required
    - `timeHorizonYears` integer, required
  - ModelInputsFire: Inputs for model spec fire v1.0.1. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `currentAge` integer, required
    - `currentSavings` number, required
    - `annualIncome` number, required
    - `annualExpenses` number, required
    - `savingsRate` number, required
    - `expectedReturn` number, required
    - `withdrawalRate` number, required
  - ModelInputsRothVsTraditional: Inputs for model spec roth-vs-traditional v1.0.1. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): retirementAge must exceed currentAge.
    - `annualContribution` number, required
    - `currentAge` integer, required
    - `retirementAge` integer, required
    - `currentMarginalRate` number, required
    - `retirementTaxRate` number, required
    - `expectedReturn` number, required
  - ModelInputsRefinance: Inputs for model spec refinance v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `currentBalance` number, required
    - `currentRate` number, required
    - `currentRemainingMonths` integer, required
    - `newRate` number, required
    - `newTermMonths` integer, required
    - `closingCosts` number, required
    - `monthsUntilMove` integer, required
  - ModelInputsWindfall: Inputs for model spec windfall v1.0.1. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `windfallAmount` number, required
    - `highInterestDebtBalance` number, required
    - `highInterestDebtRate` number, required
    - `taxableInvestmentReturn` number, required
    - `retirementReturn` number, required
    - `yearsToRetirement` integer, required
    - `marginalTaxRate` number, required
    - `allocationDebt` number, required
    - `allocationEmergency` number, required
    - `allocationRetirement` number, required
    - `allocationTaxable` number, required
  - ModelInputsSabbatical: Inputs for model spec sabbatical v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): retirementAge must exceed currentAge.
    - `currentSavings` number, required
    - `monthlyExpenses` number, required
    - `sabbaticalMonths` integer, required
    - `currentAge` integer, required
    - `retirementAge` integer, required
    - `annualSalary` number, required
    - `savingsRate` number, required
    - `annualReturn` number, required
    - `marginalTaxRate` number, required
  - ModelInputsOneIncome: Inputs for model spec one-income v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): retirementAge must exceed currentAge.
    - `income1` number, required
    - `income2` number, required
    - `monthlyExpenses` number, required
    - `currentSavings` number, required
    - `currentAge` integer, required
    - `retirementAge` integer, required
    - `annualReturn` number, required
    - `marginalTaxRate` number, required
    - `savingsRateOnOneIncome` number, required
    - `childcareMonthlyOffset` number, required
  - ModelInputsSecondHome: Inputs for model spec second-home v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `purchasePrice` number, required
    - `downPaymentPct` number, required
    - `mortgageRate` number, required
    - `mortgageTerm` integer, required
    - `propertyTaxRate` number, required
    - `insuranceAnnual` number, required
    - `maintenancePct` number, required
    - `rentalIncomeMonthly` number, required
    - `occupancyRate` number, required
    - `appreciationRate` number, required
    - `annualReturn` number, required
    - `yearsHorizon` integer, required
  - ModelInputsDivorce: Inputs for model spec divorce v1.2.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): annualReturnRate is in PERCENT points (e.g. 7 = 7%), not a decimal.
    - `combinedAssets` number, required
    - `combinedDebt` number, required
    - `homeValue` number, required
    - `homeMortgageBalance` number, required
    - `retirementAssets` number, required
    - `splitRatio` integer, required
    - `yourCurrentIncome` number, required
    - `alimonyMonthly` number, required
    - `childSupportMonthly` number, required
    - `legalFees` number, required
    - `yourAge` integer, required
    - `yearsToRetirement` integer, required
    - `annualReturnRate` number, required
  - ModelInputsDownPayment: Inputs for model spec down-payment v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `homePrice` number, required
    - `downPaymentPct` number, required
    - `currentSavings` number, required
    - `monthlySavings` number, required
    - `annualReturn` number, required
  - ModelInputsRsu: Inputs for model spec rsu v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `sharesVesting` number, required
    - `sharePrice` number, required
    - `annualSalary` number, required
    - `filingStatus` 'single' | 'married', required
    - `stateTaxRate` number, required
    - `holdingPeriodYears` integer, required
    - `diversifyPct` number, required
    - `stockGrowthRate` number, required
  - ModelInputsDebtPayoff: Inputs for model spec debt-payoff v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): debts[i].name is a free display string, ignored by the engine and excluded from verification; extraMonthlyPayment is a scalar in 0–2,000 USD/mo (per spec).
    - `extraMonthlyPayment` number, required
    - `debts` object[], required
      - `balance` number, required
      - `annualRate` number, required
      - `minimumPayment` number, required
  - ModelInputsStudentLoanPayoff: Inputs for model spec student-loan-payoff v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): investmentReturn must stay > 0 (NaN at 0).
    - `loanBalance` number, required
    - `interestRate` number, required
    - `minimumPayment` number, required
    - `extraPayment` number, required
    - `investmentReturn` number, required
    - `taxDeductionRate` number, required
  - ModelInputsEmergencyFund: Inputs for model spec emergency-fund v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `monthlyExpenses` number, required
    - `targetMonths` integer, required
    - `currentSavings` number, required
    - `monthlySavings` number, required
    - `savingsAccountRate` number, required
  - ModelInputsSalaryJump: Inputs for model spec salary-jump v1.0.1. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): retirementAge must exceed currentAge.
    - `currentSalary` number, required
    - `newSalary` number, required
    - `currentAge` integer, required
    - `retirementAge` integer, required
    - `currentSavings` number, required
    - `currentSavingsRate` number, required
    - `newSavingsRate` number, required
    - `annualReturn` number, required
    - `marginalTaxRate` number, required
  - ModelInputsHavingAChild: Inputs for model spec having-a-child v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): retirementAge must exceed currentAge.
    - `annualIncome` number, required
    - `currentSavingsRate` number, required
    - `currentSavings` number, required
    - `currentAge` integer, required
    - `retirementAge` integer, required
    - `annualReturn` number, required
    - `marginalTaxRate` number, required
    - `firstYearCost` number, required
    - `ongoingAnnualCost` number, required
    - `childcareYears` integer, required
    - `childcareAnnualCost` number, required
    - `college529Monthly` number, required
  - ModelInputsWedding: Inputs for model spec wedding v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): debtInterestRate must stay > 0 (NaN at 0).
    - `weddingBudget` number, required
    - `fundingMethod` 'savings' | 'debt', required
    - `currentSavings` number, required
    - `monthlySavings` number, required
    - `debtInterestRate` number, required
    - `debtRepaymentMonths` unknown, required
    - `annualReturn` number, required
    - `yearsHorizon` integer, required
  - ModelInputsRenovation: Inputs for model spec renovation v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): helocRate must stay > 0 (NaN at 0).
    - `renovationCost` number, required
    - `estimatedValueIncrease` number, required
    - `currentHomeValue` number, required
    - `fundingMethod` 'savings' | 'heloc', required
    - `helocRate` number, required
    - `helocTermMonths` integer, required
    - `appreciationRate` number, required
    - `annualReturn` number, required
    - `yearsHorizon` integer, required
  - ModelInputsSideBusiness: Inputs for model spec side-business v1.0.1. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): annualReturn must stay > 0 (NaN at 0).
    - `sideIncomeMonthly` number, required
    - `selfEmploymentTaxRate` number, required
    - `incomeTaxRate` number, required
    - `businessExpensesMonthly` number, required
    - `currentSavings` number, required
    - `currentMonthlySavings` number, required
    - `annualReturn` number, required
    - `yearsHorizon` integer, required
    - `currentAge` integer, required
  - ModelInputsMegaBackdoorRoth: Inputs for model spec mega-backdoor-roth v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): salary is a dead input by spec (accepted, no effect on outputs).
    - `salary` number, required
    - `traditional401kContribution` number, required
    - `employerMatch` number, required
    - `afterTaxContribution` number, required
    - `incomeTaxRate` number, required
    - `annualReturn` number, required
    - `yearsToRetirement` integer, required
  - ModelInputs529CollegeSavings: Inputs for model spec 529-college-savings v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): collegeStartAge must be at least childAge; annualReturn529 and annualReturnTaxable must stay > 0 (NaN at 0).
    - `childAge` integer, required
    - `collegeStartAge` integer, required
    - `annualTuition` number, required
    - `tuitionInflationRate` number, required
    - `yearsInCollege` integer, required
    - `currentSaved` number, required
    - `monthlyContribution` number, required
    - `annualReturn529` number, required
    - `annualReturnTaxable` number, required
    - `incomeTaxRate` number, required
  - ModelInputsPrivateSchool: Inputs for model spec private-school v1.2.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): annualReturn must stay > 0 (NaN at 0).
    - `annualTuition` number, required
    - `tuitionInflationRate` number, required
    - `yearsInPrivate` integer, required
    - `currentSavings` number, required
    - `monthlySavings` number, required
    - `annualReturn` number, required
  - ModelInputsSocialSecurityTiming: Inputs for model spec social-security-timing v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): lifeExpectancy must be at least currentAge.
    - `monthlyBenefitAt62` number, required
    - `fullRetirementAge` integer, required
    - `currentAge` integer, required
    - `lifeExpectancy` integer, required
    - `annualReturn` number, required
    - `inflationRate` number, required
  - ModelInputsLongTermCare: Inputs for model spec long-term-care v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): careStartAge must be at least currentAge.
    - `currentAge` integer, required
    - `careStartAge` integer, required
    - `careDurationYears` integer, required
    - `annualCareCost` number, required
    - `careInflationRate` number, required
    - `retirementSavings` number, required
    - `annualReturn` number, required
    - `ltcInsurancePremiumMonthly` number, required
    - `ltcInsuranceDailyBenefit` number, required
    - `ltcInsuranceBenefitPeriodYears` integer, required
  - ModelInputsEldercare: Inputs for model spec eldercare v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): careStartAge must be at least parentAge; annualReturnRate is in PERCENT points (e.g. 7 = 7%), not a decimal.
    - `parentAge` integer, required
    - `careStartAge` integer, required
    - `careDurationYears` integer, required
    - `careType` 'in-home-basic' | 'in-home-full' | 'assisted-living' | 'memory-care' | 'nursing-home', required
    - `parentAssets` number, required
    - `yourCurrentSavings` number, required
    - `yourMonthlySavings` number, required
    - `annualReturnRate` number, required
  - ModelInputsEstatePlanning: Inputs for model spec estate-planning v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): stateTaxRate and annualGrowthRate are in PERCENT points, not decimals.
    - `totalEstateValue` number, required
    - `retirementAccounts` number, required
    - `lifeInsurance` number, required
    - `totalDebts` number, required
    - `annualGifting` number, required
    - `charitableGiving` number, required
    - `numberOfHeirs` integer, required
    - `estateTaxExemption` number, required
    - `stateTaxRate` number, required
    - `yourAge` integer, required
    - `annualGrowthRate` number, required
    - `yearsToProject` integer, required
  - ModelInputsAutoLoan: Inputs for model spec auto-loan v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `vehiclePrice` number, required
    - `downPayment` number, required
    - `tradeInValue` number, required
    - `salesTaxRate` number, required
    - `titleAndFees` number, required
    - `annualRate` number, required
    - `termMonths` integer, required
  - ModelInputsLoanComparison: Inputs for model spec loan-comparison v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Costs are lifetime nominal dollars (interest + fees), undiscounted. Comparing offers with different terms ignores time value and payment duration — a longer loan's lower nominal total can still be worse in present-value terms..
    - `loanAmount` number, required
    - `annualRateA` number, required
    - `termMonthsA` integer, required
    - `feesA` number, required
    - `annualRateB` number, required
    - `termMonthsB` integer, required
    - `feesB` number, required
  - ModelInputsExtraPayment: Inputs for model spec extra-payment v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `currentBalance` number, required
    - `annualRate` number, required
    - `remainingTermMonths` integer, required
    - `extraMonthlyPayment` number, required
  - ModelInputsBiweeklyMortgage: Inputs for model spec biweekly-mortgage v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `loanAmount` number, required
    - `annualRate` number, required
    - `termMonths` integer, required
  - ModelInputsPointsBreakEven: Inputs for model spec points-break-even v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `loanAmount` number, required
    - `termMonths` integer, required
    - `baseRate` number, required
    - `reducedRate` number, required
    - `pointsPct` number, required
  - ModelInputsPmiRemoval: Inputs for model spec pmi-removal v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped.
    - `homePrice` number, required
    - `downPaymentPct` number, required
    - `annualRate` number, required
    - `termMonths` integer, required
    - `pmiMonthly` number, required
    - `cancelLtv` '0.80' | '0.78', required
  - ModelInputsArmVsFixed: Inputs for model spec arm-vs-fixed v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): armInitialPeriodMonths must be ≤ termMonths − 12 (the adjustment happens at least a year before payoff); violating requests are rejected, never adjusted..
    - `loanAmount` number, required
    - `termMonths` integer, required
    - `fixedRate` number, required
    - `armInitialRate` number, required
    - `armInitialPeriodMonths` integer, required
    - `armAdjustedRate` number, required
  - ModelInputsCreditCardMinimum: Inputs for model spec credit-card-minimum v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): minimumNeverPaysOff / fixedNeverPaysOff (booleans) are the authoritative never-pays-off signals; when true, that path's months and interest are truncated at the 1200-month horizon — never compare months to 1200..
    - `balance` number, required
    - `apr` number, required
    - `minPaymentPct` number, required
    - `minPaymentFloor` number, required
    - `fixedPayment` number, required
  - ModelInputsRmd: Inputs for model spec rmd v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Uniform Lifetime Table only (owner not >10 years older than a sole-beneficiary spouse; account not inherited). RMD start age follows the SECURE 2.0 birth cohort under the TY2026 pin: currentAge ≤ 66 → 75, currentAge ≥ 67 → 73..
    - `currentAge` integer, required
    - `accountBalance` number, required
    - `expectedReturn` number, required
    - `yearsToProject` integer, required
  - ModelInputsRothConversionLadder: Inputs for model spec roth-conversion-ladder v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): The TY2026 federal bracket table is applied to every ladder year (no bracket inflation); annualOtherTaxableIncome is taxable income after deductions..
    - `traditionalBalance` number, required
    - `annualConversion` number, required
    - `annualOtherTaxableIncome` number, required
    - `filingStatus` 'single' | 'married', required
    - `ladderYears` integer, required
    - `growthRate` number, required
  - ModelInputsBackdoorRoth: Inputs for model spec backdoor-roth v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): nondeductibleContribution max is the TY2026 IRA limit (facts registry irs.ira.contribution-limit.2026); existingPretaxIraBalance aggregates all traditional/SEP/SIMPLE IRAs and is assumed fully pre-tax..
    - `nondeductibleContribution` number, required
    - `existingPretaxIraBalance` number, required
    - `marginalRate` number, required
  - ModelInputsEmployerMatch: Inputs for model spec employer-match v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Single-tier match formula (matchRate × contributions up to matchLimitPct of salary); employee deferral capped at the TY2026 §402(g) limit of $24,500 (no catch-up) and match-eligible compensation at the §401(a)(17) limit of $360,000..
    - `salary` number, required
    - `employeeContributionPct` number, required
    - `matchRate` number, required
    - `matchLimitPct` number, required
  - ModelInputsCapitalGains: Inputs for model spec capital-gains v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Gains only — loss netting and carryforwards are out of scope. NIIT MAGI is approximated by taxable income + gains, which can understate NIIT near the threshold (spec exclusion)..
    - `ordinaryTaxableIncome` number, required
    - `shortTermGain` number, required
    - `longTermGain` number, required
    - `filingStatus` 'single' | 'married', required
  - ModelInputsSsaPia: Inputs for model spec ssa-pia v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): AIME (the 35-year indexed earnings average) is the caller's input — computing it from an earnings record is out of scope. Bend points are the 2026 eligibility-year pair; the 90/32/15 factors are fixed in law. PIA rounds down to the dime (SSA rule); the monthly benefit rounds down to the whole dollar as SSA pays it. Claiming ages are whole years; delayed credits stop at 70..
    - `aime` number, required
    - `claimAge` integer, required
    - `fullRetirementAge` unknown, required
  - ModelInputsStateIncomeTax: Inputs for model spec state-income-tax v1.1.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Input is STATE taxable income — each state's own deductions, exemptions, and base modifications are the caller's job (spec exclusion). Covers the nine no-income-tax states, the flat-rate states IL/PA/CO, and the graduated states CA/NY/MA/NJ/VA, all at TY2025 tables. filingStatus selects the graduated table and affects no flat or no-tax state. NY's tax-benefit recapture, MA's short-term-gains rates, and all local taxes are spec exclusions..
    - `state` 'AK' | 'FL' | 'NV' | 'NH' | 'SD' | 'TN' | 'TX' | 'WA' | 'WY' | 'IL' | 'PA' | 'CO' | 'CA' | 'NY' | 'MA' | 'NJ' | 'VA', required
    - `stateTaxableIncome` number, required
    - `filingStatus` 'single' | 'married', required
  - ModelInputsQuarterlyEstimates: Inputs for model spec quarterly-estimates v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): IRC §6654 safe harbors with the non-MFS 110% AGI trigger ($150,000); four equal installments — the annualized-income method is out of scope..
    - `expectedCurrentYearTax` number, required
    - `priorYearTax` number, required
    - `priorYearAgi` number, required
    - `expectedWithholding` number, required
  - ModelInputsEspp: Inputs for model spec espp v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Immediate-sale (disqualifying disposition) scenario only; domain edges approximate §423 limits (15% max discount; the $25,000 cap is on grant-date FMV, which the contribution-only domain does not recompute — see spec exclusions)..
    - `annualContribution` number, required
    - `discountPct` number, required
    - `priceAtGrant` number, required
    - `priceAtPurchase` number, required
    - `lookback` 'yes' | 'no', required
    - `marginalOrdinaryRate` number, required
  - ModelInputsBurnRateRunway: Inputs for model spec burn-rate-runway v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): ranOutOfCash / reachesCashflowPositive (booleans) are the authoritative signals: runwayMonths = 120 is the 10-year horizon truncation and firstCashflowPositiveMonth = 0 means none within it — never read those numbers without the booleans..
    - `cashOnHand` number, required
    - `monthlyBurn` number, required
    - `monthlyRevenue` number, required
    - `revenueGrowthRate` number, required
    - `burnGrowthRate` number, required
  - ModelInputsSafeDilution: Inputs for model spec safe-dilution v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): postMoneyValuationCap must be ≥ 2 × safeInvestment (a SAFE selling more than half the company is rejected, never adjusted). Valuation-cap post-money SAFE only — discount-only and MFN variants are out of scope.; safePctPostSafes and safePctPostRound are FLOORS: if the priced round values the company at or too close to the post-money cap, the SAFE converts into MORE than investment ÷ cap (Safe User Guide warning). The model assumes a round comfortably above the cap..
    - `safeInvestment` number, required
    - `postMoneyValuationCap` number, required
    - `newInvestorsPct` number, required
    - `optionPoolIncreasePct` number, required
  - ModelInputsOptionPool: Inputs for model spec option-pool v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): newMoney must be ≤ preMoneyValuation (rounds selling more than half the company are rejected, never adjusted); the pool increase is created pre-money and dilutes existing holders only..
    - `preMoneyValuation` number, required
    - `newMoney` number, required
    - `targetPostRoundPoolPct` number, required
    - `existingUnallocatedPoolPct` number, required
  - ModelInputsEquipmentLeaseVsBuy: Inputs for model spec equipment-lease-vs-buy v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Costs are after-tax lifetime nominal dollars, undiscounted, and the two terms may differ — the loan-comparison time-value caveat applies. Straight-line depreciation to residual; accelerated schedules (MACRS/§179/bonus) excluded.; Under this contract the tax rate rescales BOTH costs by (1 − marginalTaxRate) and can never change cheaperOption — taxes flip the real decision only through deduction timing and discounting, which are excluded (see spec)..
    - `equipmentCost` number, required
    - `loanRate` number, required
    - `loanTermMonths` integer, required
    - `monthlyLeasePayment` number, required
    - `leaseTermMonths` integer, required
    - `residualValuePct` number, required
    - `marginalTaxRate` number, required
  - ModelInputsSbaLoanCost: Inputs for model spec sba-loan-cost v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): FY2026 standard 7(a) fee schedule (loans approved 2025-10-01 through 2026-09-30); manufacturer and veteran fee waivers not applied; the 0.55% annual service fee is lender-paid by rule and deliberately excluded from borrower cost..
    - `loanAmount` number, required
    - `annualRate` number, required
    - `termMonths` integer, required
    - `financeUpfrontFee` 'yes' | 'no', required
  - ModelInputsIsoExercise: Inputs for model spec iso-exercise v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): fmvAtExercise must be ≥ strikePrice (underwater exercise has no bargain element and is out of domain). AMTI is approximated by ordinaryTaxableIncome + bargain element — AMT-specific deduction add-backs are a spec exclusion..
    - `ordinaryTaxableIncome` number, required
    - `isoShares` integer, required
    - `strikePrice` number, required
    - `fmvAtExercise` number, required
    - `filingStatus` 'single' | 'married', required
  - ModelInputsQsbsExclusion: Inputs for model spec qsbs-exclusion v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Eligibility (original issuance, C-corp, qualified trade or business, the §1202(d) gross-assets test) is an input assumption. Amounts and character only — no tax dollars are computed (spec exclusion)..
    - `realizedGain` number, required
    - `stockBasis` number, required
    - `acquisitionPeriod` '1993-08-11-to-2009-02-17' | '2009-02-18-to-2010-09-27' | '2010-09-28-to-2025-07-04' | 'after-2025-07-04', required
    - `holdingYears` integer, required
    - `priorExclusionsUsed` number, required
  - ModelInputs83bElection: Inputs for model spec 83b-election v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): pricePaid must be ≤ fmvAtGrant. Ordinary-income comparison only — sale-year capital gains are a spec exclusion (basis outputs + capital-gains cover the sale)..
    - `shares` integer, required
    - `fmvAtGrant` number, required
    - `pricePaid` number, required
    - `annualFmvGrowth` number, required
    - `vestingYears` integer, required
    - `ordinaryTaxableIncome` number, required
    - `filingStatus` 'single' | 'married', required
  - ModelInputsWashSale: Inputs for model spec wash-sale v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): basisPerShare must be ≥ saleProceedsPerShare (gains have no wash-sale question; equality degenerates to zero loss). replacementShares means shares of substantially identical stock acquired inside the §1091(a) 61-day window — the window and the substantially-identical determination are input assumptions (spec)..
    - `sharesSold` integer, required
    - `saleProceedsPerShare` number, required
    - `basisPerShare` number, required
    - `replacementShares` integer, required
    - `replacementCostPerShare` number, required
  - ModelInputsRetirementIncomeCliffs: Inputs for model spec retirement-income-cliffs v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): additionalIncome is ordinary in character. Taxable income and IRMAA-MAGI use a deduction-free proxy; IRMAA's two-year lookback is reported, not simulated; ACA uses the 48-state FPL with tax-family = coverage-family (spec exclusions)..
    - `filingStatus` 'single' | 'married', required
    - `ssAnnualBenefit` number, required
    - `otherOrdinaryIncome` number, required
    - `taxExemptInterest` number, required
    - `additionalIncome` number, required
    - `healthCoverage` 'medicare' | 'aca' | 'none', required
    - `householdSize` integer, required
    - `benchmarkMonthlyPremium` number, required
  - ModelInputsLongevityHorizon: Inputs for model spec longevity-horizon v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): SSA period life table 2023: population mortality, sex-distinct, no cohort improvement or personal underwriting (spec exclusions). Probabilities to already-attained ages are 1 by definition..
    - `currentAge` integer, required
    - `sex` 'male' | 'female', required
    - `planningSurvivalProbability` number, required
  - ModelInputsAnnuityPayout: Inputs for model spec annuity-payout v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): The actuarially FAIR payout under SSA population mortality — real quotes are lower (insurer loads + annuitant self-selection; spec exclusions). Annual payment mode; monthly figure is annual/12 by convention..
    - `purchaseAge` integer, required
    - `sex` 'male' | 'female', required
    - `premium` number, required
    - `annualDiscountRate` number, required
  - ModelInputsLifeInsuranceNeeds: Inputs for model spec life-insurance-needs v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Needs sizing, not underwriting: survivor benefits, spousal earnings, and taxes are excluded, so the recommendation errs conservative (spec exclusions)..
    - `annualIncomeToReplace` number, required
    - `yearsOfIncomeReplacement` integer, required
    - `realDiscountRate` number, required
    - `outstandingDebts` number, required
    - `mortgageBalance` number, required
    - `educationFund` number, required
    - `finalExpenses` number, required
    - `liquidAssets` number, required
    - `existingCoverage` number, required
  - ModelInputsStepUpVsGiftNow: Inputs for model spec step-up-vs-gift-now v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): costBasis ≤ assetValue (loss property's §1015 dual-basis rule is a spec exclusion); annualAppreciationPct and heirLtcgRatePct are PERCENT points, not decimals.
    - `assetValue` number, required
    - `costBasis` number, required
    - `annualAppreciationPct` number, required
    - `yearsToTransfer` integer, required
    - `heirLtcgRatePct` number, required
  - ModelInputsInheritedIra10Year: Inputs for model spec inherited-ira-10-year v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): All three rates are PERCENT points. Flat marginal rate by design — probe bracket dynamics by re-running with each timing's expected rate (spec assumptions)..
    - `inheritedBalance` number, required
    - `annualReturnPct` number, required
    - `marginalRatePct` number, required
    - `afterTaxReturnPct` number, required
  - ModelInputsQcd: Inputs for model spec qcd v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): Whole-year ages: eligibility modeled at 71+ (§408(d)(8) grants it at 70½ — a donor at 70 should read the answer as their post-70½ position)..
    - `age` integer, required
    - `plannedGivingAnnual` number, required
    - `rmdAmount` number, required
    - `marginalRatePct` number, required
    - `itemizes` 'yes' | 'no', required
  - ModelInputsBracketFill: Inputs for model spec bracket-fill v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): The TY2026 federal bracket table is applied to every year (no bracket inflation); annualOtherTaxableIncome is taxable income after deductions. Room is 0 when other income already reaches the chosen bracket's top: the model never converts above the chosen rate..
    - `traditionalBalance` number, required
    - `annualOtherTaxableIncome` number, required
    - `filingStatus` 'single' | 'married', required
    - `fillToRatePct` unknown, required
    - `years` integer, required
    - `growthRate` number, required
  - ModelInputsCharitableBunching: Inputs for model spec charitable-bunching v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): agi is each year's AGI before any QCD and includes iraDistributions (values above agi are read as agi). Whole-year ages: QCD eligibility modeled at 71+. Cash gifts above the 60% AGI limit are reported, not carried forward (spec exclusions)..
    - `filingStatus` 'single' | 'married', required
    - `agi` number, required
    - `iraDistributions` number, required
    - `age` integer, required
    - `annualGiving` number, required
    - `otherItemizedDeductions` number, required
    - `bunchYears` integer, required
  - ModelInputsPlan529Superfunding: Inputs for model spec plan529-superfunding v1.0.0. Every listed input is required; unknown keys are rejected; out-of-domain values are rejected, never clamped. Cross-field constraints (rejected, never normalized): annualReturnPct and taxableDragPct are PERCENT points. The 529 arm assumes qualified withdrawals (spec exclusions)..
    - `contributionPerBeneficiary` number, required
    - `donors` integer, required
    - `beneficiaries` integer, required
    - `annualReturnPct` number, required
    - `years` integer, required
    - `taxableDragPct` number, required

## Response `200`

The run envelope: inputs echoed, verified outputs, sentinels, assumptions, facts and the evidence record.

- RunSuccess
  - `ok` unknown, required
  - `model` string, required
  - `specVersion` string, required
  - `contractUrl` string, required
  - `specUrl` string, required
  - `inputs` object, required: Echo of the request inputs (the hashed `inputs`).
  - `outputs` object, required: The verified outputs, untouched except: display-only `formula` strings dropped; non-finite numbers encoded as "Infinity" / "-Infinity" / "NaN". Sentinel values are annotated, never rewritten.
  - `sentinels` SentinelNote[], required
    - `field` string, required
    - `value` union, required: Non-finite sentinels are encoded as the string "Infinity".
      - number
      - string
    - `meaning` string, required
    - `triggered` boolean, required
  - `assumptions` string[], required
  - `facts` FactRef[], required
    - `id` string, required
    - `label` string, required
    - `value` number, required
    - `period` string, required
    - `source` string, required
  - `record` DecisionRecord, required: Evidence record v2. Verify with POST /api/v1/records/verify or the SDKs' verifyRecord.
    - `sha256` string, required: SHA-256 (hex) over the canonical JSON of {model, specVersion, inputs, outputs} — keys sorted recursively, no whitespace.
    - `fields` unknown, required
    - `howToVerify` string, required
    - `model` string, required: The hashed model identity — a catalog model name, "household-projection", or "decision-<strategy>".
    - `specVersion` string, required
    - `inputs` object: The exact hashed inputs, present on records whose envelope does not otherwise expose them (household projections, decisions). Point-model run responses echo `inputs` at top level instead; a verify response's record covers the inputs the caller sent in the request.
    - `signature` RecordSignature: Proves Worthune minted the record's hash. Absent when the deployment has no signing key; a stored decision is signed only when its hash is recomputed from the stored inputs.
      - `alg` 'Ed25519', required
      - `keyId` string, required: Matches a key at GET /api/v1/records/keys.
      - `value` string, required: base64url signature.
      - `message` string, required: What was signed: "worthune-record:v1:" + sha256. Rebuild it from the hash when verifying.
  - `disclaimer` string, required

## Other responses

- `400`: Malformed JSON or validation failures, one entry per field.
- `402`: A paid model (or its spec / dataset / grading) was called without a key, or with an unrecognized or revoked key. Free without a key: emergency-fund, relocation, side-business.
- `404`: Unknown model.
- `429`: Hourly per-org stateful quota, a per-route durable limit, or the 120 requests/minute per-IP burst backstop.

---

[API](https://skmtc.dev/worthune/apis/worthune-api.md) · [All operations](https://skmtc.dev/worthune/apis/worthune-api/llms.txt) · [OpenAPI document](https://skmtc.dev/worthune/apis/worthune-api/revisions/9f2241072555?raw)
