The Far Better Off API: finance math as JSON, no key required

28 endpoints of US personal-finance math, free and keyless. There is nothing to sign up for, no plan to choose, no quota to apply for and no tracking of what you send. Every endpoint calls the same @calcwise/finance function the site itself runs on, so an answer from this API and an answer from a Far Better Off page can never disagree.

Authentication
None. No key, no account.
Methods
GET with a query string, or POST with JSON.
CORS
Open to every origin. No cookies.
Rate limit
60 requests / 60s per IP, best effort.

Quick start

One request, no setup. This is the whole onboarding.

curl "https://farbetteroff.com/api/v1/mortgage?homePrice=400000&downPayment=80000&rate=6.5&termYears=30"

From the browser — CORS is open, so this works from any origin, including a CodePen or someone else's blog:

const params = new URLSearchParams({
  balance: 5000,
  apr: 22.8,
  monthlyPayment: 150,
});

const res = await fetch(`https://farbetteroff.com/api/v1/credit-card-payoff?${params}`);
const { result } = await res.json();

console.log(result.months, result.totalInterest);

Every response has the same shape: the endpoint, the inputs it actually used (defaults included), the result, and provenance.

{
  "endpoint": "cd",
  "inputs": {
    "deposit": 10000,
    "apy": 4.25,
    "termMonths": 12
  },
  "result": {
    "maturity": 10425,
    "interest": 425
  },
  "notes": [
    "APY already accounts for the bank's compounding frequency, which is what makes it the comparable number (12 CFR Part 1030 / Regulation DD, Appendix A).",
    "Interest is shown before tax. CD interest is generally taxable as ordinary income."
  ],
  "meta": {
    "source": "https://farbetteroff.com",
    "calculator": "https://farbetteroff.com/calculators/cd-calculator",
    "docs": "https://farbetteroff.com/api/v1",
    "disclaimer": "Educational estimate, not financial advice."
  }
}

The spec

Both of these are generated from the same source as this page, so they cannot drift from what the API actually does.

  • GET /api/v1/openapi.json

    OpenAPI 3.1 document. Feed it to a client generator, Swagger UI, Postman, or an assistant's tool loader.

  • GET /api/v1

    The JSON index: every endpoint, parameter, unit, bound, default, return field and a working example URL.

One file you can vendor

/calcwise.js is a single ES module with no dependencies, no build step and no package to install — save it next to your own code and call it. It is generated from the same endpoint list as this page, so it has a documented method for all 28 endpoints and cannot offer one the API doesn't serve.

curl -O https://farbetteroff.com/calcwise.js
import { calcwise } from "./calcwise.js";

const cw = calcwise();

const { result, notes } = await cw.mortgage({
  homePrice: 400000,
  downPayment: 80000,
  rate: 6.5,
  termYears: 30,
  propertyTaxAnnual: 3600,
  insuranceAnnual: 1800,
});

result.principalAndInterest;  // 2022.62
result.monthlyTotal;          // 2472.62  (P&I + $300 tax + $150 insurance)
notes;                        // the caveats you have to read before trusting it

Methods are named for their endpoint, camelCased at the hyphens — cw.rentVsBuy(), cw.creditCardPayoff(). The 2 that start with a digit are reached with brackets, because JavaScript won't take one after a dot: cw["401k"]() and cw["401kMatch"](). cw.call(slug, params) takes the slug directly when it is held in a variable, and cw.url(slug, params) builds the request URL without sending it.

A non-2xx response throws a CalcWiseError carrying the API's own explanation rather than flattening it to a status code — every invalid parameter, with its reason:

import { calcwise, CalcWiseError } from "./calcwise.js";

try {
  await calcwise().loan({ principal: 300000, rate: 6.5 });
} catch (err) {
  if (err instanceof CalcWiseError) {
    err.status;   // 400
    err.code;     // "invalid_params"
    err.issues;   // [{ param: "termMonths", message: "Required. Expected integer, …" }]
    err.docs;     // "https://farbetteroff.com/api#loan"  — the endpoint that failed, not the catalogue
  }
}

The calls and the answers are both typed in the file itself, so vendoring it is enough. Turn on checkJs and your editor completes the params you pass and the res.result and res.inputs you get back, field by field — 198 parameters, 198 echoed inputs and 316 result fields — and marks a misspelling of any of them, with nothing installed and no build step. A result field in [brackets] is one the endpoint genuinely omits for some inputs.

Each endpoint's three types are named, so a request is something you can annotate rather than only something you can pass: @type {MortgageParams} on an object you build up is checked where you build it. The same names are declarations in /calcwise.d.ts for a TypeScript project, and a test asserts the two files declare the same fields with the same types, so vendoring the one file loses nothing.

It also compiles clean under strict, which is what your project probably already has on — a vendored file is compiled by your settings, not by the ones it was written under, and a file you are told to trust should not be the thing that lights up your build. Zero findings in a browser project and in a Node one, which disagree about whether response.json() is any or unknown; both are checked by a test against the exact bytes this page links.

Runs anywhere there is fetch: browsers, Node 18+, Deno, Bun and workers. calcwise({ baseUrl, fetch, timeout, method }) covers the rest — point it at your own copy, hand it a caching fetch, or switch to POST for a long parameter set. It ships unminified and MIT-licensed at 195.2 KB, of which 170.4 KB is that type block: the code is the first 595 lines, because the person about to trust it with their site's numbers should be able to read it first.

TypeScript, without installing anything

Save /calcwise.d.ts next to calcwise.js and TypeScript picks it up on its own — no import, no types field, no tsconfig change. The parameters, the echoed inputs and the result of every endpoint are all typed, so a misspelled input is a compile error and so is a misread output:

curl -O https://farbetteroff.com/calcwise.js -O https://farbetteroff.com/calcwise.d.ts
import { calcwise } from "./calcwise.js";
const cw = calcwise();

const { result, inputs } = await cw.loan({ principal: 300000, rate: 6.5, termMonths: 360 });

result.totalInterest;             // number
result.schedule?.[0].balance;     // number | undefined — schedule=true only
result.monthlyPayment;            // Property 'monthlyPayment' does not exist on type 'LoanResult'

inputs.schedule;                  // boolean — false, the default the API filled in
inputs.termMonths.toFixed(0);     // number, not number | string | boolean

await cw.mortgage({ homePrce: 400000 });
//   'homePrce' does not exist in type 'MortgageParams'. Did you mean to write 'homePrice'?

const { result: st } = await cw.stateTax({ state: "CA", wages: 75000 });
const owed: number = st.tax;      // Type 'number | null' is not assignable to type 'number'

The result types are derived, not declared. A hand-written type for result would be a second copy of what the endpoint returns, and it would drift the first time a field was added — so the generator runs every endpoint over 2,364 valid input combinations, covering every enum and boolean branch it has, and types the 316 fields it observes. A field the API can omit comes out optional; one that can be null comes out | null; the state code and filing status the API echoes back come out as the exact set of values it will ever send.

inputs is typed too, across all 198 fields of it. That is what the answer was actually computed from rather than what you sent, so it is the honest thing to render in “computed at 6.5% over 30 years” — and it is not simply your parameters again: an optional parameter with a default is always echoed, one without is echoed only when you send it, and both readings are in the type.

Numbers are numbers in the types. The HTTP API also accepts "$400,000" as a string, because people paste money — the typed client asks for the canonical form so a wrong unit is visible at the call site. It is a declaration file, so it disappears at build time: 193.8 KB in your repo and 0 bytes in your bundle.

A whole page, not a snippet

Everything above shows you the call. If what you actually want is to see the finished thing — 3 worked examples are single HTML files with no build step, no framework and no key: a mortgage payment that updates as you type, and the state-tax endpoint with its three-way answer handled properly. Open one, read it end to end, save it, change the numbers. They also show the three habits — debounce, cache, abort — that keep a keystroke-driven page inside the 60-a-minute budget.

Conventions

Percentages are percentages
rate=6.5 means 6.5%, not 0.065. Every percent-valued parameter says so in its unit.
Money can look like money
principal=$300,000 parses the same as principal=300000, so you can pass a value straight out of a form field without stripping it first.
Dollars are rounded to cents
Rates and year counts keep more precision where it matters. Nothing is rounded before the math, only after.
JSON has no Infinity
A card that never pays off returns neverPaysOff: true and a null month count rather than a number you have to guard against.
Unknown parameters are an error
A typo is reported, not ignored. Sending principle gets you a 400 naming principal as the thing you probably meant — and where no single name is the obvious match, the parameters the endpoint does accept — instead of a confidently wrong answer computed without it.
Every answer carries its provenance
meta.calculator is the page on farbetteroff.com that answers the same question with the same function, so a reader can check your number against ours. Where the answer rests on a figure somebody published for a named year, meta.dataVintage names the edition and the date it is superseded — see how old is this data.

Errors

Non-2xx responses are {"error": {"code", "message", …}}. A validation failure lists every problem at once, so one round trip tells you everything that is wrong.

A name within an edit or two of a real parameter is answered with the one it probably meant, in didYouMean on its own issues entry, and docslinks the section for the endpoint you called — not this page’s table of contents. Where the guess would be a coin flip it isn’t made, but it isn’t dropped either: apr is one edit from all six of apr1 … apr6, the six per-debt slots on /debt-snowball, so that one comes back with all six in candidates. Exactly one of the two keys is ever present, and a name nothing is close to still gets the accepted list.

A wrong endpoint is answered the same way, in didYouMean. That covers the case this page causes: the slug of the calculator you were reading is not the slug of the endpoint, so /v1/mortgage-calculator points you at /v1/mortgage and /v1/retirement-calculator at /v1/safe-withdrawal. Where a page is answered by two endpoints the choice would be a coin flip, so it isn’t made — both are named in candidates instead, and /v1/take-home-paycheck-calculator comes back with paycheck and state-tax. Exactly one of the two keys is ever present.

A mistyped value of an enum reads the same way, in the same two keys: status=marrried comes back with married. The alternative spellings count as spellings, so state=Ohioo and state=ohoi both read as OH — a correction is always the documented value, never the alias it was nearest to. The accepted list still appears when nothing is close, which is where it is the answer; it is what a mistyped state used to get instead, all 51 of them. A number that is out of range carries neither key, because there the value is wrong rather than misspelt — it gets a reading of a different kind, below.

Percentages are whole numbers, and a decimal one is caught rather than obeyed. Send rate=6.5 for 6.5%, never 0.065. That second convention is the one mistake here that used to pass validation and answer anyway: 0.065 is a legal value, so the reply was a correct answer to 0.065% and nothing said so. A percent parameter given a value under 1 now comes back with a warnings entry beside the answer — code: "percent_looks_like_fraction", the sent value, and didYouMean holding the one you probably wanted. The result is still a real answer to what you sent; the warning is how you find out you sent the wrong thing. Under 1 is where the two conventions genuinely disagree and nowhere else: 6.5 cannot be a fraction, and 0 is zero either way.

It fires only where the rescaled reading is a value that parameter accepts, which is what keeps it off real sub-1 rates. pmiRate defaults to 0.5 and caps at 5, so 0.5 would have to mean 50 — out of range, not a fraction, no warning; the same test spares a 0.5% property-tax rate. The reading is attached to the error too, where the value is rejected outright: withdrawalRate=0.04is below that parameter’s minimum of 0.1, and that is the 4% rule written the other way round, so the message names 4 instead of only repeating the bound.

$ curl "https://farbetteroff.com/api/v1/compound-interest?principal=10000&rate=0.07&years=10"

{
  "endpoint": "compound-interest",
  "inputs": { "principal": 10000, "rate": 0.07, "years": 10, … },
  "result": {
    "balance": 10070.24,
    "contributed": 10000,
    "growth": 70.24
  },
  "warnings": [
    {
      "param": "rate",
      "code": "percent_looks_like_fraction",
      "message": "Read as 0.07%. Percentages here are whole numbers, so 7 means 7% — if you meant 7%, send rate=7.",
      "sent": 0.07,
      "didYouMean": 7
    }
  ],
  …
}
$ curl "https://farbetteroff.com/api/v1/loan?principle=300000&rate=6.5"

{
  "error": {
    "code": "invalid_params",
    "message": "3 parameters are invalid.",
    "issues": [
      {
        "param": "principle",
        "message": "Unknown parameter. Did you mean \"principal\"?",
        "didYouMean": "principal"
      },
      {
        "param": "principal",
        "message": "Required. Expected number, US dollars, between 0 and 100000000000."
      },
      {
        "param": "termMonths",
        "message": "Required. Expected integer, whole months, between 1 and 1200."
      }
    ],
    "docs": "https://farbetteroff.com/api#loan"
  }
}
StatusCodeWhen
400invalid_paramsA parameter is missing, mistyped, out of range, or not a parameter at all.
400invalid_jsonA POST body that is not a JSON object.
404unknown_endpointNo such endpoint. The response lists every valid slug, names one in didYouMean when the intent is clear — including when you sent the calculator page's slug instead of the endpoint's — and names several in candidates when they draw.
429rate_limitedMore than 60 requests in 60 seconds from one IP. Includes Retry-After.
405—A method other than GET, POST or OPTIONS.
500internal_errorOur bug, never your inputs. Please report it on GitHub.

Caching and fair use

Every answer is a pure function of its inputs, so the same URL is the same JSON forever. Successful responses are served with Cache-Control: public, max-age=3600, s-maxage=31536000, stale-while-revalidate=86400 — cache them as hard as you like. A cached response costs us nothing and does not count against the limit.

The 60-per-60s limit is a courtesy brake against a runaway loop, not a paywall in disguise. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 adds Retry-After. If you need more than this for something real, email hellofarbetteroff@gmail.com — there is no upsell at the end of that conversation.

No attribution is required to call the API. If you show the numbers to other people, a link back to farbetteroff.com is appreciated and is what keeps this free for everyone else.

How old is this data?

Most of what this API returns is arithmetic, and arithmetic does not go stale: the payment on a 30-year loan at 6.5% is the same number in 2029. 9 endpoints are different. They answer with figures a government body set or measuredfor a named year — the IRS brackets for a tax year, the Federal Reserve’s survey of what households actually have — and those are superseded on a schedule their publisher keeps, not one Far Better Off keeps.

Each of those responses carries a meta.dataVintage array saying which edition the answer rests on, and GET /api/v1 lists the whole schedule once in dataVintages.

There is a date, and deliberately no verdict. Every answer here is cacheable for up to a year, so a stale: true computed when the response was generated would describe the moment it entered a cache, not the moment you read it — the one field nobody could trust. So the block carries supersededFrom, a fixed date, and you compare it against your own clock. If you would rather import that comparison than write it, @calcwise/finance exports isStale() and staleVintages() over the same registry these come from.

EditionPublisherData yearCycleSuperseded fromEndpoints
Changes in U.S. Family Finances from 2019 to 2022Federal Reserve Board2022every 3 years2026-12-01net-worth
Rev. Proc. 2025-32 (tax year 2026)Internal Revenue Service2026annual2027-01-01paycheck, roth-vs-traditional
Notice 2025-67 (retirement plan limits for 2026)Internal Revenue Service2026annual2027-01-01paycheck, 401k, roth-vs-traditional
2026 wage base, $184,500Social Security Administration (via IRS Topic no. 751)2026annual2027-01-01paycheck
Rates in force for 2026State revenue departments2026annual2027-01-01state-tax
Employee contribution rates for calendar year 2026State labor and employment agencies2026annual2027-01-01state-tax
90 FR 57890, effective 1 January 2026Consumer Financial Protection Bureau2026annual2027-01-01debt-to-income
Economic Well-Being of U.S. Households in 2025Federal Reserve Board2025annual2027-06-01emergency-fund, budget
City wage tax rates in force from 2026-07-01City revenue departments2026annual2027-08-01state-tax
Collection Financial Standards, transportation, effective 2026-06-29Internal Revenue Service2026annual2027-09-01car-affordability

Published figures

Everything above is a pure function of its query string: the same URL is the same answer forever. The 4 routes below are the other kind of thing — a figure Far Better Off publishes rather than a function it exposes. No parameters, and the same URL returns a different number when the body behind it publishes — a statistical series for some, an IRS notice for others — so each one carries an asOf (the date the figure last changed, not the date it was served) and a shorter Cache-Control to match.

Today's US consumer interest rates

The nine national average rates the site runs on, each with its own reading date: 30- and 15-year fixed mortgages, the Fed funds target, the savings and 12-month CD averages, the 10-year Treasury, and the Federal Reserve's credit card, new-car and personal-loan averages. Every row names the body that published it — Freddie Mac, the FDIC or the Federal Reserve Board — rather than the aggregator it was read through. Takes no parameters; refetched every six hours.

GET https://farbetteroff.com/api/v1/rates · the same figures, with every step shown, are on its page.

Sources: Freddie Mac PMMS · FDIC national rates · Federal Reserve H.15 · Federal Reserve G.19 · FOMC target rate

Income needed to buy the median new home in the United States

The gross household income the 28% front-end ratio asks for on the median-priced new home at the current 30-year fixed rate, with the payment broken out, the same answer on 10% down, and the price the median household income actually reaches. Takes no parameters; rebuilt every six hours from three public series.

GET https://farbetteroff.com/api/v1/income-needed-to-buy-a-house · the same figures, with every step shown, are on its page.

Sources: MSPUS · MORTGAGE30US · MEHOINUSA646N

State income tax on wages, 2026

What each of the 50 states and the District of Columbia charges on a paycheck: the 9 that levy no individual income tax on wages, the 16 with one statutory rate, the 4 whose published bracket schedules are modelled in full, and the 22 where the row is an explicit refusal rather than a number. Every verified row carries its revenue department's own page, its standard deduction, its zero band or surtax where it has one, and a top marginal rate. Takes no parameters.

GET https://farbetteroff.com/api/v1/state-income-tax-rates · the same figures, with every step shown, are on its page.

Sources: State revenue departments

The 2026 money numbers

The 2026 US contribution limits, deductions and rates in one call: 401(k), IRA and HSA limits, the standard deduction and the senior deduction, the gift exclusion, the Social Security COLA, wage base and full retirement age, and I bond and FDIC figures. Every figure carries the notice, revenue procedure or section of the US Code that set it. Takes no parameters.

GET https://farbetteroff.com/api/v1/money-numbers · the same figures, with every step shown, are on its page.

Sources: IRS Notice 2025-67 · IRS Rev. Proc. 2025-32 · IRS Rev. Proc. 2025-19 · 90 FR 49047 · 26 U.S.C. § 151 · TreasuryDirect I bonds · FDIC deposit insurance

What the API does not do

  • No withholding, and state tax only where it is a fact. /api/v1/paycheck is federal only: brackets, the standard deduction and FICA, with no W-4 allowances and no withholding tables. /api/v1/state-tax answers the state line only where Far Better Off can answer it honestly — 0 in the 9 states that levy no individual income tax on wages, a computed figure in the 16 charging one statutory rate, and an explicit null with a reason in the other 22, whose graduated brackets Far Better Off does not model and will not approximate. An API that quietly ignored state tax would be worse than no API; one that guessed at it would be worse still.
  • No rates, no lookups.Property tax, insurance, APRs and PMI rates are values you pass in. The API never guesses a number for your location. (Far Better Off's own rates page reads the public FRED series if you need a current average.)
  • No advice.These are educational estimates. Where a figure comes from a regulator — IRS contribution limits, the CFPB's PMI cancellation rules — the endpoint says so in its notes.
  • No state in either sense. Nothing is stored, nothing is logged, there is no account to create and no cookie to set.

Endpoint reference

All 28 endpoints live under https://farbetteroff.com/api/v1.

Every console below is a link. Send a request and the address bar becomes https://farbetteroff.com/api?try=pay&…, which opens this page at that endpoint with those numbers already in the form and the answer already fetched — Copy link to this call hands the same URL over. So a question about this API travels as a working request rather than as a description of one: paste it into an issue, a README, a review or a reply and whoever opens it sees the number, not the instructions for getting it. A bare ?try=pay opens the documented example.

get/api/v1/pay

Pay, converted

One wage restated in every period: per hour, per day, per week, every two weeks, twice a month, per month and per year — in either direction.

Parameters

NameAcceptsRequiredDescription
amountnumber, US dollars, between 0 and 1000000000yesThe pay figure you have.
perone of hour, day, week, biweek, semimonth, month, yearyesThe period that amount is for. biweek is every two weeks (26 paychecks a year), semimonth twice a month (24).
hoursPerWeeknumber, a count, between 0.5 and 168no, defaults to 40Hours worked in a week.
weeksPerYearnumber, a count, between 1 and 52no, defaults to 52Weeks paid in a year. Drop it for unpaid time off: two weeks off is 50.
daysPerWeeknumber, a count, between 1 and 7no, defaults to 5Days worked in a week, which is what the daily figure divides by.
overtimeAfterHoursnumber, a count, between 1 and 168no, defaults to 40Hours in the week after which the premium starts. 40 is the federal floor; a contract or a state rule can start it sooner.
overtimeMultipliernumber, between 1 and 3no, defaults to 1.5What an hour past the threshold pays, as a multiple of the base rate. Send 1 for a schedule with no premium — a salaried exempt job — and every figure is straight time again.

Returns, inside result

hourly
Pay for one hour worked, averaged over the week: above the threshold this is higher than baseHourly, because some of those hours pay the premium.
daily
Pay for one worked day.
weekly
Pay for one paid week.
biweekly
One paycheck when payroll runs every two weeks (26 a year).
semiMonthly
One paycheck when payroll runs twice a month (24 a year).
monthly
One month's pay — a twelfth of the year, not four weeks.
annual
The yearly total.
hoursPerYear
Paid hours in the year the hourly figure divides by.
baseHourly
The straight-time rate behind the answer — what one of the first overtimeAfterHours hours pays. Sent an hourly amount, it is that amount; sent a salary, it is what an hourly job would have to pay to reach it once the premium is counted, which is less than the average hour.
overtimeHours
Hours a week above the threshold. Zero on a schedule that never reaches it.
overtimeRate
What an hour past the threshold pays: baseHourly × overtimeMultiplier. Quoted even on a week that never reaches it, because it is what the next hour would earn.
overtimePremiumAnnual
What the premium alone adds over the year, against the same hours at straight time. Zero when there is no premium.
  • Gross pay, before tax and deductions. /api/v1/paycheck takes federal income tax and FICA out of the annual figure; /api/v1/state-tax adds state wage tax where Far Better Off models it.
  • Hourly, daily and weekly follow the schedule you pass, because a real schedule changes them: 40 hours a week for 52 weeks by default, a 2,080-hour year.
  • Hours past 40 carry the overtime premium, because a paycheck does: 29 U.S.C. § 207(a)(1) requires at least one and a half times the regular rate past 40 hours in a workweek, so amount=25&per=hour&hoursPerWeek=50 is $71,500 a year — 40 × $25 plus 10 × $37.50 — and not the $65,000 straight-lining gives. That is the default because the salary ↔ hourly calculator and the /pay pages have answered it that way since 2026-09-12, and one wage cannot have two answers. Send overtimeMultiplier=1 for an exempt salaried schedule that earns no premium.
  • Sent a salary rather than an hourly rate, the yearly total is whatever you sent — a salary is already the whole year — and the premium changes what it is worth by the hour instead: hourly is the average across every hour, baseHourly is what an hourly job would have to pay for the first 40. A $60,000 salary at 50 hours a week averages $23.08 an hour but only needs a $20.98 base rate to match, because ten of those hours pay 1.5×.
  • This is the federal floor and nothing else. California, Alaska and a handful of other states add a daily overtime rule on top of the weekly one, and a contract can start the premium sooner — overtimeAfterHours is there for both. Whether a particular job is exempt from the premium at all is a question about the job, not about the arithmetic, and this endpoint does not answer it.
  • Monthly, semi-monthly and biweekly are fixed payroll counts — 12, 24 and 26 pay periods — so they do not move when the schedule does.
  • 26 biweekly periods is the convention, not the calendar: 52 weeks is exactly 26 fortnights, but a 365-day year is 26.07, so some years contain 27 biweekly paychecks.
  • Federal pay conversion divides an annual rate by 2,087 hours rather than 2,080 (5 U.S.C. § 5504(b), which averages the leap-year cycle in), so a federal annual rate converted here reads about 0.34% high.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/pay?amount=25&per=hour

Share https://farbetteroff.com/api?try=pay&amount=25&per=hour#pay

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/pay?amount=25&per=hour"

get/api/v1/paycheck

Take-home pay (federal)

Federal income tax bracket by bracket, Social Security, Medicare and what is left of a salary — per year, per month and per paycheck.

Parameters

NameAcceptsRequiredDescription
salarynumber, US dollars, between 0 and 1000000000yesGross annual salary.
statusone of single, married, hoh, mfsno, defaults to singleFiling status: single, married (filing jointly), hoh (head of household) or mfs (married filing separately).
contribPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0401(k)/403(b) contribution as a percent of salary. See contribType for which side of the tax line it falls on.
contribTypeone of traditional, rothno, defaults to traditionaltraditional: an elective deferral, exempt from income tax but not from FICA. roth: a designated Roth contribution, which the IRS includes in gross income when it is earned, so it reduces no tax base at all and only takeHome moves.
catchUpone of none, age50, age60to63no, defaults to noneWhich catch-up raises the § 402(g) deferral cap, by the age reached during the year: none caps the contribution at $24,500, age50 at $32,500, age60to63 at $35,750 (IRS Notice 2025-67). contribPercent is capped at whichever applies, so contribution can be less than the percent asked for — see contributionLimited.
payPeriodsinteger, a count, between 1 and 365no, defaults to 26Paychecks per year: 52 weekly, 26 every two weeks, 24 twice a month, 12 monthly.

Returns, inside result

takeHome
Annual pay after federal tax, Social Security, Medicare and the contribution. No state tax.
perPaycheck
takeHome divided by payPeriods.
perMonth
takeHome divided by 12.
taxableIncome
salary minus pretaxContribution minus the standard deduction, floored at 0. A Roth contribution is not subtracted.
standardDeduction
The 2026 standard deduction for the filing status.
contribution
Dollars contributed over the year, of either type, after the annual limit. Never more than deferralLimit.
requestedContribution
What contribPercent asked for, before the limit: salary times the percent. Equal to contribution unless contributionLimited.
deferralLimit
The § 402(g) cap applied for catchUp: 24500, 32500 or 35750 for 2026. An employer match is outside it.
contributionLimited
Whether the percent asked for more than deferralLimit allows.
contributionType
traditional or roth, echoed back.
pretaxContribution
The part of contribution that reduced taxable income: all of it for traditional, 0 for roth. This is the figure to subtract from a state or local wage base.
federalIncomeTax
Federal income tax on taxableIncome.
socialSecurity
6.2% of wages up to the wage base.
medicare
1.45% of all wages.
additionalMedicare
0.9% of wages above $200,000. Usually 0.
fica
socialSecurity + medicare + additionalMedicare.
totalTax
federalIncomeTax + fica. Federal only.
effectiveTaxRatePercent
totalTax as a percent of gross salary.
marginalRatePercent
The top bracket the income reaches. Not the same as the effective rate.
brackets
Each bracket the income reached: rate, band, the income inside it and the tax on it.
taxYear
The tax year the brackets and deduction come from.
socialSecurityWageBase
Wages above this pay no Social Security tax.
additionalMedicareThreshold
Wages above this pay the extra 0.9% Medicare tax.
  • Federal only. No state or local income tax is included, so in 41 states and D.C. real take-home pay is lower than takeHome. /api/v1/state-tax answers the state line where that is a fact rather than a guess: 0 in the 9 states that tax no wages, a computed figure in the 16 with one statutory rate and in California, New Jersey, New York and Virginia, whose published bracket schedules are modelled, and null in the other 22, whose brackets Far Better Off has not verified and will not approximate. Income tax is not the whole of it either: 10 states withhold a disability or paid-leave contribution from the same wages, which the same endpoint answers in "payrollContributions" — so takeHome is high by $975 a year for a Californian on $75,000 before a cent of state income tax is counted, and high in Washington, which levies no income tax at all.
  • 2026 figures: brackets and standard deduction from IRS Rev. Proc. 2025-32; Social Security wage base $184,500 and the FICA rates from IRS Topic no. 751; the $24,500 elective-deferral limit and its $8,000 and $11,250 catch-ups from IRS Notice 2025-67.
  • contribPercent is capped at the § 402(g) limit, so a percent that would exceed it returns the contribution a plan could actually take and flags contributionLimited. Traditional and Roth deferrals share the one limit; an employer match is outside it and is not modelled here.
  • This is the employee half of FICA. It is not self-employment tax, and it does not model W-4 allowances, pre-tax health or HSA premiums, credits, or income other than wages.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/paycheck?salary=75000&status=single&contribPercent=5&payPeriods=26

Share https://farbetteroff.com/api?try=paycheck&salary=75000&status=single&contribPercent=5&payPeriods=26#paycheck

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/paycheck?salary=75000&status=single&contribPercent=5&payPeriods=26"

get/api/v1/state-tax

State income tax on wages

What a state takes out of a salary, for the 29 jurisdictions where that is a verified fact rather than a guess — 9 that tax no wages at all, 16 that charge one statutory rate, and California, New Jersey, New York and Virginia on their own published bracket schedules. For the other 22 it answers null and says why.

Parameters

NameAcceptsRequiredDescription
stateone of AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WYyesUSPS two-letter code, or the full state name ("Ohio", "District of Columbia"). Where the bare name is taken, the spelling people actually write answers too — "Washington DC", "Washington, D.C." and "D.C." for the District, "Washington State" and "New York State" for the two states whose names those places open. Either case; the code is echoed back.
wagesnumber, US dollars, between 0 and 1000000000yesGross annual wages.
pretaxRetirementnumber, US dollars, between 0 and 1000000000no, defaults to 0Traditional 401(k)/403(b) dollars contributed over the year. Subtracted from the taxed wages everywhere except Pennsylvania, which taxes elective deferrals.
filingStatusone of single, married, hoh, mfsno, defaults to singleHow this person files, which decides the state's standard deduction where we model one (Georgia exempts $15,000 single and $30,000 married filing jointly). Ignored in states whose deduction is not modelled.
localityone of oh-cincinnati, oh-cleveland, oh-columbus, pa-philadelphia, pa-philadelphia-nonresident, mi-detroit, ny-new-york-city, in-marion, in-allen, in-lake, in-hamilton, in-st-joseph, in-vanderburgh, in-tippecanoe, in-monroe, ky-louisville, ky-louisville-nonresident, ky-lexington, ky-lexington-nonresident, mi-detroit-nonresident, mi-grand-rapids, mi-grand-rapids-nonresident, mi-lansing, mi-lansing-nonresident, mi-flint, mi-flint-nonresident, mi-pontiac, mi-pontiac-nonresident, mi-east-lansing, mi-east-lansing-nonresident, mi-battle-creek, mi-battle-creek-nonresident, mi-saginaw, mi-saginaw-nonresident, mi-highland-park, mi-highland-park-nonresident, mi-muskegon, mi-muskegon-nonresident, mi-big-rapids, mi-big-rapids-nonresident, mi-walker, mi-walker-nonresident, mi-hamtramck, mi-hamtramck-nonresident, mi-muskegon-heights, mi-muskegon-heights-nonresident, mi-portland, mi-portland-nonresident, mi-benton-harbor, mi-benton-harbor-nonresident, mi-albion, mi-albion-nonresident, mi-ionia, mi-ionia-nonresident, mi-lapeer, mi-lapeer-nonresident, mi-springfield, mi-springfield-nonresident, pa-pittsburgh, pa-pittsburgh-nonresident, pa-allentown, pa-allentown-nonresident, pa-reading, pa-reading-nonresident, pa-erie, pa-erie-nonresident, pa-scranton, pa-scranton-nonresident, pa-bethlehem, pa-bethlehem-nonresident, pa-lancaster, pa-lancaster-nonresident, pa-harrisburg, pa-harrisburg-nonresident, pa-altoona, pa-altoona-nonresident, pa-york, pa-york-nonresident, pa-wilkes-barre, pa-wilkes-barre-nonresident, pa-state-college, pa-state-college-nonresident, pa-norristown, pa-norristown-nonresident, pa-west-chester, pa-west-chester-nonresident, pa-cheltenham, pa-cheltenham-nonresident, pa-upper-darby, pa-bensalem, pa-abington, pa-millcreek, pa-bristol-township, pa-ross-township, pa-mount-lebanon, oh-toledo, oh-akron, oh-dayton, oh-canton, oh-springfield, oh-kettering, oh-parma, oh-lorain, oh-hamilton, oh-euclid, oh-cuyahoga-falls, oh-middletown, oh-mansfield, oh-lakewood, mo-st-louis, ky-bowling-greennoA local wage tax — a city, county, township or borough — to add on top of the state line, where Far Better Off models one. Omit it and every "local" field comes back null, which means not asked rather than none — read "localitiesAvailable" for what this state offers. The locality must sit in "state"; a mismatch is a 400 rather than a silent swap.
schoolDistrictone of 214 Ohio school district ids (oh-sd-2301-amanda-clearcreek), or the four-digit district code from box 20 of your W-2 (2301) — the list is in "schoolDistrictsAvailable" on any answer for state=OHnoOhio's school district income tax, which is a second local levy on the same paycheck and the only one here charged by where you live rather than where you work — so it is owed on top of "locality" and not instead of it. All 214 districts that levy one for 2026 are accepted, by id or by the four-digit code from box 20 of your W-2 ("2301"), which is the only reliable way to match one: a district's boundaries are not a city's, a township's or a ZIP code's, so a bare name is deliberately not a spelling. Omit it and every "schoolDistrict" field comes back null, which means not asked rather than none — read "schoolDistrictsAvailable" for what this state offers. The district must sit in "state"; a mismatch is a 400 rather than a silent swap.
localExemptionsnumber, between 0 and 20no, defaults to 0Personal and dependency exemptions to claim against the locality's tax, as a head count — the filer, a spouse, each dependent. Only Michigan's 40 rates allow any of the localities modelled ($600 a head in Detroit, Grand Rapids, Lansing, Flint, Pontiac, East Lansing, Highland Park, Muskegon, Big Rapids, Walker, Hamtramck, Muskegon Heights, Albion and Lapeer, and $700 a head in Ionia, and $750 a head in Battle Creek, Saginaw, Benton Harbor and Springfield, and $1000 a head in Portland, read back in "localExemptionAmount"); elsewhere it changes nothing. The default of 0 is the larger bill, so an omitted count never understates a city.

Returns, inside result

state
The USPS code the answer is for.
stateName
The state's full name.
taxability
Which of four cases this state is: "none" (taxes no wages), "flat" (one verified statutory rate), "graduated" (a verified bracket schedule, applied in full — "ratePercent" is null because no single rate describes it) or "unmodeled" (brackets Far Better Off has not verified, where there is no answer).
modeled
True when tax is a number. False only where taxability is "unmodeled".
tax
State income tax on the year's wages, or null where taxability is "unmodeled". Null is not zero.
taxedWages
The wages a rate was applied to: wages minus pretaxRetirement (the whole salary in Pennsylvania), minus standardDeduction where one is modelled, minus ficaDeduction in Massachusetts. 0 where the state taxes no wages at all, null where there is no answer.
standardDeduction
What this state exempts for this filingStatus before its rate applies, where we have verified it. Null usually means not verified, never verified as zero — but in Pennsylvania it means none exists, and in Utah it means the state grants none and hands the federal deduction back as a credit instead (see "credit"). It is what these wages actually got, not a table row: Illinois disallows its exemption allowance outright over $250,000 ($500,000 filing jointly), so a filer above the limit gets 0 with the label still set.
standardDeductionLabel
What the state calls it: "standard deduction", or "personal exemption and standard deduction" in Mississippi, which gives both. Null where none is modelled.
standardDeductionSource
Where the deduction figures were verified, when that isn't the same page as the rate (North Carolina's are in the statute, Kentucky's in a DOR announcement). Null otherwise.
ficaDeduction
What this state takes off for the Social Security and Medicare tax already paid on these wages — Massachusetts's, and null in every other state, where the answer is that no such deduction exists rather than that nobody checked. M.G.L. c. 62, § 3(B)(a)(3) caps it at $2,000 "attributable to any one taxpayer", so every salary over $26,144 gets exactly $2,000 and a smaller one gets the 7.65% it actually paid. It follows the payroll tax rather than the income tax, so pretaxRetirement does not reduce it, and filingStatus does not double it: the second $2,000 belongs to a second earner, whose pay this endpoint was not given. taxedWages already has it subtracted.
ficaDeductionLabel
What the state calls it, or null. Massachusetts: "deduction for the Social Security and Medicare tax you paid".
ficaDeductionSource
Where that cap and what it is taken of were verified. Null in every state that has no such deduction.
filingStatus
The filing status the answer used. Echoed so a cached response is self-describing.
effectiveRatePercent
tax as a percent of gross wages. Lower than ratePercent wherever there is an exempt band.
ratePercent
The statutory rate on wage income, or null — null in a graduated state too, where the answer is a table rather than a rate. Read "rateLabel" for how the state states it, and "effectiveRatePercent" for what these wages actually paid.
marginalRatePercent
The rate this filer's next dollar of wages meets, as a percent — the number that answers "what does a raise cost me here", which effectiveRatePercent and ratePercent both get wrong. 0 in a state that taxes no wages and 0 under a filing threshold or inside an exempt band, the statutory rate in a flat state, the band this income reaches in a graduated one, and null only where taxability is "unmodeled". It can be higher than ratePercent: Massachusetts adds its 4-point surtax above the threshold, and Utah's tapering credit costs another 1.3 cents a dollar while it lasts, so a Utahn inside that taper meets 5.8% and not the 4.5% the state advertises. Clamping this to the statutory rate would be wrong in both states.
marginalBracket
The band marginalRatePercent came from, as { over, ratePercent }, in a state that publishes a schedule. Null in a flat state (ratePercent is the whole answer), in a state that taxes no wages, and under a filing threshold, where no band applies because no tax does.
brackets
This state's own schedule for this filingStatus, as [{ over, ratePercent }] from the first dollar — the table "tax" was worked out from, so a caller can reproduce or display it without a second source. Null in a flat state and where the state taxes no wages. The bands are measured on taxable income: taxedWages less exemptBelow, not on gross wages. A schedule alone does not always reproduce "tax" — read "supplementalTax" in New York, "baseTax" in Ohio and "credit" in Utah.
stateAndLocalMarginalRatePercent
marginalRatePercent plus localMarginalRatePercent: what one more dollar of wages really costs in sub-federal income tax. Null wherever either half is null — an unmodeled state, or no locality asked for — for the same reason stateAndLocalTax is. The two add honestly because every locality modelled taxes a base that a dollar of wages enters: gross pay in Ohio's cities and Philadelphia, federal AGI in Detroit, and state taxable income in New York City and Indiana's counties.
exemptBelow
The slab this state taxes at nothing before its rate starts, after any standardDeduction (Ohio, Mississippi, Idaho). For this filingStatus: Idaho's is $4,811 on a single return and $9,622 on a joint one. Null elsewhere.
noTaxBelow
The filing threshold this state charges nothing at all under, for this filingStatus — Virginia's $11,950 ($23,900 filing jointly) and New Jersey's $10,000 ($20,000 jointly or as head of household). Null in every other state. Unlike exemptBelow this is measured on income before any standardDeduction, and clearing it does not subtract it: a dollar over, the whole schedule applies from the bottom.
belowFilingThreshold
Whether these taxedWages fall under noTaxBelow, so the state charges nothing. The two states disagree about the boundary itself and this answers for each: Virginia's statute says "less than $11,950", so $11,950 exactly is taxed, while New Jersey's says "$10,000 or less ... pay no tax", so $10,000 exactly is not. False in a state with no threshold, null where the state is unmodeled.
baseTax
Flat dollars owed once the exempt band is cleared (Ohio's $332). Null elsewhere.
surtaxPercent
Extra percentage points a state charges above a threshold, on top of ratePercent (Massachusetts: 4). Null in every other state.
surtaxThreshold
The taxable income above which surtaxPercent applies. Massachusetts indexes it annually and does not vary it by filing status, so a couple filing jointly reaches it at the same income a single filer does. Null elsewhere.
surtax
How much of tax came from that top band for these wages — 0 below the threshold, and null in a state that has no surtax. tax already includes it; this is here so ratePercent times taxedWages and our number agree.
surtaxSource
Where the surtax rate and its threshold were verified. Null where there is no surtax.
supplementalTax
How much of tax came from a state taking back the benefit of its own lower brackets — New York's supplemental tax, and nothing else here. 0 below the income where it starts, and null in a state that has no such rule. tax already includes it; this is here so a consumer applying the bracket schedule and our number agree.
supplementalTaxLabel
How the state describes that rule, or null. New York: "New York's supplemental tax, which takes back the lower brackets above $107,650".
supplementalTaxSource
Where those steps were verified. Null where the state has no such rule.
credit
A credit this state takes off the tax itself, for these wages — Utah's taxpayer tax credit, and nothing else here. It is 6% of the federal standard deduction, less 1.3% of income above a base amount, so it falls to 0 around $92,500 of single income. tax already has it subtracted and is floored at zero, so a low earner's credit can be larger than the tax it wiped out. Null in every other state.
creditLabel
What the state calls it, or null. Utah: "taxpayer tax credit".
creditSource
Where the credit's percentages and base amounts were verified. Null elsewhere.
taxesPretaxRetirement
True where 401(k) contributions are taxed as compensation anyway (Pennsylvania).
rateLabel
How the state describes its own rate, in a phrase you can print.
excludes
What this figure leaves out in this state — deductions, exemptions, credits, local taxes. Always read it.
reason
Present only where taxability is "unmodeled": why there is no number.
source
Where this state's figure was verified: { publisher, url, verified?, quote? } on the agency's, legislature's or code's own site. "verified" is an ISO day that citation was last re-opened and found to still say this, and it is absent rather than null where nobody has re-read it — which is not a doubtful rate, only an unrepeated reading. "quote" is the sentence on that page the day was earned on, so you can repeat the check instead of trusting it: fetch the url, strip tags to single spaces, fold curly punctuation to ASCII, and the string is still there. It is absent with no "verified" day, and absent on the two citations that are PDFs, where no substring search can repeat a person's reading. Null only where a rate is confirmed but not yet linked.
taxYear
The tax year the rates come from.
localitiesAvailable
Every local wage tax Far Better Off models in this state, whether a city, county, township or borough levies it, as { id, name, ratePercent, topRatePercent } — the accepted values of "locality" here, so a client can build the picker without a second call. "ratePercent" is null for a locality that publishes a schedule instead of a rate (New York City's four resident brackets), and "topRatePercent" is its highest rate, so a picker always has one number to show. Empty is "none modelled", never "none exists": Indiana's other 84 counties, many Kentucky and Michigan cities and much of Pennsylvania levy one that is not in this table yet, and "excludes" says so.
locality
The locality id the answer used, or null when none was asked for.
localityName
What that locality is called ("Philadelphia (I live in the city)"). Null when none was asked for.
localTax
Local income tax — city, county, township or borough — on the same year of wages, or null when no locality was asked for. Null is not zero, exactly as it is for the state line.
localRatePercent
The locality's rate on wage income, as a percent. Null when none was asked for, and null in New York City, which publishes a schedule rather than a rate — read "localBrackets" and "localMarginalRatePercent" there.
localMarginalRatePercent
The rate on the next dollar of local tax, as a percent — the locality's flat rate everywhere but New York City, and the bracket this filer's city taxable income lands in there. Null when no locality was asked for.
localBrackets
The locality's own schedule for this filing status, as [{ over, ratePercent }] from the first dollar, where it publishes one — New York City only. Null everywhere else, where there is a single "localRatePercent" instead.
localTaxableIncome
What the locality's rate or schedule was applied to, where that is not gross pay: New York City charges its brackets on New York State taxable income and an Indiana county charges its rate on Indiana's, so this is the state's standard deduction or personal exemption already taken off. Null for every locality that taxes gross pay (read "localTax" and "localRatePercent" there) and when none was asked for.
localTaxLabel
How the locality states its own charge, in a phrase you can print ("Philadelphia's 3.735% resident Wage Tax"). Null when none was asked for.
localTaxesPretaxRetirement
True where the locality taxes 401(k) elective deferrals as compensation anyway — true in Ohio's cities, which tax box 5 Medicare wages, and in Philadelphia, which follows the Pennsylvania rule. False in Michigan's 40, whose base is a federal figure the contribution was never in — the AGI on a Detroit resident's return, W-2 box 1 in every other Michigan city here and on a Detroit commuter's. Null when no locality was asked for.
localExemptionAmount
Dollars a year this locality exempts for each personal or dependency exemption, resident and non-resident alike — $600 a head in Detroit, Grand Rapids, Lansing, Flint, Pontiac, East Lansing, Highland Park, Muskegon, Big Rapids, Walker, Hamtramck, Muskegon Heights, Albion and Lapeer, and $700 a head in Ionia, and $750 a head in Battle Creek, Saginaw, Benton Harbor and Springfield, and $1000 a head in Portland. Each is the figure that city prints on its own return rather than one the state sets: the Uniform City Income Tax Ordinance caps the rate and says nothing about the exemption, which is why Battle Creek's is the largest of them. Null where the locality allows none, which is every locality outside Michigan, and null when no locality was asked for. Null here is "the city taxes the first dollar", not "unverified".
localExemptionsApplied
The exemption count actually used, which is 0 wherever the locality allows none however many you asked for. Null when no locality was asked for.
localExcludes
What the local figure leaves out — a second Ohio municipality's tax net of credit, Philadelphia's income-based refund. Always read it. Null when no locality was asked for.
localSource
Where the locality's rate was verified: { publisher, url } on the city's own revenue page. Null when no locality was asked for.
schoolDistrictsAvailable
Every school district income tax Far Better Off models in this state, as { id, code, name, ratePercent, base } — the accepted values of "schoolDistrict", so a client can build the second picker without a second call. "code" is the four-digit number box 20 of a W-2 carries, which is the field to match a reader against; "base" is "wages" or "state taxable income", and both appear in Ohio, which is why one rate is two bills. Empty in 50 of the 51 jurisdictions, and that is "none modelled", never "none exists": Pennsylvania's school districts levy an earned income tax of their own, which rides inside the Act 32 rates in "localitiesAvailable" rather than as rows here.
schoolDistrict
The school district id the answer used, or null when none was asked for.
schoolDistrictName
What that district is called, with its four-digit code ("Westerville City School District (2512)"). Null when none was asked for.
schoolDistrictCode
The four-digit code alone, so a client can show it against box 20 of the reader's own W-2 without parsing the name. Null when no district was asked for.
schoolDistrictTax
Ohio school district income tax on the same year of wages, or null when no district was asked for. Null is not zero, exactly as it is for the state and local lines. It is charged on where the reader lives, so it is owed on top of localTax, which is charged on where they work — a Westerville resident working in Columbus owes both.
schoolDistrictRatePercent
The district's rate on its own base, as a percent. Every district modelled charges one flat rate — none publishes a schedule — so unlike localRatePercent this is never null for a district that was asked for.
schoolDistrictBase
Which of the two bases Ohio Revised Code 5748.01(E) lets a district choose this one is on: "wages" for the earned income base, division (E)(2), which is wages with no deduction and no exemption, or "state taxable income" for the traditional base, division (E)(1), which is Form SD 100 line 5 — modified adjusted gross income less the Ohio IT 1040 exemption. It is the field that explains why one rate is two bills: 1% is $750 on the earned income base and $729 on the traditional one for a single filer on $75,000, and $708 filing jointly, because the traditional base takes two of Ohio's exemptions and the earned income base has no filing status at all. Null when no district was asked for.
schoolDistrictTaxableIncome
What the district's rate was applied to, where that is not gross pay — the Ohio taxable income a traditional-base district charges. Ohio's $26,050 zero band and its $332 of flat dollars are not in it: they belong to the state's own schedule, which is why $28,400 of wages can owe Ohio nothing and owe a 1% district $260.50. Null for an earned income district, where the answer is "wages", and null when none was asked for.
schoolDistrictTaxLabel
How the district states its own charge, in a phrase you can print ("Westerville City School District's 0.75% income tax"). Null when none was asked for.
schoolDistrictTaxesPretaxRetirement
False for every district modelled, and it is the one local line in Ohio where that is true: a municipal tax here reaches "qualifying wages" — box 5 Medicare wages, which an elective deferral is still inside — while both school district bases are built on federal adjusted gross income, which it was never in. So on one Ohio payslip a 5% deferral leaves Columbus at $1,875 and takes Westerville from $562.50 to $534.38. Null when no district was asked for.
schoolDistrictExcludes
What the district figure leaves out — self-employment earnings on the earned income base, every non-wage dollar of modified adjusted gross income on the traditional one, Ohio's dependency exemptions, and the SD 100's $50 senior citizen credit. Always read it. Null when none was asked for.
schoolDistrictSource
Where the district's rate and its base were verified: { publisher, url } on the Ohio Department of Taxation's own employer-withholding list. Null when none was asked for.
schoolDistrictTaxYear
The year the district rates are in force for. Ohio's list is dated by the day employers must use it — 1 January — rather than by a tax year, so it is stated separately from taxYear above. Null when no district was asked for.
stateAndLocalTax
Every sub-federal income tax line on this salary added up: "tax" plus "localTax" plus "schoolDistrictTax", which is the number a person here actually loses. Null wherever any half asked for is null — an unmodeled state, or no locality and no district asked for — because a sum missing a term is not a total. A term nobody asked for is not missing: with "locality" alone this is tax plus localTax, as it always was, and the district only enters it when a district was named.
payrollContributions
What this state withholds from the employee's own wages for a named state programme in a year — disability insurance, paid family and medical leave, and in New Jersey unemployment insurance too. It is not income tax, so no rate above can show it, and it is often the larger deduction: California's SDI takes 1.3% of every dollar earned, $975 a year on $75,000, where the state income tax on the same salary is under 4%. Charged on gross wages, so pretaxRetirement does not reduce it — a 401(k) deferral escapes the income tax and not this. Null where Far Better Off has verified no such contribution, which is not zero: Delaware's Paid Leave and Maryland's FAMLI both belong here and neither rate has been read off its agency's page yet.
payrollContributionLabel
The line a pay stub shows, in a phrase you can print ("California SDI", "Washington PFML + WA Cares"). Null where none is modelled.
payrollContributionDescription
The same thing in running text, for a sentence rather than a table cell ("State Disability Insurance"). Null where none is modelled.
payrollContributionRatePercent
Every programme's employee rate added up, as a percent. Read it with "payrollContributionPrograms": the sum describes a salary under the lowest wage base and no other, because New Jersey's four rates stop at two different ceilings — Unemployment Insurance and workforce development at $44,800 — so above that the real charge is less than this figure states. Null where none is modelled.
payrollContributionMarginalRatePercent
The rate the next dollar of wages meets in contributions, as a percent — the figure to add to marginalRatePercent when answering what a raise costs. It is 0 once every wage base is passed (a Rhode Islander over $100,000 pays no more Temporary Disability Insurance however big the raise), the whole rate below the lowest base, and in between it is neither: a New Jerseyan over $44,800 meets 0.42% of the 0.845% the rate above sums, because Unemployment Insurance has stopped charging and disability and family leave have not. Null where none is modelled.
payrollContributionPrograms
The programmes behind the total, in the order a pay stub lists them, as [{ name, short, ratePercent, wageBase, chargedWages, amount }]. "wageBase" is null where the programme charges every dollar — California removed SDI's ceiling on 1 January 2024 and WA Cares never had one — and "chargedWages" is what the rate actually met, so a base that has bitten is visible rather than inferred. Null where none is modelled.
payrollContributionYear
The calendar year these rates are in force for. They turn over on 1 January, unlike the income tax rates above, which are stated for a tax year. Null where none is modelled.
payrollContributionExcludes
What the contribution figure leaves out or assumes, in the state's own terms — an employer that volunteers to pay more of your share, a private plan that withholds instead, a WA Cares exemption, a rate already legislated to move next January. Always read it. Null where none is modelled.
payrollContributionSource
Where each rate and wage base was verified: { publisher, url } on the labor or paid-leave agency's own page. Null where none is modelled.
stateTaxAndContributions
Everything the state itself takes out of this salary: "tax" plus "payrollContributions". Null wherever either half is null — an unmodeled state, or one with no verified contribution — for the same reason "stateAndLocalTax" is null without a locality: a sum missing a term is not a total. It excludes any locality; add "localTax" for the whole sub-federal bill.
  • Wage income only, and 29 of the 51 jurisdictions get a number: 9 that levy no individual income tax on wages, 16 that charge one statutory rate (3 of those after a zero band), and California, New Jersey, New York and Virginia, whose own published bracket schedule is applied in full. For the other 22, "tax" is null and "taxability" is "unmodeled". Far Better Off will not guess at a bracket table it has not read off the state's own forms — so treat null as "no answer", never as zero.
  • Where a state's own standard deduction has been verified it is applied, by filingStatus, and returned in "standardDeduction" with its citation — Arizona, Colorado, Georgia, Idaho, Illinois, Indiana, Iowa, Kentucky, Louisiana, Massachusetts, Michigan, Mississippi, North Carolina and Ohio so far, and in Iowa and Idaho that deduction is the federal one, because both start from the federal figures rather than from your wages. In Illinois it stops above $250,000 ($500,000 filing jointly), and in Ohio it steps down at $40,000 and again at $80,000 of wages and stops above $500,000, as each state's own rule does — so "standardDeduction" is what this filer actually gets, not what the statute's headline figure says. Every other flat-rate state's own rule is settled too rather than left out: Pennsylvania grants none, and Utah gives the federal deduction back as a credit ("credit") instead. In the graduated states the figure still leaves out personal exemptions and credits, so those filers owe less. County and municipal income taxes are never included, so in Indiana, Kentucky, Michigan, Ohio and much of Pennsylvania the real total is higher. The per-state "excludes" field says which of those apply.
  • Pennsylvania is the one state here that taxes 401(k) elective deferrals as compensation, so its 3.07% applies to the whole salary. Everywhere else the rate is applied to wages minus pretaxRetirement.
  • Utah is the one state here that gives back a credit instead of a deduction, so "standardDeduction" is null there and "ratePercent" times "taxedWages" overstates the bill: 4.5% on every dollar, less a taxpayer tax credit of 6% of the federal standard deduction that shrinks by 1.3¢ for each dollar of income above $18,213 single, $36,426 filing jointly and $27,320 head of household (the 2025 schedule, indexed annually). Two things follow that a flat rate hides — a single Utahn owes nothing below about $20,700, and between there and about $92,500 each extra dollar really meets 5.8%, not 4.5%. The dollars are in "credit".
  • Massachusetts is the one state here with a second rate at the top, so "ratePercent" alone does not reproduce "tax" there for a very high earner: 5% on wage income after the personal exemption, plus 4 points more on taxable income above $1,107,750 in 2026 ("surtaxPercent" and "surtaxThreshold", with the dollars in "surtax"). The threshold is indexed for inflation each year and is the same whatever your filing status. Below it Massachusetts is flat, and "surtax" comes back as 0.
  • 2026 rates, each cited to the state's own revenue department, constitution or code. The citation comes back in the "source" field of every answer, and the whole table is readable at /state-income-tax-rates. Michigan's rate, for instance, is re-determined each April and stayed at 4.25% for 2026.
  • Local income tax is answered where it has been verified and nowhere else. Pass "locality" for one of the rates modelled — Cincinnati 1.8%, Cleveland 2.5%, Columbus 2.5%, Philadelphia 3.735%, Philadelphia 3.425% for a non-resident who works there, Detroit 2.4%, New York City 3.078%–3.876%, Indianapolis (Marion County) 2.02%, Fort Wayne (Allen County) 1.59%, Gary and Hammond (Lake County) 1.5%, Carmel and Fishers (Hamilton County) 1.1%, South Bend (St. Joseph County) 1.75%, Evansville (Vanderburgh County) 1.25%, Lafayette (Tippecanoe County) 1.28%, Bloomington (Monroe County) 2.14%, Louisville 2.2%, Louisville 1.45% for a non-resident who works there, Lexington 2.75%, Lexington 2.25% for a non-resident who works there, Detroit 1.2% for a non-resident who works there, Grand Rapids 1.5%, Grand Rapids 0.75% for a non-resident who works there, Lansing 1%, Lansing 0.5% for a non-resident who works there, Flint 1%, Flint 0.5% for a non-resident who works there, Pontiac 1%, Pontiac 0.5% for a non-resident who works there, East Lansing 1%, East Lansing 0.5% for a non-resident who works there, Battle Creek 1%, Battle Creek 0.5% for a non-resident who works there, Saginaw 1.5%, Saginaw 0.75% for a non-resident who works there, Highland Park 2%, Highland Park 1% for a non-resident who works there, Muskegon 1%, Muskegon 0.5% for a non-resident who works there, Big Rapids 1%, Big Rapids 0.5% for a non-resident who works there, Walker 1%, Walker 0.5% for a non-resident who works there, Hamtramck 1%, Hamtramck 0.5% for a non-resident who works there, Muskegon Heights 1%, Muskegon Heights 0.5% for a non-resident who works there, Portland 1%, Portland 0.5% for a non-resident who works there, Benton Harbor 1%, Benton Harbor 0.5% for a non-resident who works there, Albion 1%, Albion 0.5% for a non-resident who works there, Ionia 1%, Ionia 0.5% for a non-resident who works there, Lapeer 1%, Lapeer 0.5% for a non-resident who works there, Springfield 1%, Springfield 0.5% for a non-resident who works there, Pittsburgh 3%, Pittsburgh 1% for a non-resident who works there, Allentown 1.975%, Allentown 1.28% for a non-resident who works there, Reading 3.6%, Reading 1% for a non-resident who works there, Erie 1.65%, Erie 1.65% for a non-resident who works there, Scranton 3.4%, Scranton 1% for a non-resident who works there, Bethlehem 1%, Bethlehem 1% for a non-resident who works there, Lancaster 1.6%, Lancaster 1% for a non-resident who works there, Harrisburg 2%, Harrisburg 1% for a non-resident who works there, Altoona 1.7%, Altoona 1.4% for a non-resident who works there, York 1.25%, York 1.25% for a non-resident who works there, Wilkes-Barre 3%, Wilkes-Barre 1% for a non-resident who works there, State College Borough 2.25%, State College Borough 1% for a non-resident who works there, Norristown Borough 2.1%, Norristown Borough 1% for a non-resident who works there, West Chester Borough 1.25%, West Chester Borough 1% for a non-resident who works there, Cheltenham Township 1.5%, Cheltenham Township 1% for a non-resident who works there, Upper Darby Township 1%, Bensalem Township 1%, Abington Township 1%, Millcreek Township 1%, Bristol Township 0.5%, Ross Township 1%, Mount Lebanon Township 1.3%, Toledo 2.5%, Akron 2.5%, Dayton 2.5%, Canton 2.5%, Springfield 2.4%, Kettering 2.25%, Parma 2.5%, Lorain 2.5%, Hamilton 2%, Euclid 2.85%, Cuyahoga Falls 2%, Middletown 2%, Mansfield 2.25%, Lakewood 1.5%, St. Louis 1% and Bowling Green 2% — and the answer comes back in "localTax", with "stateAndLocalTax" for the two lines together. "localitiesAvailable" lists what each state offers. They do not share a base, and the answer says which one it used rather than leaving you to assume: Ohio's cities and Philadelphia charge their rate on gross pay with no deduction and no exemption, so a 401(k) contribution does not reduce them ("localTaxesPretaxRetirement" is true), while Michigan's cities charge theirs on a federal wage figure the contribution was never in — the AGI on a Detroit resident's return, W-2 box 1 in every other city there — and each allows an exemption of its own ($600 a head in Detroit, Grand Rapids, Lansing, Flint, Pontiac, East Lansing, Highland Park, Muskegon, Big Rapids, Walker, Hamtramck, Muskegon Heights, Albion and Lapeer, and $700 a head in Ionia, and $750 a head in Battle Creek, Saginaw, Benton Harbor and Springfield, and $1000 a head in Portland), so a contribution does reduce all 40 of those rates and "localExemptions" is worth passing. New York City is the third base and the only locality here with a schedule rather than a rate: four resident brackets from 3.078% to 3.876% charged on New York State taxable income, so "localRatePercent" is null there and "localBrackets", "localMarginalRatePercent" and "localTaxableIncome" are how the answer is reproduced — and "status" changes it, because the state's standard deduction and the city's brackets both follow the filing status. Indiana's counties are the fourth base and the first to reuse one: eight of them charge a single rate on the same Indiana taxable income the state taxes, so "localRatePercent" and "localTaxableIncome" are both filled in and a 401(k) reduces the county line too. St. Louis is the fifth base and the first in a state this API cannot compute: its 1% earnings tax reaches a published list of compensation items — salaries, wages, bonuses, commissions, tips and severance — with deferred compensation and cafeteria plans on the city's own non-taxable list, so a 401(k) reduces it, there is no deduction or exemption to pass, and Missouri's own schedule is not modelled, which is why "tax" is null there and "stateAndLocalTax" is null with it. What is still missing is missing for the same reason the rest took this long, and Kansas City is the clearest case of it: its Code of Ordinances imposes the same 1% on residents' earnings and on work done in the city, but the RD-109 instructions that would settle whether a 401(k) deferral is inside that figure are served by a host that refuses every automated read, so the rate is absent rather than copied off a page the city does not publish. It will not be guessed at.
  • Ohio asks the local question twice, so this endpoint takes two local parameters and adds both. A municipal tax follows the work ("locality"); the school district income tax follows the home ("schoolDistrict"), and all 214 districts that levy one for 2026 are answered — so a Westerville resident working in Columbus owes Columbus's 2.5% on the work and Westerville City School District's 0.75% on the residence, and a request naming only one of them is short by the other. Name a district by its id or by the four-digit code on box 20 of the reader's own W-2, which is the only reliable way to match one: a district's boundaries are not a city's, so a bare name is deliberately not a spelling and "schoolDistrictsAvailable" carries the code beside every row. Ohio Revised Code 5748.01(E) lets a district choose one of two bases and they are not interchangeable, which is why "schoolDistrictBase" is in every answer: 68 charge their rate on wages with no deduction and no exemption, and 146 charge it on Ohio taxable income — Form SD 100 line 5, the state's personal exemption already off — so 1% of $75,000 is $750 in one and $729 in the other, and $708 filing jointly. Two things that follow surprise people: the state's $26,050 zero band and its $332 of flat dollars stay with the state, so $28,400 of wages owes Ohio nothing and owes a 1% district $260.50; and a 401(k) deferral reduces a district line and no Ohio city line, because both district bases are built on federal adjusted gross income and a municipal tax reaches box 5 Medicare wages.
  • Two rates come back, and they answer different questions. "effectiveRatePercent" is what this year cost; "marginalRatePercent" is what the next dollar costs, with the band it came from in "marginalBracket" and the whole schedule in "brackets". Do not clamp the marginal rate to "ratePercent": it is legitimately higher in Massachusetts above the surtax threshold, and in Utah, where a tapering credit takes 1.3 cents of every dollar between about $20,700 and $92,500 of single income, so the real rate on a raise there is 5.8% against an advertised 4.5%. Where a locality is asked for, "stateAndLocalMarginalRatePercent" adds the two.
  • Income tax is not the only thing a state takes out of a paycheck, and in 10 of them the second line is answered here too: "payrollContributions" is the disability, paid-leave and — in New Jersey alone — unemployment contribution withheld from the worker's own wages, with the programmes behind it in "payrollContributionPrograms" and the two lines added in "stateTaxAndContributions". It behaves like FICA and not like the tax above: charged on gross pay, so a 401(k) deferral does not reduce it, with a per-programme wage base rather than a deduction or a filing status. Washington's two contributions are the clearest case of why this cannot be folded into a rate — the state levies no income tax at all and still takes the most of any state here. Where nothing has been verified the field is null and not zero: Delaware's Paid Leave and Maryland's FAMLI belong in that table and are not in it yet, and New York's disability benefits contribution and Hawaii's TDI are left out because the law lets an employer pay them instead of setting the worker's share.
  • This is the state line only unless you ask for a locality. For the federal side — brackets, FICA and take-home pay — call /api/v1/paycheck and subtract this number.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/state-tax?state=OH&wages=75000&pretaxRetirement=3750&locality=oh-columbus&schoolDistrict=2514

Share https://farbetteroff.com/api?try=state-tax&state=OH&wages=75000&pretaxRetirement=3750&locality=oh-columbus&schoolDistrict=2514#state-tax

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/state-tax?state=OH&wages=75000&pretaxRetirement=3750&locality=oh-columbus&schoolDistrict=2514"

get/api/v1/loan

Loan payment & amortization

Monthly payment, total interest and the year-by-year schedule for any fixed-rate amortizing loan — mortgage, auto, student or personal.

Parameters

NameAcceptsRequiredDescription
principalnumber, US dollars, between 0 and 100000000000yesAmount borrowed.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesAnnual interest rate (APR).
termMonthsinteger, whole months, between 1 and 1200yesLength of the loan in months. A 30-year mortgage is 360.
extraMonthlynumber, US dollars, between 0 and 1000000000no, defaults to 0Extra principal paid on top of the scheduled payment each month.
schedulebooleanno, defaults to falseInclude the year-by-year amortization schedule in the response.

Returns, inside result

payment
Scheduled monthly payment (principal and interest only).
months
Months until the loan is paid off, after any extra principal.
termLabel
That payoff time in words, e.g. "24 yr 11 mo".
totalInterest
Interest paid over the life of the loan.
totalPaid
Principal plus interest.
extraPayment
Present only when extraMonthly > 0: months and interest saved against the original schedule.
schedule
Present only when schedule=true: one row per year with principal paid, interest paid and closing balance.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/loan?principal=300000&rate=6.5&termMonths=360&extraMonthly=200

Share https://farbetteroff.com/api?try=loan&principal=300000&rate=6.5&termMonths=360&extraMonthly=200#loan

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/loan?principal=300000&rate=6.5&termMonths=360&extraMonthly=200"

get/api/v1/mortgage

Mortgage payment (PITI)

The whole monthly payment on a home loan — principal, interest, property tax, insurance, HOA and PMI — not just principal and interest.

Parameters

NameAcceptsRequiredDescription
homePricenumber, US dollars, between 0 and 10000000000yesPurchase price.
downPaymentnumber, US dollars, between 0 and 10000000000no, defaults to 0Down payment in dollars.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesAnnual interest rate (APR).
termYearsinteger, years, between 1 and 50no, defaults to 30Loan term in years.
propertyTaxAnnualnumber, US dollars, between 0 and 10000000no, defaults to 0Property tax per year.
insuranceAnnualnumber, US dollars, between 0 and 10000000no, defaults to 0Homeowner's insurance per year.
hoaMonthlynumber, US dollars, between 0 and 1000000no, defaults to 0HOA dues per month.
pmiRatenumber, a percentage, so 6.5 means 6.5%, between 0 and 5no, defaults to 0.5Annual PMI premium as a percentage of the loan. Only charged below 20% down. Freddie Mac puts a typical premium at $30–$70 a month per $100,000 borrowed, which is 0.36%–0.84% of the loan a year.
extraMonthlynumber, US dollars, between 0 and 10000000no, defaults to 0Extra principal per month.

Returns, inside result

loanAmount
Home price minus the down payment.
downPaymentPercent
Down payment as a percentage of the price.
principalAndInterest
The loan payment alone.
monthlyTotal
Everything due each month, including any extra principal.
breakdown
Each component of the monthly total, in dollars.
totalInterest
Interest over the life of the loan, after any extra principal.
payoffMonths
Months to payoff.
payoffTermLabel
That payoff time in words, e.g. "30 yr" or "24 yr 11 mo".
pmi
Null when no PMI is charged. Otherwise the month it drops off automatically, the earlier month you may request cancellation, and what it costs either way.
  • PMI termination follows the Homeowners Protection Act as summarised by the CFPB: automatic at 78% of the original value, or the amortization midpoint as a backstop; borrower-requested at 80%.
  • Property tax and insurance are whatever you pass in — Far Better Off does not look up local rates.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/mortgage?homePrice=400000&downPayment=80000&rate=6.5&termYears=30&propertyTaxAnnual=3600&insuranceAnnual=1800

Share https://farbetteroff.com/api?try=mortgage&homePrice=400000&downPayment=80000&rate=6.5&termYears=30&propertyTaxAnnual=3600&insuranceAnnual=1800#mortgage

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/mortgage?homePrice=400000&downPayment=80000&rate=6.5&termYears=30&propertyTaxAnnual=3600&insuranceAnnual=1800"

get/api/v1/house-affordability

How much house can I afford

The highest home price whose whole payment fits inside a lender's two debt-to-income ratios — answered at the 28/36 convention and at both of FHA's manual-underwriting thresholds.

Parameters

NameAcceptsRequiredDescription
incomenumber, US dollars, between 1 and 100000000yesGross household income per year, before tax. Annual, not monthly — the ratios below are applied to a twelfth of it.
monthlyDebtsnumber, US dollars, between 0 and 1000000no, defaults to 0Required monthly payments on everything that is not housing — car, student loans, credit-card minimums, alimony and child support. Groceries, utilities and phone bills are not debt and do not belong here.
downPaymentnumber, US dollars, between 0 and 100000000no, defaults to 0Cash going in. It raises the price you can reach and is not borrowed.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesMortgage APR you expect to be offered.
termYearsinteger, years, between 1 and 50no, defaults to 30Loan term in years.
propertyTaxRatePctnumber, a percentage, so 6.5 means 6.5%, between 0 and 10no, defaults to 0.89Annual property tax as a percent of the home's price. Defaults to the US average effective rate; county rates run from about 0.3% to over 2%, so last year's bill divided by the price is the number to send.
insuranceAnnualnumber, US dollars, between 0 and 1000000noYour own annual homeowners premium, if you have a quote. Leave it out and the premium is read off the measured curve described in the notes, which re-prices at every home price the search tries.
pmiRatePctnumber, a percentage, so 6.5 means 6.5%, between 0 and 5no, defaults to 0.5Annual PMI as a percent of the loan, charged only where the answer lands above 80% loan-to-value. Defaults to 0.5%, mid-range for the $30–$70 a month per $100,000 borrowed Freddie Mac describes. Send pmiRatePct=0 for a payment with no mortgage insurance in it — the right call for a VA loan, or where you are solving the lender's PITI rather than what underwriting measures.

Returns, inside result

maxPrice
The highest home price whose full payment fits both ratios, under the 28/36 rule.
loanAmount
What has to be borrowed at that price.
downPaymentPercent
The down payment as a percent of that price.
incomeMultiple
The price as a multiple of gross annual income — the figure the “3 to 4 times income” rule of thumb is about.
monthlyBudget
The housing budget that binds: the lower of the two below.
frontEndBudget
Housing alone, under the front-end ratio.
backEndBudget
What is left for housing under the back-end ratio, after the other debts.
limitedBy
"income" when the front-end ratio is the ceiling, "debts" when the other payments are — the one field that says what to do about the answer.
principalAndInterest
The mortgage payment itself at that price.
monthlyTax
Estimated property tax per month at that price.
monthlyInsurance
Estimated homeowners insurance per month at that price.
monthlyPmi
Mortgage insurance per month at that price, charged above 80% loan-to-value. 0 when pmiApplies is false or pmiRatePct=0 was sent.
totalMonthlyPayment
Principal, interest, tax, insurance and mortgage insurance — the whole housing payment, which is the figure the ratios are measured against (Fannie Mae's PITIA).
pmiApplies
True when the down payment lands under 20% of the price, where a conventional loan adds the PMI that is charged in monthlyPmi and in the payment above.
byBenchmark
The same solve at each underwriting benchmark — the 28/36 convention and FHA's two manual-underwriting pairs — each with its ratios, its price, its payment and the authority behind it. Strictest first.
  • The price is found by bisection, not by a formula: property tax and the insurance premium both move with the price being tested, so the price appears on both sides of the constraint. Forty halvings of the range between the down payment and $5,000,000 settle it to well under a cent.
  • The 28/36 pair is a lending convention with no regulation behind it. FHA's 31/43 is a real qualifying ratio for manually underwritten loans — above it the lender must justify in writing why the mortgage is an acceptable risk — and 37/47 needs a documented compensating factor and a decision credit score of 580 or better (HUD Handbook 4000.1 II.A.5.d).
  • PMI is in this payment, and it is inside the ratios rather than on top of them. That is where underwriting puts it: Fannie Mae's monthly housing expense — the numerator of the debt-to-income ratio these benchmarks are about — is principal and interest plus "property, flood, and mortgage insurance premiums (as applicable)" (Selling Guide B3-6-03). So a loan above 80% LTV buys less house, not the same house plus a premium: on income=90000&monthlyDebts=500&downPayment=40000&rate=6.5 the premium is about $107 a month and costs about $14,858 of price. pmiApplies says whether it was charged, monthlyPmi is the figure, pmiRatePct=0 turns it off, and /api/v1/pmi dates its removal. HOA dues, ground rent and closing costs are still not in it, and FHA's mortgage insurance — charged at any down payment, often for the life of the loan — is not modelled.
  • The default property tax rate is 0.89% — the national average effective rate, computed from the US Census Bureau's 2024 American Community Survey, https://data.census.gov/table/ACSDT5Y2024.B25103 — and it is an average across counties that range from about 0.3% to over 2%. Send your own propertyTaxRatePct if you know it; it moves the answer more than anything here except the rate.
  • The default insurance premium is measured rather than assumed, and it is not a flat rate: read off the 2024 American Community Survey 1-year PUMS microdata, where the same household reports both its premium (INSP) and its property value (VALP), the premium rises as roughly the 0.31 power of the price — $1,930 a year at a $400,000 home, about $2,400 at $836,000. A premium is priced on what it costs to rebuild the house, and land cannot burn down. Source: https://www.census.gov/programs-surveys/acs/microdata.html
  • This is what a lender would lend, which is not the same as what is comfortable to spend. The ratios say nothing about childcare, retirement saving or the cost of a roof.
  • Same math as the calculator page: both call houseAffordability in @calcwise/finance, so this answer and https://farbetteroff.com/calculators/how-much-house-can-i-afford cannot disagree.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/house-affordability?income=90000&monthlyDebts=500&downPayment=40000&rate=6.5

Share https://farbetteroff.com/api?try=house-affordability&income=90000&monthlyDebts=500&downPayment=40000&rate=6.5#house-affordability

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/house-affordability?income=90000&monthlyDebts=500&downPayment=40000&rate=6.5"

get/api/v1/rent-affordability

How much rent can I afford

The rent a household can carry on the 30% rule and on a lender's back-end ratio, plus where the answer falls on HUD's cost-burden scale — which counts utilities, and almost nothing else does.

Parameters

NameAcceptsRequiredDescription
incomenumber, US dollars, between 1 and 100000000yesGross household income per year, before tax. Annual, not monthly. Gross rather than take-home, because every rule here is written on gross — the landlord's 3x test included.
monthlyDebtsnumber, US dollars, between 0 and 1000000no, defaults to 0Required monthly payments on everything that is not housing — car, student loans, credit-card minimums, alimony and child support. Groceries, phone and utilities are not debt; utilities have their own parameter below.
monthlyUtilitiesnumber, US dollars, between 0 and 100000no, defaults to 0Electric, gas, water and trash you pay on top of the rent. HUD counts these inside housing cost, so they move costBurdenRent and burdenAtMaxRent — send them or those two answers are optimistic.
sharePctnumber, a percentage, so 6.5 means 6.5%, between 1 and 100no, defaults to 30Share of gross income to target for rent. Defaults to the 30% convention, which is a rule of thumb nobody set — see the notes.
backEndPctnumber, a percentage, so 6.5 means 6.5%, between 1 and 100no, defaults to 36Back-end debt-to-income ratio used as the second ceiling on rent plus all other debt. Defaults to 36, the back-end half of the 28/36 lending convention. byBenchmark answers at every benchmark in the table regardless of what is sent here.
dependentsinteger, between 0 and 20no, defaults to 0Number of dependents. Used only by federalFormula, where each one is a deduction under 24 CFR § 5.611(a)(1). It does not change maxRent — no budgeting rule of thumb accounts for household size.
childcareAnnualnumber, US dollars, between 0 and 1000000no, defaults to 0Reasonable childcare per year needed to work or study. Deductible in full under 24 CFR § 5.611(a)(4), so it enters federalFormula only.
elderlyOrDisabledbooleanno, defaults to falseTrue for an elderly or disabled family, which unlocks the § 5.611(a)(2) deduction and the medical deduction below. federalFormula only.
medicalAnnualnumber, US dollars, between 0 and 1000000no, defaults to 0Unreimbursed health, medical and attendant-care costs per year. Deductible only for an elderly or disabled family, and only above 10 percent of annual income. federalFormula only.

Returns, inside result

maxRent
The answer: the lower of the share rule and the back-end ratio, never negative.
limitedBy
"share" when the percent-of-income rule is the ceiling, "debts" when the other payments are — the field that says what to do about the answer.
grossMonthlyIncome
Gross annual income ÷ 12, which every ratio here divides by.
shareOfIncome
sharePct of gross monthly income — the rule as it is usually applied.
debtAdjusted
Rent the back-end ratio leaves room for once the other debts are paid, floored at zero.
costBurdenRent
The rent at which this household crosses HUD's cost-burden line — 30% of gross less the utility bill, because utilities sit inside HUD's numerator.
severeCostBurdenRent
The same at HUD's severe line, 50% of gross less utilities.
burdenAtMaxRent
"not-burdened", "cost-burdened" or "severely-cost-burdened" — where maxRent plus utilities falls under 24 CFR § 91.5.
landlordMaxRent
Gross monthly income ÷ 3 — the most rent a landlord applying the usual "income must be at least 3x the rent" screen would accept.
leftOver
Gross monthly income less rent, utilities and other debt.
byBenchmark
The rent left over at each real underwriting back-end ratio — the 28/36 convention's 36 and FHA's 43 and 47 — each with the authority behind it. Strictest first.
federalFormula
What 24 CFR § 5.628 would charge this household if it were assisted: 30% of monthly adjusted income or 10% of monthly gross, whichever is higher, with the § 5.611 deductions applied. A different answer to the same 30%.
thresholds
HUD's two cost-burden thresholds and what they measure, verbatim from 24 CFR § 91.5.
  • The 30% rule is a convention, not a rule anyone set. No agency caps what an unassisted renter may pay. The number is borrowed from federal housing policy, where it means two other things — the two paragraphs below — and this endpoint returns all three rather than picking one.
  • HUD's 30% counts utilities, and that is the correction most rent calculators need. 24 CFR § 91.5 defines cost burden as the extent to which “gross housing costs, including utility costs, exceed 30 percent of gross income”, and severe cost burden as the same above 50 percent. A household paying exactly 30% of gross in rent is already cost burdened once the electric bill is counted, which is why monthlyUtilities exists and why costBurdenRent is the threshold less that bill. https://www.ecfr.gov/current/title-24/subtitle-A/part-91/section-91.5
  • The other federal 30% is of adjusted income, with a 10%-of-gross floor underneath it. An assisted household's total tenant payment is the highest of “30 percent of the family's monthly adjusted income” and “10 percent of the family's monthly income” (24 CFR § 5.628(a)), among other amounts. Adjusted income is annual income less the deductions in § 5.611 — dependents, elderly or disabled status, medical costs above 10% of income, and childcare — so it is below gross for any household with children or care costs. Send dependents, childcareAnnual, elderlyOrDisabled and medicalAnnual and federalFormula computes it. https://www.ecfr.gov/current/title-24/subtitle-A/part-5/subpart-F/section-5.628
  • The § 5.611 deduction amounts are the regulation's figures, and HUD raises both every year. $480 per dependent and $525 for an elderly or disabled family are what the CFR prints; each “will be adjusted by HUD annually in accordance with the Consumer Price Index for Urban Wage Earners and Clerical Workers, rounded to the next lowest multiple of $25”. This API does not claim a current-year adjusted amount, so those two are floors — which makes federalFormula.totalTenantPayment at or slightly above what a housing authority would charge, the safe direction to be wrong in for anyone planning a budget.
  • The back-end ceiling is a mortgage ratio applied to rent, and it is labelled as one. 36 is the back-end half of the 28/36 convention; 43 and 47 are FHA's manual-underwriting thresholds, where above 31%/43% the lender must justify in writing why the loan is an acceptable risk and 37%/47% additionally needs a documented compensating factor and a decision credit score of 580 (HUD Handbook 4000.1 II.A.5.d). No regulator sets a back-end ratio for a lease.
  • The 3x-income screen most landlords apply is the same arithmetic as a 33% share, so landlordMaxRent will sit slightly above the 30% answer. It is a screening rule private landlords choose, not law, and it varies by market.
  • Security deposits, first and last month up front, renters insurance, parking and commuting are not in any of these numbers.
  • Same math as the calculator page: both call rentAffordability in @calcwise/finance, so this answer and https://farbetteroff.com/calculators/rent-affordability-calculator cannot disagree.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/rent-affordability?income=60000&monthlyDebts=600&monthlyUtilities=180

Share https://farbetteroff.com/api?try=rent-affordability&income=60000&monthlyDebts=600&monthlyUtilities=180#rent-affordability

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/rent-affordability?income=60000&monthlyDebts=600&monthlyUtilities=180"

get/api/v1/car-affordability

How much car can I afford

The car the 20/4/10 rule leaves room for, with insurance, fuel and upkeep taken out of the ten percent first — from the IRS's own operating allowance for the caller's part of the country, beside what the IRS allows for the payment itself.

Parameters

NameAcceptsRequiredDescription
takeHomenumber, US dollars, between 1 and 10000000yesMonthly pay after tax. Take-home rather than gross, because the rule is written on take-home — sending gross overstates every answer here by roughly a quarter.
downPaymentnumber, US dollars, between 0 and 10000000no, defaults to 0Down payment plus trade-in. It adds to the price directly and is what the rule's 20% leg is measured against.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesAnnual percentage rate on the car loan.
termMonthsinteger, whole months, between 1 and 120no, defaults to 48Loan term in months. Defaults to the rule's 48 — byTerm prices 36, 48, 60 and 72 at the same monthly payment regardless, which is the cheapest way to see what stretching costs.
sharePctnumber, a percentage, so 6.5 means 6.5%, between 1 and 100no, defaults to 10Share of take-home pay for all car costs, payment and running costs together. Defaults to the rule's 10, which is a convention nobody set — see the notes.
areaone of northeast, boston, new-york, philadelphia, midwest, chicago, cleveland, detroit, minneapolis-st-paul, st-louis, south, atlanta, baltimore, dallas-ft-worth, houston, miami, tampa, washington-dc, west, anchorage, denver, honolulu, los-angeles, phoenix, san-diego, san-francisco, seattlenoWhere the car is run, as an IRS area id ("miami", "west"), the label the IRS itself prints ("Washington, D.C.", "West region") or a USPS state code ("tx" or "TX", either case, which resolves to its census region). Picks the IRS operating allowance used for insurance, fuel and upkeep. Omit it and the four regions' mean is used instead, flagged as national-average.
monthlyOperatingCostsnumber, between 0 and 100000noWhat insurance, fuel and upkeep actually cost you each month. Overrides area when sent, and it is the number to send if you know it — the IRS allowance is a ceiling on what a taxpayer may claim, not a measurement of your bills.
carsinteger, between 1 and 2no, defaults to 1How many cars the household runs. Scales both IRS allowances; the table itself only goes to two.

Returns, inside result

maxPrice
The answer: what maxPayment finances over the term, plus the down payment.
maxPayment
What is left of the car budget for the loan payment once running costs are paid — the figure a payment-only calculator would have handed you as the whole ten percent.
totalCarBudget
sharePct of take-home pay: the whole car allowance, payment included.
operatingCosts
Monthly insurance, fuel and upkeep used in the answer.
operatingCostBasis
"provided" when you sent a figure, "irs-area" when it came from the IRS table for area, "national-average" when it is the unweighted mean of the four census regions — which is this API's arithmetic, not an IRS figure.
operatingCostArea
The IRS area the allowance came from, or null.
budgetCoversOperatingCosts
False when running costs alone exhaust the allowance. Not an error: at that income the rule leaves nothing for a payment, however long the loan.
takeHomeForAnyPayment
The monthly take-home pay at which sharePct first covers the running costs — below it, maxPayment is zero.
maxLoan
The loan maxPayment supports over termMonths at rate.
totalInterest
Interest paid over the full term at that payment.
meetsFourYearTerm
False past the rule's second leg, four years.
operatingCostAreaLabel
The area's label as the IRS table prints it ("Miami", "West region"), or null.
termMonths
The term the headline answer was solved over, in months.
twentyPctDown
The rule's first leg, measured rather than enforced: whether the down payment reaches a fifth of maxPrice, the priciest car a fifth of it would cover, and the shortfall.
byTerm
The same monthly payment solved over 36, 48, 60 and 72 months, with the interest each costs and whether it is inside the rule.
irsAllowance
What the IRS treats as a necessary monthly expense for the same car — the ownership (loan or lease) allowance plus the operating allowance — and what that is as a share of your take-home pay. Usually well above what the rule of thumb allows.
rule
The 20/4/10 convention's three legs, and the statement that no agency sets it.
  • The ten percent is all car costs, not the payment. The rule caps the payment together with insurance, fuel, maintenance and registration at 10% of take-home, so this endpoint subtracts running costs from the allowance before solving for a loan. Calculators that solve 10% straight into a payment answer a much looser question — on $4,200 of take-home, $420 a month of payment instead of $124.
  • Running costs default to the IRS's own allowance. The Collection Financial Standards split what a car costs exactly the way this calculation needs: ownership costs of $703 a month for the loan or lease, and operating costs by census region and metropolitan area covering “maintenance, repairs, insurance, fuel, registrations, licenses, inspections, parking and tolls” — $248 in Anchorage to $423 in Miami. Send area to pick one. https://www.irs.gov/businesses/small-businesses-self-employed/local-standards-transportation
  • Those allowances are not advice, and the endpoint does not present them as any. They are what the IRS treats as a necessary living expense when calculating repayment of delinquent taxes — a ceiling on what a taxpayer may claim, derived from Bureau of Labor Statistics expenditure data. A household spending more than the standard is ordinary. They also exclude personal property taxes and say nothing about depreciation.
  • The national average is arithmetic on the table, not a published figure. The IRS prints no nationwide operating cost, so a caller who names no area gets the unweighted mean of the four census-region allowances — $295.75. It is the middle of four government figures, not a population-weighted estimate of what households pay, and operatingCostBasis says so on every response that uses it.
  • 20/4/10 is a convention with no authority behind it. No agency publishes or enforces it. Worth holding beside irsAllowance: the IRS treats about $1,000 a month as necessary for one car, while the rule allows $420 on $4,200 of take-home. Neither is a law; they are two different answers, and this endpoint returns both rather than picking.
  • The first leg is reported, not applied. Enforcing “20% down” would answer $0 for anyone with nothing saved, which is what the rule literally says and is useless as a ceiling to shop against — so maxPrice is the payment answer and twentyPctDown tells you where you stand.
  • maxPrice is the car, not the drive-away cost: sales tax, title, registration and dealer fees are on top, and this endpoint does not model them.
  • Same math as the calculator page: both call carAffordability in @calcwise/finance, so this answer and https://farbetteroff.com/calculators/car-affordability-calculator cannot disagree.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/car-affordability?takeHome=4200&downPayment=4000&rate=7.5&area=tx

Share https://farbetteroff.com/api?try=car-affordability&takeHome=4200&downPayment=4000&rate=7.5&area=tx#car-affordability

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/car-affordability?takeHome=4200&downPayment=4000&rate=7.5&area=tx"

get/api/v1/pmi

PMI termination schedule

When private mortgage insurance comes off a conventional loan — the automatic date, the earlier date you can ask, and what waiting costs.

Parameters

NameAcceptsRequiredDescription
principalnumber, US dollars, between 1 and 10000000000yesOriginal loan amount.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesAnnual interest rate (APR).
termMonthsinteger, whole months, between 1 and 1200yesLoan term in months.
originalValuenumber, US dollars, between 1 and 10000000000yesThe home's original value — the lower of purchase price and original appraised value, which is the figure the rule is measured against.
pmiMonthlynumber, US dollars, between 0 and 100000yesPMI premium per month.
extraMonthlynumber, US dollars, between 0 and 10000000no, defaults to 0Extra principal per month, which brings the automatic date forward.

Returns, inside result

automaticEndMonth
Month PMI must be dropped without you asking.
automaticEndYear
That month expressed in years.
automaticEndLabel
That month in words, e.g. "11 yr 3 mo".
requestableFromMonth
First month you may request cancellation (80% of original value).
endsAtAmortizationMidpoint
True when the midpoint backstop, not the 78% balance, is what ends it.
totalIfAutomatic
Total PMI paid if you wait for automatic termination.
totalIfRequested
Total PMI paid if you request cancellation the first month you can.
savingsFromRequesting
The difference — what asking is worth.
pmi
Present, and null, only when no PMI is charged at all — 20% or more down, so there is nothing to cancel. Every other field is then absent.
reason
Why there is no schedule, on that same no-PMI answer.
  • Source: CFPB, “When can I remove private mortgage insurance (PMI) from my loan?” — https://www.consumerfinance.gov/ask-cfpb/when-can-i-remove-private-mortgage-insurance-pmi-from-my-loan-en-202/
  • Conventional loans only. FHA mortgage insurance follows different rules and is not modelled.
  • Dates are based on the original amortization schedule, which is what the statute uses — not on a new appraisal.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/pmi?principal=190000&rate=6.5&termMonths=360&originalValue=200000&pmiMonthly=79

Share https://farbetteroff.com/api?try=pmi&principal=190000&rate=6.5&termMonths=360&originalValue=200000&pmiMonthly=79#pmi

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/pmi?principal=190000&rate=6.5&termMonths=360&originalValue=200000&pmiMonthly=79"

get/api/v1/debt-to-income

Debt-to-income ratio

Front-end and back-end DTI, residual income, and which of the underwriting benchmarks that actually govern something the result clears.

Parameters

NameAcceptsRequiredDescription
monthlyIncomenumber, US dollars, between 1 and 10000000yesGross monthly income, before tax and deductions. Monthly, not annual — /api/v1/pay converts a salary if you have the yearly figure.
housingnumber, US dollars, between 0 and 1000000yesRent, or the mortgage payment including property tax, insurance, HOA dues and mortgage insurance. This is the front-end ratio on its own.
autoLoansnumber, US dollars, between 0 and 1000000no, defaults to 0Car and other vehicle payments, per month.
studentLoansnumber, US dollars, between 0 and 1000000no, defaults to 0Student loan payments, per month.
creditCardMinimumsnumber, US dollars, between 0 and 1000000no, defaults to 0Minimum payments due, not balances — the ratio is built from payments.
alimonyChildSupportnumber, US dollars, between 0 and 1000000no, defaults to 0Alimony and child support. Counted as debt by 12 CFR 1026.43(c)(7)(i)(A), and the item most often left out.
otherDebtnumber, US dollars, between 0 and 1000000no, defaults to 0Personal loans and any other recurring debt obligation.

Returns, inside result

backEnd
All debt as a percent of gross monthly income — "your DTI".
frontEnd
Housing payment alone, as a percent of gross monthly income.
totalMonthlyDebt
Housing plus every non-housing debt payment.
nonHousingDebt
The non-housing part on its own.
residualIncome
Gross monthly income minus total debt. Negative when debt exceeds income, because that is the case worth seeing.
strictestCleared
The id of the strictest benchmark both ratios clear, or null if none do.
benchmarks
Each benchmark with clearsFrontEnd, clearsBackEnd and clears, plus the source it comes from. Strictest first.
qualifiedMortgage
What replaced the 43% limit, as data rather than prose: thresholdYear, the six tiers in force for it (each with its lien, its loan-amount band as numbers and as a sentence, and the aprSpread over the average prime offer rate at or above which the loan stops being a General QM), the formerDtiLimit with the date it stopped applying, and the citation. Constant — it is the regulation, not an answer about your inputs.
  • Gross income, never take-home. DTI is computed on income before tax because that is what a lender uses; comparing debts to net pay overstates the ratio.
  • What counts as debt is defined, not guessed: 12 CFR 1026.43(c)(7)(i)(A) sums the mortgage payment, simultaneous loans, mortgage-related obligations (property tax, insurance, HOA) and current debt obligations including alimony and child support. Everyday living costs — groceries, utilities, phone — are not in that list and are not in this ratio.
  • 43% is no longer the CFPB's qualified-mortgage limit, and citing it as one is out of date. The CFPB's General QM Final Rule removed the General QM definition's 43% DTI limit and replaced it with price-based thresholds, mandatory from 1 October 2022. The current text of 12 CFR 1026.43 contains no occurrence of "43 percent". The replacement is a price test, and every tier of it comes back in result.qualifiedMortgage: in 2026, a first-lien General QM of $137,958 or more must keep its APR under the average prime offer rate plus 2.25 percentage points, and 5 further tiers cover smaller loans, manufactured homes and subordinate liens — 12 CFR 1026.43(e)(2)(vi).
  • The $110,260 printed in the regulation is not the amount in force, and quoting it is the second-order version of the same mistake. The section prints 2021 base figures and marks them "(indexed for inflation)", then says in as many words to read the official commentary for the current dollar amounts. The Bureau re-indexes them to the CPI-U reported the preceding June and republishes them each December, effective 1 January: the 2026 amounts in qualifiedMortgage.tiers are the ones from 90 FR 57890. meta.dataVintage carries the date the next edition is due.
  • DTI did not stop mattering; it stopped being a bright line. A creditor must still consider and verify the borrower's debt-to-income ratio or residual income under 12 CFR 1026.43(c)(2)(vii) and (c)(7), with no numeric ceiling attached — which is why residualIncome is returned beside the ratios rather than as a nicety.
  • Where 43% does still bind: FHA's qualifying ratios for manually underwritten loans are 31%/43%, and above either the lender must justify in writing why the loan is an acceptable risk. 37%/47% is reachable with a documented compensating factor and a credit score of 580 or better (HUD Handbook 4000.1 II.A.5.d).
  • The 28/36 pair is a lending convention with no regulation behind it, and is labelled convention rather than fha in the response for exactly that reason.
  • A benchmark is cleared only when both ratios are at or under it, and the boundary is inclusive: a back-end ratio of exactly 43.0% clears FHA's, since it is exceeding the ratio that triggers the write-up.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/debt-to-income?monthlyIncome=6000&housing=1600&autoLoans=400&studentLoans=250&creditCardMinimums=150

Share https://farbetteroff.com/api?try=debt-to-income&monthlyIncome=6000&housing=1600&autoLoans=400&studentLoans=250&creditCardMinimums=150#debt-to-income

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/debt-to-income?monthlyIncome=6000&housing=1600&autoLoans=400&studentLoans=250&creditCardMinimums=150"

get/api/v1/credit-card-payoff

Credit card payoff

How long a card balance takes to clear at a fixed monthly payment, and what it costs — including the minimum-payment trap.

Parameters

NameAcceptsRequiredDescription
balancenumber, US dollars, between 0 and 1000000000yesCurrent balance.
aprnumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesAnnual percentage rate.
monthlyPaymentnumber, US dollars, between 0 and 1000000000no, defaults to 0Fixed amount paid each month. Ignored when minimumOnly=true.
minimumOnlybooleanno, defaults to falsePay only the card's minimum each month (1% of the balance plus interest, floor $25) instead of a fixed amount.

Returns, inside result

months
Months to clear the balance. Null when the payment never clears it.
termLabel
That time in words.
totalInterest
Interest paid getting there.
totalPaid
Balance plus interest.
firstPayment
The first month's payment — the useful number under minimumOnly.
neverPaysOff
True when the payment is at or below the monthly interest.
  • The minimum-payment formula (1% of balance plus that month's interest, with a $25 floor) is the common US issuer convention, not a statutory rule. Your card's terms govern.
  • Assumes no new charges and no fees.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/credit-card-payoff?balance=5000&apr=22.8&monthlyPayment=150

Share https://farbetteroff.com/api?try=credit-card-payoff&balance=5000&apr=22.8&monthlyPayment=150#credit-card-payoff

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/credit-card-payoff?balance=5000&apr=22.8&monthlyPayment=150"

get/api/v1/debt-snowball

Debt snowball vs. avalanche

Both payoff orders for up to six debts, run side by side: the queue, the month each debt disappears, the debt-free date and what each method costs in interest.

Parameters

NameAcceptsRequiredDescription
balance1number, US dollars, between 0 and 10000000yesBalance owed on the first debt. Send them in any order — the payoff queue is worked out for you.
apr1number, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual percentage rate on debt 1, e.g. 24.99. This is what the avalanche orders by.
minimum1number, US dollars, between 0 and 1000000no, defaults to 0Minimum payment due on debt 1 each month — the payment, not the balance.
balance2number, US dollars, between 0 and 10000000yesBalance owed on debt 2.
apr2number, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual percentage rate on debt 2, e.g. 24.99. This is what the avalanche orders by.
minimum2number, US dollars, between 0 and 1000000no, defaults to 0Minimum payment due on debt 2 each month — the payment, not the balance.
balance3number, US dollars, between 0 and 10000000no, defaults to 0Balance owed on debt 3. Leave it out or send 0 to skip the slot.
apr3number, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual percentage rate on debt 3, e.g. 24.99. This is what the avalanche orders by.
minimum3number, US dollars, between 0 and 1000000no, defaults to 0Minimum payment due on debt 3 each month — the payment, not the balance.
balance4number, US dollars, between 0 and 10000000no, defaults to 0Balance owed on debt 4. Leave it out or send 0 to skip the slot.
apr4number, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual percentage rate on debt 4, e.g. 24.99. This is what the avalanche orders by.
minimum4number, US dollars, between 0 and 1000000no, defaults to 0Minimum payment due on debt 4 each month — the payment, not the balance.
balance5number, US dollars, between 0 and 10000000no, defaults to 0Balance owed on debt 5. Leave it out or send 0 to skip the slot.
apr5number, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual percentage rate on debt 5, e.g. 24.99. This is what the avalanche orders by.
minimum5number, US dollars, between 0 and 1000000no, defaults to 0Minimum payment due on debt 5 each month — the payment, not the balance.
balance6number, US dollars, between 0 and 10000000no, defaults to 0Balance owed on debt 6. Leave it out or send 0 to skip the slot.
apr6number, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual percentage rate on debt 6, e.g. 24.99. This is what the avalanche orders by.
minimum6number, US dollars, between 0 and 1000000no, defaults to 0Minimum payment due on debt 6 each month — the payment, not the balance.
extranumber, US dollars, between 0 and 1000000no, defaults to 0Everything you can pay above the minimums, per month. This single number decides how fast you are free; the method only decides the order.

Returns, inside result

debtCount
How many slots carried a balance and were simulated.
startBalance
Everything owed today.
minimums
The minimum payments added up.
monthlyBudget
Minimums plus extra — the same under both methods, which is what makes the comparison fair.
cheaper
"avalanche", or null when both orders come out identical. Never "snowball": highest-rate-first is optimal for total interest.
interestSaved
Interest the cheaper order saves. Zero when the two orders agree.
monthsSaved
Months the cheaper order saves. Often zero even when the interest differs.
sameOrder
True when both methods pick the same queue, so the two plans are one plan.
avalanche
The highest-rate-first plan: months, termLabel, totalInterest, totalPaid, firstDebtGoneMonth, neverPaysOff, and order — one row per debt with its rank, payoff month and interest.
snowball
The smallest-balance-first plan, in the same shape.
  • Both methods pay every minimum every month and throw everything left at one debt, then roll a cleared debt's minimum onto the next one. The monthly payment is identical; only the order differs. That is why the two plans can be compared at all.
  • The avalanche (highest rate first) is never slower or more expensive — it kills the costliest interest first. The snowball (smallest balance first) clears a whole debt sooner, which is what firstDebtGoneMonth is for. The CFPB describes both and crowns neither, because the plan you actually finish is the one that works: https://www.consumerfinance.gov/about-us/blog/how-reduce-your-debt/
  • Debts are slots, not a list: balance1 … balance6, each with its own apr and minimum. A slot with a zero balance is ignored, so you can send a fixed set of six and leave the unused ones empty. Debts are returned named for the slot they came in on.
  • Interest is charged monthly on the remaining balance at apr/12, which is how a credit-card statement behaves. Minimums are held constant rather than shrinking with the balance, which is how most people actually pay.
  • Assumes the rates and minimums stay put, no new debt is added, and the whole monthlyBudget keeps being paid even as debts disappear. Stop rolling the freed-up minimums forward and the real payoff stretches out by months.
  • When the payment does not outrun the interest the balances grow forever: months is null and neverPaysOff is true rather than a 600-month answer being invented. Anything past 50 years is reported the same way.
  • Ties are broken on the other measure, so the queue never depends on the order the debts were sent in: two debts at the same rate are ordered smallest balance first, two at the same balance highest rate first.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/debt-snowball?balance1=6200&apr1=24.99&minimum1=155&balance2=2100&apr2=6.5&minimum2=95&balance3=11500&apr3=18.9&minimum3=260&extra=200

Share https://farbetteroff.com/api?try=debt-snowball&balance1=6200&apr1=24.99&minimum1=155&balance2=2100&apr2=6.5&minimum2=95&balance3=11500&apr3=18.9&minimum3=260&extra=200#debt-snowball

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/debt-snowball?balance1=6200&apr1=24.99&minimum1=155&balance2=2100&apr2=6.5&minimum2=95&balance3=11500&apr3=18.9&minimum3=260&extra=200"

get/api/v1/compound-interest

Compound interest

What a balance grows to with regular contributions, split into what you put in and what compounding added.

Parameters

NameAcceptsRequiredDescription
principalnumber, US dollars, between 0 and 1000000000000yesStarting balance.
contributionnumber, US dollars, between 0 and 1000000000no, defaults to 0Added at the end of every compounding period.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesNominal annual return.
yearsinteger, years, between 0 and 100yesHow long to run it.
periodsPerYearinteger, a count, between 1 and 365no, defaults to 12Compounding periods per year. 12 is monthly, 1 is annual.
seriesbooleanno, defaults to falseInclude the year-by-year balance series.

Returns, inside result

balance
Final balance.
contributed
Principal plus every contribution.
growth
Balance minus contributed — what the compounding did.
series
Present only when series=true: balance, contributed and growth for each year.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/compound-interest?principal=10000&contribution=500&rate=7&years=25

Share https://farbetteroff.com/api?try=compound-interest&principal=10000&contribution=500&rate=7&years=25#compound-interest

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/compound-interest?principal=10000&contribution=500&rate=7&years=25"

get/api/v1/savings-goal

Savings goal

Both halves of a savings target: how long a monthly deposit takes to get there, and what deposit hits a deadline exactly.

Parameters

NameAcceptsRequiredDescription
goalnumber, US dollars, between 0 and 1000000000000yesThe amount you are aiming at.
currentnumber, US dollars, between 0 and 1000000000000no, defaults to 0What you have saved already.
monthlynumber, US dollars, between 0 and 1000000000no, defaults to 0What you put in each month. Drives the time-to-goal answer.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 0Annual return or APY on the savings.
deadlineYearsnumber, years, between 0 and 100no, defaults to 0Optional deadline. When above 0, the response also says what monthly deposit lands on the goal exactly then.

Returns, inside result

reached
Whether monthly gets there within 100 years.
months
Months to the goal at monthly. Null if it never arrives.
termLabel
That time in words.
balanceAtGoal
Balance the month the goal is met.
requiredMonthly
Present only with deadlineYears > 0: the deposit that lands exactly on the goal by the deadline.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/savings-goal?goal=30000&current=5000&monthly=400&rate=4&deadlineYears=5

Share https://farbetteroff.com/api?try=savings-goal&goal=30000&current=5000&monthly=400&rate=4&deadlineYears=5#savings-goal

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/savings-goal?goal=30000&current=5000&monthly=400&rate=4&deadlineYears=5"

get/api/v1/emergency-fund

Emergency fund

How big a cushion is, how much of it is already there, and how many months of expenses today's savings would actually cover.

Parameters

NameAcceptsRequiredDescription
monthlyExpensesnumber, US dollars, between 0 and 1000000yesEssential monthly outgoings: housing, food, utilities, transport, insurance and minimum debt payments. Essentials, not the whole budget — restaurants, holidays and subscriptions pause in an emergency.
monthsnumber, whole months, between 1 and 24no, defaults to 6Months of cushion to size the target against. Defaults to 6, which is a convention rather than a rule — see the notes. ladder answers for 1, 3, 6 and 12 regardless of what you send.
savednumber, US dollars, between 0 and 1000000000no, defaults to 0What is set aside for emergencies today.
monthlySavingnumber, US dollars, between 0 and 1000000no, defaults to 0What can be added each month. Drives monthsToTarget; leave it out and that answer is null.
annualIncomenumber, US dollars, between 0 and 100000000no, defaults to 0Annual pre-tax family income. Drives peers.byIncome only — it changes no arithmetic. Omit it and that cut comes back null.
agenumber, years, between 0 and 120no, defaults to 0Age of the adult. Drives peers.byAge only — it changes no arithmetic. The survey covers adults, so an age under 18 falls outside every published band and returns null.

Returns, inside result

target
Dollars the chosen cushion comes to — monthlyExpenses × months.
targetMonths
Months of cushion the target represents, echoed.
gap
Dollars still to save. 0 once the target is met.
fundedPct
Share of the target already saved, 0–100.
funded
Whether the target is met.
monthsCovered
The target-independent answer: months of essentials current savings would cover. Does not move when months changes. Null when monthlyExpenses is 0.
monthsToTarget
Whole months of saving to close the gap, ignoring interest. 0 when already funded; null when nothing is being saved, or when it would take over 100 years.
termLabel
monthsToTarget in words, or null.
coversSmallShock
Whether savings alone cover the Federal Reserve's $400 emergency-expense question.
atRainyDayBenchmark
Whether savings reach three months of expenses — the rainy-day cushion the Federal Reserve measures households against.
ladder
The four cushion conventions (1, 3, 6, 12 months) with amount, reached and shortfall against each, plus who each size is usually suggested for.
benchmarks
The measured Federal Reserve figures this endpoint reports against — the $400 and three-month shares, and how many adults can cover neither — with their survey year.
peers
Is that normal? — the measured company this household keeps, for whichever cuts were supplied. byIncome and byAge give the share of adults in that band with three months set aside; savingsCeiling places saved in the Fed's largest-expense-from-savings distribution with the share below it and at or above it. Each cut is null when its input was not sent, and the full published bands ride along in bands so a caller can draw the whole distribution rather than one row.
  • Nobody regulates the size of an emergency fund, and this endpoint does not pretend otherwise. "Three to six months" is a widely-repeated convention with no rule behind it. The CFPB's own guide to building an emergency fund gives no month-count target at all — it says to save what you can, and that "even a small amount can provide some financial security". So ladder is labelled a set of conventions, and the numbers here that do have a measurement behind them are kept separate in benchmarks.
  • monthsCovered is the number to quote, not fundedPct. A percentage is a ratio against a target somebody chose, so it halves when a caller changes months from 6 to 12 while nothing about the household has changed. Months covered is what the Federal Reserve's Survey of Household Economics and Decisionmaking actually asks about: whether a household "could cover three months of expenses with a rainy day fund".
  • The $400 figure in coversSmallShock is the Fed's small-emergency question — whether an adult could cover "a hypothetical $400 emergency expense exclusively using cash, savings, or a credit card paid off at the next statement". 63% of US adults said they could in the 2025 survey, unchanged from the previous several years and down from a high of 68% in 2021. The three-month cushion in atRainyDayBenchmark is the other measured one: 55% of US adults reached it, while 30% could not cover three months by any means at all — borrowing and selling included. Both distributions, by income and by age, are set out at /how-much-should-i-have-in-an-emergency-fund with the table citations.
  • Interest is deliberately ignored. An emergency fund belongs somewhere liquid, and over the months this projection covers APY moves the finish line by days, so monthsToTarget is a slight over-estimate — the safe direction to be wrong in. Use /api/v1/savings-goal if you want the same question answered with a return applied.
  • monthsToTarget distinguishes 0 from null: 0 means the target is already met, null means not on this plan. A caller that conflates them prints "never" to someone who has finished.
  • The spread is the finding, not the row a caller lands on. The same "three to six months" is advised to a household where 21% manage it and to one where 75% do, and across age it runs 37% to 71% — both bracketing the 55% headline that gets quoted on its own. A single national figure describes neither end, which is why every band travels with the one that was selected.
  • No figure here is interpolated between bands. The bands are the Federal Reserve's own and are reproduced as published rather than re-cut, so a household earning $50,000 and one earning $99,000 get the same 55% — that is the resolution the survey publishes, and inventing a curve between the bands would be a figure the Board never reported. Edges are half-open on income ($50,000 belongs to the band above, matching the Board's "$25,000–$49,999" labels) and inclusive on age.
  • savingsCeiling places saved in table 26 — "the largest emergency expense you could handle right now using only savings". pctBelowBand is summed from the published bands rather than read off a cumulative column the Board does not print, and the sum is checkable: the at-or-above share of the $500–$999 band comes to 70%, which is the figure the Board states in its own text. One caveat worth passing on: the survey asks about every dollar of savings, while saved is what a household has earmarked for emergencies, so a real ceiling may sit a band higher.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/emergency-fund?monthlyExpenses=3500&months=6&saved=4000&monthlySaving=400&annualIncome=60000&age=35

Share https://farbetteroff.com/api?try=emergency-fund&monthlyExpenses=3500&months=6&saved=4000&monthlySaving=400&annualIncome=60000&age=35#emergency-fund

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/emergency-fund?monthlyExpenses=3500&months=6&saved=4000&monthlySaving=400&annualIncome=60000&age=35"

get/api/v1/net-worth

Net worth

Everything owned minus everything owed, split into what is liquid and what is not — and where the answer sits against the Federal Reserve's measured distribution for the household's age.

Parameters

NameAcceptsRequiredDescription
cashnumber, US dollars, between 0 and 1000000000no, defaults to 0Cash, checking and savings.
investmentsnumber, US dollars, between 0 and 1000000000no, defaults to 0Taxable brokerage holdings. Counted as liquid alongside cash.
retirementnumber, US dollars, between 0 and 1000000000no, defaults to 0401(k), IRA and other retirement accounts. Counted as an asset but not as liquid — reaching it early generally costs tax and a penalty.
homenumber, US dollars, between 0 and 1000000000no, defaults to 0Current market value of the home — what it would sell for today, not its purchase price.
vehiclesnumber, US dollars, between 0 and 1000000000no, defaults to 0Resale value of vehicles. See the notes on why this one normally falls year over year.
otherAssetsnumber, US dollars, between 0 and 1000000000no, defaults to 0Business interests, collectibles, cash value of insurance, anything else owned.
mortgagenumber, US dollars, between 0 and 1000000000no, defaults to 0Outstanding mortgage principal. Netted against home to give homeEquity.
autoLoansnumber, US dollars, between 0 and 1000000000no, defaults to 0Auto loan balances.
studentLoansnumber, US dollars, between 0 and 1000000000no, defaults to 0Student loan balances.
creditCardsnumber, US dollars, between 0 and 1000000000no, defaults to 0Credit card balances carried. Subtracted from liquid assets to give liquidNetWorth.
otherDebtsnumber, US dollars, between 0 and 1000000000no, defaults to 0Personal loans, medical debt, anything else owed. Also treated as short-term debt.
agenumber, years, between 0 and 120no, defaults to 0Age of the household's reference person. Drives benchmark only — it changes no arithmetic. Omit it and benchmark comes back null.

Returns, inside result

netWorth
Total assets minus total liabilities. Negative is common rather than exceptional — see the notes.
totalAssets
Everything owned, summed.
totalLiabilities
Everything owed, summed.
negative
Whether debts outweigh assets.
liquidAssets
cash + investments — what could be reached without selling a house or a car.
liquidNetWorth
Liquid assets less short-term debt (creditCards + otherDebts). The honest emergency figure: a brokerage balance offset by a card balance is not really available.
homeEquity
home − mortgage. Negative when the mortgage exceeds the home's value.
underwater
Whether the mortgage exceeds the home's value. False when there is no home.
debtToAssetPct
Liabilities as a percent of assets. Null when there are no assets to divide by.
liquidSharePct
Share of assets that is liquid, 0–100. Null when there are no assets.
assetMix
Each non-empty asset category with its amount, sharePct and whether it is liquid, in declared order rather than sorted by size.
benchmark
Where this net worth sits against the Federal Reserve's 2022 Survey of Consumer Finances for the household's age band: the band's median and mean, the meanToMedianRatio that explains the gap between them, vsMedianPct and atOrAboveMedian. Null when no age was sent.
allFamilies
Median and mean net worth across all US families in the same survey, with the same ratio — the denominator for "compared to everyone, not just my age".
  • Quote the median, not the mean. Net worth is among the most skewed quantities in household finance, so its average describes almost nobody: across all US families in the 2022 SCF the mean is $1,059,470 against a median of $192,700 — the mean is 5.5× the median, pulled there by the top of the distribution. Every "average net worth by age" figure in circulation is a mean. This endpoint returns both, and meanToMedianRatio so the difference is visible rather than implied.
  • The benchmark figures are 2022 dollars from a 2022 survey, and this endpoint does not pretend they are today's. The SCF runs every three years and the Board states that the 2022 survey "is the most recent survey conducted". Comparing a present-day balance sheet against a 2022-dollar benchmark flatters the present-day one, so surveyYear and dollarYear travel with every comparison. Nothing here inflates them to a current year — that would invent figures the Federal Reserve never published.
  • Every figure was transcribed from the Fed's own published workbook (table 4, "Family net worth, by selected characteristics of families, 1989–2022 surveys"), not from a secondary summary: https://www.federalreserve.gov/econres/files/scf2022_tables_public_real_historical.xlsx
  • The age bands are the Federal Reserve's own and are not evenly sized (Less than 35, then 35–44, 45–54, 55–64, 65–74, 75 or more). They are reproduced as published rather than re-cut, because re-cutting them needs data the summary table does not carry.
  • A negative net worth is a normal starting point, not a failure state: a new graduate with student loans or a recent buyer with a fresh mortgage will often show one for years. negative is reported as a fact about the balance sheet, and nothing in this response treats it as a verdict.
  • Assets are counted at what they would sell for today, not at what they cost. That is why a car normally pulls this number down year over year, and why nothing here applies appreciation, depreciation or a growth rate — net worth is a snapshot, and projecting it forward would be a forecast wearing a measurement's clothes.
  • retirement counts toward netWorth but not toward liquidAssets, and home counts toward neither liquidAssets nor liquidNetWorth. A household can be comfortably positive and still unable to cover a $400 emergency — use /api/v1/emergency-fund for that question.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/net-worth?cash=12000&investments=20000&retirement=45000&home=320000&vehicles=18000&mortgage=250000&autoLoans=9000&studentLoans=14000&creditCards=3000&age=40

Share https://farbetteroff.com/api?try=net-worth&cash=12000&investments=20000&retirement=45000&home=320000&vehicles=18000&mortgage=250000&autoLoans=9000&studentLoans=14000&creditCards=3000&age=40#net-worth

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/net-worth?cash=12000&investments=20000&retirement=45000&home=320000&vehicles=18000&mortgage=250000&autoLoans=9000&studentLoans=14000&creditCards=3000&age=40"

get/api/v1/budget

50/30/20 budget

Take-home pay split into needs, wants and savings on the 50/30/20 rule — with housing measured against the needs slice it has to fit inside, and against the two benchmarks that are actually published.

Parameters

NameAcceptsRequiredDescription
incomenumber, US dollars, between 0 and 10000000yesMonthly take-home pay — after taxes and payroll deductions.
housingnumber, US dollars, between 0 and 10000000noMonthly housing cost including utilities, HUD's basis. Drives the whole housing object; omit it and that comes back null.
grossMonthlyIncomenumber, US dollars, between 0 and 10000000noMonthly income before taxes. Used for nothing but HUD's cost-burden test, which is defined on gross income. Omit it and housing.hud comes back null rather than being estimated from take-home.
annualIncomenumber, US dollars, between 0 and 1000000000noAnnual pre-tax family income. Selects margin.band only — it changes no arithmetic. Omit it and the band comes back null.

Returns, inside result

income
Monthly take-home pay, echoed.
plan
The rule's three slices in dollars a month: needs (50%), wants (30%) and savings (20%).
savingsPerYear
The savings slice over twelve months, at this pace and ignoring investment returns.
ruleShares
The three percentages, so a caller never hardcodes 50/30/20 itself.
ruleOrigin
Where the rule comes from — a 2005 book, named. See the notes.
housing
Housing against the budget: sharePct of take-home, shareOfNeedsBudgetPct of the rule's own needs slice, leavesForOtherNeeds in dollars, and fitsNeedsBudget. Null when no housing was sent. Its nested hud carries HUD's cost-burden test on HUD's own basis — grossSharePct, costBurdened (above 30% of gross) and severelyCostBurdened (above 50%) — and is itself null unless grossMonthlyIncome was supplied, per the notes.
margin
What the Federal Reserve measures about having anything left over at month end: alwaysOrOftenPct across all US adults, the band matching annualIncome, and every bands entry with its full five-point distribution.
  • 50/30/20 is a rule of thumb from a book, not a standard. It traces to the 2005 book All Your Worth: The Ultimate Lifetime Money Plan, by Elizabeth Warren and Amelia Warren Tyagi. No regulator publishes it, no agency measures against it, and no federal survey reports it as a norm. This endpoint implements it faithfully and returns ruleOrigin with every response, so a caller quoting the split can say where it came from instead of implying an authority that does not exist.
  • shareOfNeedsBudgetPct is the figure to quote, and nobody else publishes it. Everyone reports housing as a share of income; the question the rule actually poses is whether housing fits inside the 50% it allows for all needs. On $4,500 of take-home the needs slice is $2,250, so $1,800 of rent is 80% of the entire needs budget and leaves $450 for food, utilities, transport, insurance and minimum debt payments. Above 100 the rule is broken before groceries. That is the arithmetic answer to "is 50/30/20 realistic?".
  • HUD's 30% is defined on gross income, and this endpoint will not apply it to take-home pay. HUD defines affordable housing as housing "on which the occupant is paying no more than 30 percent of gross income for housing costs, including utilities", above 50 percent being the severe case; its CHAS dataset counts cost-burdened households against exactly that threshold. Take-home pay is a smaller denominator, so the same rent scores higher against it — $1,800 is 40% of $4,500 take-home but 30.0% of $6,000 gross, which is one household and two different verdicts. housing.hud therefore stays null until grossMonthlyIncome arrives rather than guessing a gross figure. Sources: https://archives.hud.gov/local/nv/goodstories/2006-04-06glos.cfm and https://www.huduser.gov/portal/datasets/cp.html
  • Saving 20% is not the norm, and there is a measurement for it. The Federal Reserve's Survey of Household Economics and Decisionmaking asks how often people have money left over at the end of the month. In 2025, 41 percent of US adults said always or often — similar to 2024 — and it ranges from 19 percent under $25,000 of family income to 59 percent at $100,000 or more. The rule's savings slice is a target, and margin is what the population actually reports. https://www.federalreserve.gov/publications/2026-economic-well-being-of-us-households-in-2025-income-and-expenses.htm
  • The Board publishes whole percents, so the five-point distributions in margin.bands sum to between 99 and 101 rather than exactly 100. That is rounding in the source. alwaysOrOftenPct is the Board's own stated figure rather than a sum of two rounded components — which matters in the lowest band, where the prose says 19 and often + always sums to 20.
  • annualIncome is pre-tax family income for the whole household, because that is the basis the Fed's bands use. income is monthly take-home for one budget. They are deliberately different questions and neither is derived from the other.
  • Nothing here is advice about what the split should be. The rule is returned as the rule, the two benchmarks are returned as measurements, and they are kept in separate objects so nothing borrows the other's authority.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/budget?income=4500&housing=1800&grossMonthlyIncome=6000&annualIncome=72000

Share https://farbetteroff.com/api?try=budget&income=4500&housing=1800&grossMonthlyIncome=6000&annualIncome=72000#budget

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/budget?income=4500&housing=1800&grossMonthlyIncome=6000&annualIncome=72000"

get/api/v1/cd

Certificate of deposit

What a CD is worth at maturity, from the APY the bank quotes.

Parameters

NameAcceptsRequiredDescription
depositnumber, US dollars, between 0 and 10000000000yesAmount deposited.
apynumber, a percentage, so 6.5 means 6.5%, between 0 and 50yesAnnual percentage yield, as quoted.
termMonthsinteger, whole months, between 1 and 600yesTerm of the CD in months.

Returns, inside result

maturity
Value when the term ends.
interest
Maturity minus the deposit.
  • APY already accounts for the bank's compounding frequency, which is what makes it the comparable number (12 CFR Part 1030 / Regulation DD, Appendix A).
  • Interest is shown before tax. CD interest is generally taxable as ordinary income.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/cd?deposit=10000&apy=4.25&termMonths=12

Share https://farbetteroff.com/api?try=cd&deposit=10000&apy=4.25&termMonths=12#cd

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/cd?deposit=10000&apy=4.25&termMonths=12"

get/api/v1/inflation

Inflation impact

What a sum of money will cost, and what it will be worth, after inflation has run for a while.

Parameters

NameAcceptsRequiredDescription
amountnumber, US dollars, between 0 and 1000000000000yesToday's amount.
yearsnumber, years, between 0 and 200yesHow many years forward.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 3Average annual inflation rate.

Returns, inside result

factor
Cumulative price multiplier over the period.
futureCost
What today's basket costs then.
buyingPower
What today's money is worth then, in today's dollars.
lostPercent
Share of buying power lost, as a percentage.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/inflation?amount=10000&years=20&rate=3

Share https://farbetteroff.com/api?try=inflation&amount=10000&years=20&rate=3#inflation

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/inflation?amount=10000&years=20&rate=3"

get/api/v1/401k

401(k) projection

A 401(k) balance projected to retirement, split into your money, the employer's money and growth.

Parameters

NameAcceptsRequiredDescription
currentBalancenumber, US dollars, between 0 and 10000000000no, defaults to 0What is in the account today.
salarynumber, US dollars, between 0 and 1000000000yesCurrent annual salary.
contribPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesShare of salary you defer each year.
matchRatePercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 200no, defaults to 50Cents on the dollar the employer matches — 50 means 50%.
matchLimitPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 6Share of salary the match applies up to.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 7Average annual return.
annualRaisePercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 50no, defaults to 2Average yearly raise.
yearsinteger, years, between 0 and 70yesYears until you stop contributing.
currentAgeinteger, years, between 0 and 100noThe age you reach this year. Given it, each year of the projection uses that year's own § 402(g) limit, including the age-50 and age-60-to-63 catch-ups. Ignored when deferralLimit is sent.
deferralLimitnumber, US dollars, between 0 and 1000000noEmployee deferral cap for every year, overriding currentAge. Omit both for the flat 2026 limit, $24,500.
seriesbooleanno, defaults to falseInclude the year-by-year balance series.

Returns, inside result

balance
Projected balance at the end.
yourContributions
Everything you put in, excluding the starting balance.
employerContributions
Everything the employer matched in.
growth
Investment growth on top.
cappedByDeferralLimit
True if your contribution percentage would exceed the annual cap.
catchUpContributions
Of yourContributions, the dollars only a catch-up allowed. 0 unless currentAge was sent and the plain limit would have bitten.
series
Present only when series=true.
  • 2026 employee deferral limit: $24,500 (IRS Notice 2025-67), $32,500 from the year you turn 50 and $35,750 for the four years you turn 60 to 63 — send currentAge to have each year use its own. The 2026 figures apply to every projected year; they rise with inflation most years.
  • A projection, not a promise: it assumes a constant return and a constant raise, and markets do neither.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/401k?currentBalance=25000&salary=65000&contribPercent=6&years=35

Share https://farbetteroff.com/api?try=401k&currentBalance=25000&salary=65000&contribPercent=6&years=35#401k

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/401k?currentBalance=25000&salary=65000&contribPercent=6&years=35"

get/api/v1/401k-match

Employer match

What your employer's match is worth this year — and how much of it you are leaving on the table.

Parameters

NameAcceptsRequiredDescription
salarynumber, US dollars, between 0 and 1000000000yesAnnual salary.
contribPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesShare of salary you contribute.
matchRatePercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 200no, defaults to 50Cents on the dollar matched — 50 means 50%, 100 means dollar for dollar.
matchLimitPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 6Share of salary the match applies up to.

Returns, inside result

yourContribution
Your dollars in this year.
match
Employer dollars you earn.
maxMatch
The most the employer would put in at this formula.
missed
Match you are giving up by contributing less than the limit.
total
Your contribution plus the match.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/401k-match?salary=60000&contribPercent=4&matchRatePercent=50&matchLimitPercent=6

Share https://farbetteroff.com/api?try=401k-match&salary=60000&contribPercent=4&matchRatePercent=50&matchLimitPercent=6#401k-match

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/401k-match?salary=60000&contribPercent=4&matchRatePercent=50&matchLimitPercent=6"

get/api/v1/safe-withdrawal

Safe withdrawal rate

The income a nest egg supports — the 4% rule, and the 25× multiple behind it.

Parameters

NameAcceptsRequiredDescription
nestEggnumber, US dollars, between 0 and 1000000000000yesPortfolio value at retirement.
withdrawalRatenumber, a percentage, so 6.5 means 6.5%, between 0.1 and 20no, defaults to 4First-year withdrawal rate.

Returns, inside result

annual
First-year withdrawal in dollars.
monthly
That divided by 12.
multiple
Years of spending the portfolio represents — 25 at 4%.
  • The 4% rule comes from William Bengen's 1994 study and the 1998 Trinity Study: a 4% inflation-adjusted first-year withdrawal survived every 30-year period in US market history. 30 years is the worst case in that research, not a guarantee.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/safe-withdrawal?nestEgg=1000000&withdrawalRate=4

Share https://farbetteroff.com/api?try=safe-withdrawal&nestEgg=1000000&withdrawalRate=4#safe-withdrawal

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/safe-withdrawal?nestEgg=1000000&withdrawalRate=4"

get/api/v1/fire

FIRE number and date

The portfolio that covers your spending forever, and how many years of saving it takes to get there.

Parameters

NameAcceptsRequiredDescription
annualSpendingnumber, US dollars, between 0 and 1000000000yesWhat you expect to spend per year in retirement.
currentnumber, US dollars, between 0 and 1000000000000no, defaults to 0Invested savings today.
annualSavingsnumber, US dollars, between 0 and 1000000000no, defaults to 0What you invest per year.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 7Real (after-inflation) annual return, so the answer is already in today's dollars.
withdrawalRatenumber, a percentage, so 6.5 means 6.5%, between 0.1 and 20no, defaults to 4Withdrawal rate used to set the target.

Returns, inside result

fireNumber
Annual spending divided by the withdrawal rate.
reached
Whether saving gets there inside 70 years.
years
Years until the target is hit. 0 if you are already there.
balances
Balance at the end of each year, index 0 being today.
  • Because the rate is a real return, no separate inflation adjustment is applied — every figure is in today's dollars.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/fire?annualSpending=45000&current=30000&annualSavings=25000&rate=7

Share https://farbetteroff.com/api?try=fire&annualSpending=45000&current=30000&annualSavings=25000&rate=7#fire

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/fire?annualSpending=45000&current=30000&annualSavings=25000&rate=7"

get/api/v1/coast-fire

Coast FIRE

The amount that, invested today, grows into your FIRE number by retirement with no further contributions.

Parameters

NameAcceptsRequiredDescription
annualSpendingnumber, US dollars, between 0 and 1000000000yesExpected annual spending in retirement.
currentnumber, US dollars, between 0 and 1000000000000no, defaults to 0Invested savings today.
annualSavingsnumber, US dollars, between 0 and 1000000000no, defaults to 0What you invest per year until you coast.
yearsToRetirementinteger, years, between 0 and 70yesYears until you plan to retire.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 7Real (after-inflation) annual return.
withdrawalRatenumber, a percentage, so 6.5 means 6.5%, between 0.1 and 20no, defaults to 4Withdrawal rate used to set the target.

Returns, inside result

fireNumber
The full retirement target.
coastNumberToday
Invest this much today and you can stop contributing.
reached
Whether you reach the coast point before retirement.
yearsToCoast
Years until you can stop contributing. 0 if you already can.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/coast-fire?annualSpending=45000&current=30000&annualSavings=25000&yearsToRetirement=35

Share https://farbetteroff.com/api?try=coast-fire&annualSpending=45000&current=30000&annualSavings=25000&yearsToRetirement=35#coast-fire

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/coast-fire?annualSpending=45000&current=30000&annualSavings=25000&yearsToRetirement=35"

get/api/v1/roth-vs-traditional

Roth vs Traditional

Which account leaves you with more after tax, compared at the same cost to you today — plus the effective federal rate a Traditional withdrawal actually pays, which is neither the bracket everyone quotes nor the 20% a plan withholds.

Parameters

NameAcceptsRequiredDescription
contributionnumber, US dollars, between 0 and 100000no, defaults to 7500Yearly contribution, measured as what leaves your pocket after tax. Defaults to the 2026 IRA limit. See the notes — this is not the same as the figure you type into a brokerage form.
yearsinteger, years, between 1 and 60no, defaults to 30Years of contributions and growth before you start withdrawing.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 20no, defaults to 7Annual return, the same for both accounts.
taxNownumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesYour marginal tax rate today — the bracket the contribution would otherwise be taxed in.
taxRetirenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesThe rate you expect the Traditional withdrawal to pay. Send the effective rate, not a bracket — withdrawal below computes it for you.
withdrawalnumber, US dollars, between 0 and 10000000noA year's planned withdrawal from the pre-tax account. Drives the whole retirementRate object, which is the point of this endpoint; omit it and that comes back null.
otherTaxableIncomenumber, US dollars, between 0 and 10000000no, defaults to 0Other ordinary taxable income in the same retirement year — a pension, a spouse's wages, another account's required distribution. The withdrawal stacks on top of it, so this raises the rate. Social Security is not modelled; see the notes.
withheldPctnumber, a percentage, so 6.5 means 6.5%, between 0 and 100noWhat the payer actually withheld, if you have the statement in front of you. Omit it and withholding uses the default for account — 20% or 10% — and flags it as assumed. Withholding is a deposit, not a rate; it changes no arithmetic above.
accountone of plan, irano, defaults to planWhere the withdrawal is paid from, which sets the default withholding when withheldPct is omitted. A workplace plan withholds 20% and you cannot decline it; an IRA withholds 10% and you can elect out. Selects a default only — it changes no arithmetic.
agenumber, years, between 0 and 120noYour age when the withdrawal is taken, which is a different age from age50Plus below — that one is about this year's contribution. Halves count, because the threshold is one: 59.4 is early and 59.5 is not. Selects ageRules, which also needs withdrawal; omit it and that comes back null.
statusone of single, married, hoh, mfsno, defaults to singleFiling status in retirement, which sets the standard deduction and the brackets the withdrawal fills.
maginumber, US dollars, between 0 and 100000000noToday's modified adjusted gross income. Selects eligibility only — it changes no arithmetic above. Omit it and that comes back null.
age50Plusbooleanno, defaults to falseWhether the catch-up limit applies, which raises the cap from $7,500 to $8,600. This is your age today, in the contribution year — age above is your age at the withdrawal, decades later. Affects limitEdge and eligibility.

Returns, inside result

winner
"roth", "traditional" or "tie".
roth
After-tax value of the Roth at the end. Withdrawals are tax-free, so this is the balance.
traditional
After-tax value of the Traditional at the end, net of the exit tax at taxRetire.
difference
traditional − roth. Positive means the Traditional came out ahead.
edge
The absolute difference, which is what a headline wants.
tie
True when the two land within half a percent — which is what equal tax rates produce.
retirementRate
The correction this endpoint exists for. The federal tax a withdrawal actually causes: effectiveRatePct against the marginalRatePct everyone quotes, overstatementPct between them, the untaxedAmount the standard deduction shields, and the bands the withdrawal itself occupies. assumesOnlyIncome flags the best case. Null unless withdrawal was sent.
withholding
What the payer took, against what is actually owed. withheldPct and the dollars withheld, the tax due on the same withdrawal, and the gap between them — overwithheld is true when that gap is positive, which means the excess comes back as a refund the following spring, having earned nothing in between. breakEvenWithdrawal is the withdrawal at which that withholding rate would finally be the right one; below it the payer always takes too much. assumedPct is true when the rate was the default for account rather than one you sent. Null unless withdrawal was sent.
ageRules
What the two ages cost, priced. Before 59½ an additional tax applies, and it is charged on the distribution rather than on the tax — so penalty can exceed incomeTax outright, and allInRatePct is simply the effective rate plus penaltyPct. early says which side of the threshold you are on, yearsUntilPenaltyFree how far, and assumesNoException flags that none of the 72(t) exceptions are modelled. The other age is reported rather than computed: rmdAgeReached and yearsUntilRmd against rmdAge, the age at which the withdrawal stops being a choice. Null unless both age and withdrawal were sent.
limitEdge
What the contribution cap does when you max out: the traditionalAfterTaxCost of the same nominal contribution, the equivalentPreTaxContribution that would match a full Roth, how far that exceedsLimitBy, and the resulting rothAdvantagePct. Nothing here depends on future tax rates.
eligibility
Whether this magi may contribute to a Roth IRA at all: the band, the reduced limit after the IRS's rounding, and the phaseOut range. Null unless magi was sent.
years
Whole years used, after rounding the years parameter.
status
Filing status used for the deduction, the brackets and the phase-out range, echoed.
taxYear
The tax year every bracket, deduction and limit above belongs to.
  • The retirement rate people quote is a bracket, and a withdrawal is not taxed at a bracket. A Traditional withdrawal is ordinary income filling the brackets from the bottom — the standard deduction first at 0%, then 10%, then 12%. On $60,000 withdrawn by a single filer with no other taxable income, the marginal bracket is 12% and the effective federal rate is 8.37%. Someone comparing "22% now against 22% later" and concluding it is a wash has the later figure wrong by more than the decision is worth. Send withdrawal and use the effectiveRatePct that comes back as taxRetire.
  • That rate is a floor, not a forecast, and this endpoint says so in the response. It assumes the withdrawal is the only ordinary income that year. A pension, a spouse's wages, interest, and required distributions from any other pre-tax account all stack underneath it and push it into higher bands — the same $60,000 on top of $40,000 of other income pays 17.58%, more than double. That is what otherTaxableIncome is for, and why assumesOnlyIncome is returned rather than assumed.
  • The percentage a plan withheld is not a tax rate at all, and it is usually too much. A retirement plan distribution paid to you carries mandatory withholding of 20% — the IRS's words are "even if you intend to roll it over later" — so it is a deposit against a bill computed months later, identical for everyone and knowing nothing about the filer. On the $60,000 above, the plan sends $12,000 against $5,020 owed: $6,980 lent to the Treasury, earning nothing, until the return is filed. The withholding block measures that gap, and breakEvenWithdrawal says where it closes — about $239,133 withdrawn in one year by that filer, which is why over-withholding is the normal case rather than an edge case. An IRA is the contrast that proves it is a default and not a rate: 10%, and electable out — send account=ira for it. https://www.irs.gov/retirement-plans/plan-participant-employee/rollovers-of-retirement-plan-and-ira-distributions
  • The 10% before 59½ is charged on the distribution, not on the tax — which makes it larger than the surcharge people picture. Send age and ageRules prices it: the same $60,000 taken at 50 owes $5,020 of income tax and $6,000 of additional tax — the penalty is the bigger of the two — for an all-in federal rate of 18.37% against the 8.37% the same withdrawal costs after 59½. Because it lands on the distribution it adds exactly its own 10 points to the rate, whatever the rate was; a withdrawal small enough to owe no income tax at all still owes it. The 72(t) exceptions are not modelled — disability, death, substantially equal periodic payments, qualified birth or adoption, certain medical expenses, a domestic-abuse distribution, separation from service at 55 or later for a workplace plan — so penalty is what applies if none of them fits, which is what assumesNoException says out loud. A rollover is not an early distribution: the additional tax reaches only the taxable part. https://www.irs.gov/taxtopics/tc558
  • RMDs are reported, not computed. ageRules answers whether you have reached 73 and how many years are left, because the amount depends on a life-expectancy table and the prior 31 December balance that this endpoint does not ask for. Two timing notes that are this endpoint's own arithmetic applied to a deadline: the first RMD can be deferred to April 1 of the following year, which stacks two distributions into one calendar year and raises the effective rate on both, and a participant still working for the employer sponsoring the plan can generally delay plan RMDs until they retire unless they own 5% or more of the business. Roth IRAs have no RMDs while the owner is alive. https://www.irs.gov/retirement-plans/retirement-plan-and-ira-required-minimum-distributions-faqs
  • Social Security benefit taxation is not modelled, and it is the largest thing missing. A Traditional withdrawal can raise the share of a benefit that becomes taxable, which is a second effect on top of the tax on the withdrawal itself. A retiree drawing Social Security should read retirementRate as an understatement.
  • At the same tax rate now and later the two accounts are mathematically identical, and this endpoint returns a tie rather than a winner. (1 − t)·(1 + r)ⁿ and (1 + r)ⁿ·(1 − t) are the same number. Any calculator that shows the Roth winning at equal rates is comparing equal contributions rather than equal cost — which compares a larger sacrifice against a smaller one. See contribution above.
  • The cap is the one argument for the Roth that does not depend on predicting tax rates. $7,500 into a Roth shelters $7,500 of after-tax money; the same nominal amount into a Traditional costs only $5,850 after tax at a 22% rate. Matching the Roth would take $9,615 of pre-tax money, which the cap does not allow. limitEdge reports that gap. The deferred tax is real and stays in your pocket, but it lands in a taxable account whose drag this endpoint does not model, so it is returned as taxSavings and not projected.
  • Federal only, and not a tax return. No state income tax (see /api/v1/state-tax), no IRMAA, no Net Investment Income Tax, no credits, no age-65 additional standard deduction, and no RMD schedule. Figures are for tax year 2026: standard deduction and brackets from IRS Rev. Proc. 2025-32, limits from IRS Notice 2025-67.
  • The eligibility object is the Roth contribution limit only. Whether a Traditional contribution is deductible phases out on different ranges that also depend on whether you or a spouse are covered by a workplace plan, and that is not modelled here — an undeducted Traditional contribution changes the comparison completely, so do not read a full band as advice about the other account. Roth phase-out ranges for 2026: $153,000–$168,000 single and head of household, $242,000–$252,000 married filing jointly, and $0–$10,000 filing separately, which never adjusts for inflation. https://www.irs.gov/newsroom/401k-limit-increases-to-24500-for-2026-ira-limit-increases-to-7500
  • Nothing here is advice about which account to choose. The comparison is arithmetic on the rates you supply, and the rate that matters most is the one this endpoint computes rather than asks you to guess.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/roth-vs-traditional?years=30&taxNow=22&taxRetire=22&withdrawal=60000&magi=120000

Share https://farbetteroff.com/api?try=roth-vs-traditional&years=30&taxNow=22&taxRetire=22&withdrawal=60000&magi=120000#roth-vs-traditional

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/roth-vs-traditional?taxNow=22&taxRetire=22&withdrawal=60000&years=30&magi=120000"

get/api/v1/refinance

Mortgage refinance break-even

The new payment, the monthly saving, how long it takes to earn the closing costs back, and whether resetting the term costs more interest anyway.

Parameters

NameAcceptsRequiredDescription
balancenumber, US dollars, between 0 and 10000000000yesWhat is still owed on the current mortgage.
currentRatenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesThe rate on the loan you have today.
yearsLeftnumber, years, between 0 and 50yesYears remaining on the current loan.
newRatenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesThe rate you are being offered.
newTermYearsinteger, years, between 1 and 50no, defaults to 30Term of the new loan, in years.
closingCostsnumber, US dollars, between 0 and 100000000no, defaults to 0Closing costs on the new loan, paid up front. Typically 2%–5% of the loan.

Returns, inside result

currentPayment
Principal and interest on the loan you have.
newPayment
Principal and interest on the loan you would take.
monthlySavings
Current payment minus new payment. Negative when refinancing costs more each month.
breakEvenMonths
Months of saving needed to cover the closing costs. Null (as "never") when the payment goes up.
breakEvenLabel
The same figure in words, e.g. "1 yr 6 mo".
currentInterest
Interest left on the current loan if you keep it to the end.
newInterest
Interest on the new loan over its full term.
lifetimeInterestDiff
Current interest minus new interest. Negative means the refinance costs more interest over its life, even at a lower rate.
resetsTheTerm
True when the payment falls but the lifetime interest rises — the reset trap.
  • A rate-and-term refinance: both loans are measured on the same balance, so this does not model cash-out, points bought at closing, or rolling the costs into the loan.
  • The interest figures cover each loan's own full remaining term, so they are not a like-for-like span when the terms differ. That is what makes resetsTheTerm visible instead of hidden.
  • Break-even ignores what the saved payment could earn if invested, and assumes you keep the loan to payoff.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/refinance?balance=320000&currentRate=7.25&yearsLeft=27&newRate=6&newTermYears=30&closingCosts=6000

Share https://farbetteroff.com/api?try=refinance&balance=320000&currentRate=7.25&yearsLeft=27&newRate=6&newTermYears=30&closingCosts=6000#refinance

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/refinance?balance=320000&currentRate=7.25&yearsLeft=27&newRate=6&newTermYears=30&closingCosts=6000"

get/api/v1/rent-vs-buy

Rent vs buy

Net worth year by year down both paths, counting what the renter earns investing the down payment, and the year buying pulls ahead.

Parameters

NameAcceptsRequiredDescription
yearsinteger, years, between 1 and 50yesHow long you would stay before selling or moving out.
homePricenumber, US dollars, between 0 and 10000000000yesPurchase price.
monthlyRentnumber, US dollars, between 0 and 1000000yesRent for a comparable place, per month, today.
downPaymentPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 20Down payment as a percentage of the price.
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100no, defaults to 6.5Mortgage rate (APR).
termYearsinteger, years, between 1 and 50no, defaults to 30Length of the mortgage.
homeGrowthnumber, a percentage, so 6.5 means 6.5%, between -20 and 30no, defaults to 4Annual home appreciation. May be negative.
rentGrowthnumber, a percentage, so 6.5 means 6.5%, between -20 and 30no, defaults to 3Annual rent increase, applied on each anniversary.
investReturnnumber, a percentage, so 6.5 means 6.5%, between 0 and 30no, defaults to 7What invested cash earns annually — the down payment's opportunity cost.
propertyTaxPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 10no, defaults to 1.1Property tax per year, as a percentage of the home's current value.
maintenancePercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 10no, defaults to 1Maintenance per year, as a percentage of the home's current value.
insuranceAnnualnumber, US dollars, between 0 and 1000000no, defaults to 1800Homeowner's insurance per year.
hoaMonthlynumber, US dollars, between 0 and 100000no, defaults to 0HOA dues per month.
buyClosingPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 20no, defaults to 2Buying costs paid up front, as a percentage of the price.
sellClosingPercentnumber, a percentage, so 6.5 means 6.5%, between 0 and 20no, defaults to 6Selling costs, as a percentage of the sale price — agent commission and closing.
pmiRatePctnumber, a percentage, so 6.5 means 6.5%, between 0 and 5no, defaults to 0.5Annual private mortgage insurance as a percent of the loan, charged only when the down payment leaves the loan above 80% of the price. Defaults to 0.5%, mid-range for the $30–$70 a month per $100,000 borrowed Freddie Mac describes. Send pmiRatePct=0 for a comparison with no mortgage insurance in it — the right call for a VA loan.

Returns, inside result

verdict
"buy", "rent", or "toss-up" when the two land within half a percent of the price.
difference
Buyer's net worth minus renter's at the end of the stay. Positive means buying won.
breakEvenYear
First year the buyer's net worth catches the renter's. Null when it never happens inside the stay.
buyerNetWorth
Net worth if you buy: today, then one entry per year. Home equity after selling costs, plus investments.
renterNetWorth
Net worth if you rent, over the same points — the invested down payment and every month renting was cheaper.
monthlyPayment
Principal and interest on the mortgage.
loanAmount
The mortgage itself — home price less the down payment.
remainingBalance
What is still owed on that mortgage at the end of the stay.
years
The length of the stay the comparison was run over, echoed back because every other figure is measured at its end.
finalHomeValue
What the home is worth at the end of the stay.
totals
What was spent over the whole stay: rent, mortgage interest, property tax, maintenance, insurance, HOA, and PMI.
upfront
Down payment, buying costs, and the selling costs owed at the end.
pmi
Null when no mortgage insurance is charged. Otherwise the monthly premium, the month it comes off, and what it costs inside the stay.
  • Both people start with the same cash. The buyer spends it on the down payment and buying costs; the renter invests it at investReturn, and each month the cheaper path invests the difference. That opportunity cost is what most rent-vs-buy comparisons leave out.
  • The buyer's net worth is equity after selling costs, so it is what they would walk away with — which is why buying normally starts well behind.
  • Annual rates compound monthly ((1 + r)^(1/12) − 1), so 7% means 7% a year, not 7%/12 a month.
  • PMI is charged below 20% down, and it is the cost that moves this answer most. The premium falls entirely in the early years, which is where the break-even lives: on years=7&homePrice=400000&monthlyRent=2400&downPaymentPercent=5&rate=6.5 it is $158.33 a month for 135 months — $13,300 inside a 7-year stay — and it moves breakEvenYear from 5 to 6 and difference from $26,559 to $9,595, which is more than the premium itself because the renter invests every month owning costs more. It stops on the CFPB's automatic termination date — the month the scheduled balance reaches 78% of the price, with the loan's midpoint as a backstop — the same date /api/v1/pmi returns for the same loan. pmiRatePct=0 turns it off.
  • Not modelled: the mortgage interest deduction, and capital-gains treatment on the sale. Each needs assumptions about one person's taxes, and each moves the answer.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/rent-vs-buy?years=7&homePrice=400000&monthlyRent=2400&downPaymentPercent=20&rate=6.5

Share https://farbetteroff.com/api?try=rent-vs-buy&years=7&homePrice=400000&monthlyRent=2400&downPaymentPercent=20&rate=6.5#rent-vs-buy

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/rent-vs-buy?years=7&homePrice=400000&monthlyRent=2400&downPaymentPercent=20&rate=6.5"

get/api/v1/rule-of-72

Rule of 72

Roughly how long money takes to double at a given rate, and the exact answer beside it.

Parameters

NameAcceptsRequiredDescription
ratenumber, a percentage, so 6.5 means 6.5%, between 0 and 100yesAnnual rate of return.

Returns, inside result

years
72 divided by the rate. Null at or below 0%, where money never doubles.
exactYears
The precise answer, ln(2) / ln(1 + r), for comparison.
  • The Rule of 72 is a mental-arithmetic approximation. It is accurate to within a few months over the 5%–12% range and drifts outside it — exactYears is the number to use when precision matters.
Try it — edit the values and send a real request

GET https://farbetteroff.com/api/v1/rule-of-72?rate=8

Share https://farbetteroff.com/api?try=rule-of-72&rate=8#rule-of-72

Open the raw JSON →·The same answer as a calculator page

curl "https://farbetteroff.com/api/v1/rule-of-72?rate=8"

Other ways to carry Far Better Off

If you want the calculator itself rather than the numbers, every one of them embeds in an iframe with no account and no approval: free calculator widgets for your site. Found a wrong number or need an endpoint that does not exist yet? Email hellofarbetteroff@gmail.com.