---
title: "Amortization / payoff & extra-payment schedule"
method: POST
path: "/v1/amortization"
tags: ["Data & Analytics"]
---

# Amortization / payoff & extra-payment schedule

`POST /v1/amortization`

## Request

- Base URL: `https://api.rateapi.dev`
- URL: `https://api.rateapi.dev/v1/amortization`
- Auth: API key in header `X-API-Key`

Builds a year-by-year (or month-by-month) amortization schedule for a loan: total lifetime interest, the principal/interest split per period, and a 'what if I pay $X extra/month' payoff accelerator showing months saved and interest saved. When no `rate` is supplied, the current best market rate for the state is resolved from real credit-union offers via the decision engine. The amortization math lives here as the single source of truth; the MCP `build_amortization_schedule` tool and the consumer app call this route.

**Authentication required**: Pass your API key in the `Authorization: Bearer <key>` header.

## Request body

- object
  - `loan_amount` number, required: Loan principal in dollars (must be > 0).
  - `term_months` integer, required: Loan term in months, e.g. 360 or 180 (must be > 0, cap 600).
  - `rate` number: Annual interest rate as a percent (e.g. 6.5). If omitted, the market rate is resolved from real credit-union offers via the decision engine.
  - `product_type` 'mortgage' | 'auto_loan' | 'heloc' | 'personal_loan' | 'student_loan': Loan product; required only when rate is omitted. Default mortgage.
  - `state` string: 2-letter US state code; required only when rate is omitted (for market-rate lookup).
  - `credit_score` integer: Optional borrower credit score used to qualify the market offer.
  - `extra_monthly_payment` number: Optional extra principal paid each month (>= 0). Drives the payoff-acceleration analysis.
  - `extra_one_time_payment` number: Optional one-time extra principal payment (>= 0).
  - `schedule_granularity` 'year' | 'month': Schedule row granularity. Default year.

## Response `200`

Amortization schedule with baseline totals and (when extra payments are supplied) a payoff-acceleration comparison. When the rate must be resolved from the market but no offer qualifies, `rate`/`baseline`/`monthly_payment` are null and a `reason` is returned.

- object
  - `loan_amount` number: Loan amount in US dollars.
  - `rate` number, nullable: Note rate as an annual percentage, excluding fees.
  - `rate_source` 'provided' | 'market' | 'fallback': Where the rate used in this calculation came from: `provided` if the caller supplied it, `market` if it was taken from live offers, `fallback` if neither was available and a default was used.
  - `market_lender` string, nullable: Credit union whose rate was used when the rate came from the market, or null when the caller supplied the rate.
  - `term_months` integer: Loan term in months.
  - `monthly_payment` number, nullable: Monthly principal-and-interest payment in US dollars.
  - `baseline` object, nullable: The schedule on the scheduled payment alone, or null when no rate was available.
    - `total_interest` number: Total interest paid over the full term, in US dollars.
    - `total_paid` number: Principal plus interest paid over the full term, in US dollars.
    - `payoff_months` integer: Months to pay the loan off on the scheduled payment.
  - `with_extra` object, nullable: The schedule once the extra payment is applied, or null when no extra payment was supplied.
    - `monthly_payment_total` number: Scheduled payment plus the extra payment, in US dollars.
    - `total_interest` number: Total interest paid over the full term, in US dollars.
    - `total_paid` number: Principal plus interest paid over the full term, in US dollars.
    - `payoff_months` integer: Months to pay the loan off with the extra payment applied.
    - `months_saved` integer: How many months earlier the loan is paid off.
    - `interest_saved` number: Interest avoided by paying extra, in US dollars.
  - `schedule` object[]: The amortization rows, at the requested granularity.
    - `period` integer: Sequence number of this row — the month or the year, matching the requested granularity.
    - `label` string: Human-readable name for the period, such as `Month 12` or `Year 3`.
    - `interest_paid` number: Interest paid during this period, in US dollars.
    - `principal_paid` number: Principal repaid during this period from the scheduled payment, in US dollars.
    - `extra_principal_paid` number: Principal repaid during this period from the extra payment, in US dollars.
    - `ending_balance` number: Balance remaining at the end of the period, in US dollars.
  - `reason` string: Why no schedule could be produced — present only when the response is empty because no rate was supplied and no qualifying market offer was found.
  - `assumed_defaults` object: Values filled in where the caller supplied none, so the result is reproducible.
  - `next_actions` object[]: Other endpoints or tools that are the natural next step from this result.
  - `disclosures` string[]: Statements that must be shown to a consumer alongside this result.

## Other responses

- `400`: The request was malformed — a missing required field, an unparseable body, or a parameter outside its allowed range. The `error` field names what was wrong; retrying the identical request will fail identically.
- `401`: No API key, or a key that is unknown or disabled. Send it in the `X-API-Key` header. Free keys are issued instantly by POST /keys with an email address. The response carries `WWW-Authenticate` pointing at this host's protected-resource metadata, and the `RateLimit-*` headers describing the Free-tier budget a key issued now would carry (scope `anonymous`) — a rejected request spends none of it, so `Remaining` equals `Limit`.
- `429`: Quota exhausted for the current window. `Retry-After` gives the seconds to wait; `upgradeInfo` explains how to lift the cap. Retrying before the reset will fail again and still counts as a request.

---

[API](https://skmtc.dev/rateapi/apis/rate-api.md) · [All operations](https://skmtc.dev/rateapi/apis/rate-api/llms.txt) · [OpenAPI document](https://skmtc.dev/rateapi/apis/rate-api/revisions/06a6db76995f?raw)
