Savings calculator
Start with 1,000, add 100 a month at 5% for 10 years and the balance reaches 17,175.24: 13,000 of your own money and 4,175.24 of interest. Interest compounds every month. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Deposit
- 1,000
- Monthly
- 100
- Interest rate
- 5
- Years
- 10
- Months
- 120
- Monthly rate
- 0.0041666667
- Final balance
- 17,175.24
- Total contributed
- 13,000
A savings calculator answers one household question: if you start with an initial deposit, add a fixed amount every month, and earn a stated annual interest rate for a number of years, what is the balance. This savings calculator accepts those four numbers—initial deposit, monthly contribution, annual interest as a percent, and years—and returns the final balance after monthly compounding. It does not invert a target into the monthly amount you would need, convert currencies, or project a mutual-fund SIP under a different name.
What savings growth means and how the closed form works
A savings plan in this calculator has two cash-flow shapes that compound under the same nominal annual interest rate. The initial deposit is a single amount credited at the start of the horizon. The monthly contribution is a constant amount credited at the end of every month for the whole horizon.
Convert the annual percent to a monthly rate i by dividing by one hundred and then by twelve. The number of months n is twelve times the horizon in years. The deposit grows as P times one plus i to the n, which is ordinary monthly compounding of a principal.
The contributions are treated as an ordinary end-of-month annuity: PMT times the quantity one plus i to the n, minus one, divided by i. When the annual rate is zero the monthly rate is zero and that annuity ratio is undefined, so the contribution future value collapses to PMT times n, which is simply the cash you put in. The final balance is the sum of the two pieces.
Total contributed is the deposit plus PMT times n, and interest is the final balance minus that cash. This landing is not a lumpsum-only compound-interest page, not a beginning-of-period annuity-due identity, and not a months-to-goal inverter: those queries already have their own calculators.
What you can do with it
Emergency-fund and house-deposit projections
Project the combined balance of an opening deposit invested today together with a fixed monthly transfer at a stated annual interest rate and horizon.
Classroom and coaching oracles
Generate reproducible savings answer keys that split the final balance into cash contributed and interest earned so learners can check each piece.
FAQ
How is the savings final balance calculated?
The deposit grows as P×(1+i)^n. Monthly contributions are an ordinary end-of-month annuity PMT×[((1+i)^n−1)/i], or PMT×n when i is zero. The final balance is the sum of those two pieces.
Is the rate a percent or a decimal?
A percent. Send 5 for five percent per year. Sending 0.05 would be treated as five hundredths of a percent, not five percent.
What happens if the rate or the period is negative?
A negative annual rate or a negative number of years is rejected and is not billed. Zero rate and zero years are allowed.
Are monthly contributions credited at the start or the end of each month?
At the end of each month (ordinary annuity). Beginning-of-month annuity-due identities are a different contract.
Can it tell me how much to save each month to reach a goal?
No. It works forward from a deposit, a monthly amount, a rate and a number of years to the final balance. Working back from a target to the monthly saving you would need is a different calculation.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/fin/savings \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"deposit":1000,"monthly":100,"rate":5,"years":10}'const res = await fetch("https://api.kit.forhosting.com/fin/savings", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"deposit": 1000,
"monthly": 100,
"rate": 5,
"years": 10
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/savings",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"deposit": 1000,
"monthly": 100,
"rate": 5,
"years": 10
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/savings", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"deposit":1000,"monthly":100,"rate":5,"years":10}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"deposit":1000,"monthly":100,"rate":5,"years":10}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/savings", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"deposit": 1000,
"monthly": 100,
"rate": 5,
"years": 10
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.savings",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
A negative rate or a negative period fails with invalid_input instead of a silent empty growth path.
Input contract, response shape, and error behaviour
Example: one thousand deposit, one hundred monthly, five percent, and ten years is one hundred twenty months at a five-twelfths percent monthly rate. Failed validation does not consume balance. POST a JSON body with four required finite numbers. deposit is the opening amount in one currency; aliases initial, principal, starting_balance, and initial_deposit are accepted so spreadsheets can keep familiar column names, and the value must sit between zero and one trillion inclusive. monthly is the recurring contribution in the same units, with aliases contribution, monthly_contribution, pmt, and monthly_deposit, also from zero through one trillion. Either cash-flow may be zero so you can project a pure opening deposit or a pure monthly plan on the same contract. rate is the nominal annual interest as a percent—five means five percent per year, not a decimal 0.05 unless you truly intend five hundredths of a percent; aliases annual_rate, interest_rate, and annual_percent map to the same field. rate must be from zero through one hundred. A negative rate fails with invalid_input naming rate; that is a contracted error and it is not billed. years is the horizon, a finite number from zero through eighty; fractional years such as two point five are allowed, and aliases t, time, period, and duration are accepted. If years is negative, the task fails with invalid_input naming years. Each field may arrive as a JSON number or a numeric string. On success the body echoes deposit, monthly, rate, and years, reports months as twelve times years and monthly_rate as the decimal i, and returns final_balance, total_contributed, and interest rounded half-up to two decimal places for stable currency-style goldens, plus a formula string restating the closed form.
Where a savings calculator API earns its keep
Households use a savings calculator when an emergency fund, a house deposit, or a rainy-day account sits beside a standing monthly transfer and they need one number for the combined horizon. Personal-finance coaches need a deterministic oracle that rejects a negative rate or a negative period instead of silently showing a shrinking or empty balance that a buggy form might treat as success. When you later need beginning-of-month annuity-due deposits or annual rather than monthly contributions, switch to those identities rather than stretching this four-field savings contract. Product teams wire the same contract into onboarding demos so a user who types a deposit, a monthly contribution, an annual percent, and a duration sees the identical final_balance the API will later return in production tests. Keep requests small, pin rounded final_balance, total_contributed, and interest in tests, and you get reproducible savings figures for worksheets, LMS plugins, and edge workers without standing up a spreadsheet service of your own.
Integration use cases
Product demos and CI fixtures
Seed banking apps and automated tests with deterministic final_balance, total_contributed, and interest that match the free browser widget byte-for-byte.
Technical questions
What does the savings calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.