← All posts
engineeringproperty

Building a 20-endpoint property and mortgage calculator API

Mahesh Naidu·6 min read

/property has 20 endpoints split roughly into three groups: pure-computation financial calculators, static reference datasets, and one weighted scoring model. Each group has a completely different reliability profile, and we wanted that visible at the source-code level, not just in a docs page.

Every route starts with a provenance header

Most /property routes open with three comment lines before any code:

// DATA SOURCE: Static dataset — verified stamp duty / transfer tax rates by country (2024-25)
// OWNERSHIP: owned
// REFRESH STRATEGY: update annually

For a pure-computation endpoint like amortization, that block instead reads DATA SOURCE: Pure computation — loan amortization schedule and REFRESH STRATEGY: static logic, no data dependency. The point isn't decoration — it's a forcing function. Before writing the route, you have to be able to honestly answer “where does this number come from, and does it ever go stale?” A pure formula never goes stale. A 2024-25 stamp duty table does, and the header says so explicitly so we know to revisit it.

The amortization endpoint

/amortization takes loan_amount, annual_rate, and years, and computes the standard fixed-rate mortgage formula:

monthly_payment = loan_amount × r × (1+r)^n / ((1+r)^n − 1)

where r = annual_rate / 100 / 12 (monthly rate)
      n = years × 12 (number of payments)

With full_schedule=true, it returns the complete month-by-month breakdown — payment, principal portion, interest portion, and remaining balance for every single month. This is the calculation a loan officer would show you on paper, computed exactly, not estimated.

The neighborhood-score endpoint is the interesting one

Eight of the twenty endpoints are calculators or reference lookups. One —/neighborhood-score — is a weighted decision model. It takes eight factors (walkability, school quality, safety/crime, public transit, amenities, noise level, future development outlook, commute convenience) scored by the caller, applies a default weighting — safety and crime weighted highest at 0.22, school quality at 0.18, walkability at 0.12 — and returns a single composite score.

Critically, the weights aren't fixed. The endpoint accepts a buyer_profileparameter — family, young professional, retiree, or investor — and adjusts the weighting accordingly. A family profile weights school quality higher; an investor profile weights future development outlook higher. The caller can also override every weight directly if our defaults don't match their buyer's priorities. We publish the default weights in the response so nothing is a black box.

What we deliberately left out of v1

  • No live MLS or listing-feed integration — /property-search-filters returns structured filter schemas, not live listings, because licensing real listing data is a different problem with different legal terms per country.
  • Reference rates (stamp duty, capital gains, property tax) are reviewed annually, not real-time — they're tax-code data, not market data, so this matches how often the underlying rules actually change.
  • /rental-market-data uses a hand-curated benchmark dataset, refreshed quarterly, not a live listing scrape — the route comment says so directly: not a live listing feed. /rental-yieldis pure computation from the property value, rent, and expenses you pass in, so it's only as good as the numbers you give it.
Try APlicious free
One key. 34 live namespaces. 500 free calls per month — no credit card required.
Get your free API key →
← Back to all posts