---
title: "Home affordability estimate from income and DTI"
method: POST
path: "/v1/affordability"
tags: ["Data & Analytics"]
---

# Home affordability estimate from income and DTI

`POST /v1/affordability`

## Request

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

Borrower-facing home affordability estimate. Given gross annual income, existing monthly debts, down payment, and front-end/back-end DTI caps, computes max monthly payment, max loan amount, and max home price. When no rate is supplied the current best market rate for the state is resolved via the decision engine, with a 6.5% fallback. This route is the single source of truth; the MCP affordability tool and the consumer app call it.

**Authentication required**: Pass your API key in the `X-API-Key` header.

## Request body

- object
  - `income_annual` number, required: Gross annual income in dollars.
  - `monthly_debts` number: Existing monthly debt payments in dollars. Defaults to 0.
  - `down_payment` number: Down payment in dollars. Defaults to 0.
  - `front_end_dti` number: Front-end DTI cap (fraction). Defaults to 0.28.
  - `back_end_dti` number: Back-end DTI cap (fraction). Defaults to 0.36.
  - `term_months` integer: Loan term in months. Defaults to 360.
  - `state` string: 2-letter US state code. Defaults to CA.
  - `product_type` string: Defaults to 'mortgage'.
  - `rate` number: Optional rate (percent). When omitted, resolved from the live market.
  - `credit_score` integer: Optional credit score, used when resolving the market rate.

## Response `200`

Affordability estimate. `affordable` is false when existing debts exceed the back-end budget.

- object
  - `affordable` boolean: True when the borrower can support a loan at all under the debt-to-income limits.
  - `max_monthly_payment` string: Largest monthly payment the borrower can support, formatted as a US dollar string.
  - `max_loan_amount` string: Largest loan that payment supports at the rate used, formatted as a US dollar string.
  - `max_home_price` string: That loan plus the down payment, formatted as a US dollar string.
  - `down_payment` string: Down payment in US dollars.
  - `rate_used` string: The rate the calculation was run at, as an annual percentage.
  - `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.
  - `binding_constraint` 'front_end_dti' | 'back_end_dti': Which debt-to-income limit is the one actually capping the borrower: `front_end_dti` on housing costs alone, `back_end_dti` once existing debts are counted.
  - `max_payment_value` number: The same figure as `max_monthly_payment`, as a number rather than a formatted string.
  - `back_end_budget_value` number: What is left for a housing payment once existing debts are subtracted from the back-end limit, in US dollars.
  - `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.
  - `note` string: Plain-language explanation of what this result means.
  - `reason` string: Present when `affordable` is false.

## 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)
