The comparison, as JSON

Send one loan. Get back the same answer this site gives.

What they pay, against what the market would offer them. What the gap is worth a year. Which lenders would take them. What moving would cost.

A$199 a month, including GST

60,000 calls a month. No charge per call. Nothing to meter.

Want to try it first? Ask for a free key. That is 500 calls a month. Enough to build against.

The rates themselves are free

Every lender publishes its rates under the Consumer Data Right. That data is public. It is not ours, and we do not sell it.

Download the whole set. It is rebuilt every night, free, under CC BY 4.0.

What you pay for here is the reading of it. The benchmark. The fee allowance. Which lenders this borrower could actually move to. What to do about it.

A call

curl -X POST https://rategap.com.au/v1/compare \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "balance": 650000,
    "rate": 6.9,
    "years": 25,
    "propertyValue": 850000,
    "purpose": "OWNER_OCCUPIED",
    "repayment": "PRINCIPAL_AND_INTEREST"
  }'

Call it from your server, not from a browser. There is no CORS, on purpose. A key in a browser is a key anyone can read.

And the answer

{
  "action": "move",
  "rate": {
    "paying": 6.9,
    "effective": 6.9,
    "feeState": "UNKNOWN",
    "benchmark": 6.0992,
    "anchor": 6.09,
    "feeAllowance": 0.0092,
    "surplus": 0,
    "belowAnchor": false
  },
  "gapPoints":      { "backBook": 0, "switching": 0.8008 },
  "dollarsPerYear": { "backBook": 0, "switching": 5204.78 },
  "ownLender": null,
  "market": { "pool": 118, "eligible": 96, "cheaperThanYou": 91, "cheapestEligible": 5.64 },
  "targets": [
    {
      "lender": "coral-coast",
      "lenderName": "Coral Coast Bank",
      "product": "Sharp Variable Home Loan",
      "rate": 5.64,
      "comparisonRate": 5.68,
      "annualFee": 0,
      "upfrontFees": 350,
      "conditions": [],
      "link": "https://example.com/rates"
    }
  ],
  "switchCosts": {
    "ownDischarge": null,
    "dischargeBand": [250, 500],
    "upfrontBand":   [250, 1930],
    "total":         [650, 2830]
  },
  "asOf": "2026-09-09T19:50:00Z"
}

Add ?include=lines to get the full rate table behind the answer. It is large. Most callers never need it.

What you send

FieldDefaultMeaning
balancerequiredWhat is still owed, in dollars.
raterequiredThe rate being paid now, as a percentage. Anything above 25 is refused: that is a typo, not a mortgage.
years25Years remaining on the loan.
propertyValuenullWhat the property is worth. Leave it out and the LVR is unknown. Every lender then looks open, which usually overstates the choice.
purposeOWNER_OCCUPIEDOr INVESTMENT.
repaymentPRINCIPAL_AND_INTERESTOr INTEREST_ONLY.
rateTypeVARIABLEOr FIXED. If FIXED, send fixedExpiry too, or the term cannot be priced.
fixedExpirynullISO date the fixed term ends.
annualFeenullThe ongoing fee, if it is known. null means unknown. That is not the same as 0, which is a stated fact.
needsOffsetfalseWhether an offset account is required.
lendernullThe current lender, if known. This unlocks the back-book comparison: what that lender advertises to new borrowers.

Send a value we do not recognise and you get an error naming the field. The borrower's page quietly corrects those instead. A program that sends one has a bug, and answering the wrong question would hide it.

The action field

This is the one most callers want. It says what to do.

ValueMeans
sharpAt or below the benchmark. Nothing to do.
ownRing the current lender. They advertise better than this borrower is paying, and a call cannot be refused. An application can.
moveThe gap is worth an application.
askReal, but small. A phone call usually recovers this much.
holdSmaller than lenders commonly discount for asking.

The site's own headline reads this same value, from the same code. It is not a second opinion worked out for the API.

When it says no

StatusWhy
400The request could not be read. The reply names the field and what was wrong.
401No key, or an unknown one.
402The subscription was cancelled.
422Understood, but unanswerable. Either the balance exceeds the property value, or there are too few comparable loans.
429Over the monthly limit, or too many calls from one address in an hour.

Every reply carries an x-calls-remaining header. A call only counts when you get an answer. A bad request costs you nothing.

What it will not do

It will not tell anyone what to do with their money. It reports what lenders publish, and what the arithmetic says about it. Acting on that is advice. Advice needs a licence, and this does not have one.

It also keeps nothing. The loan figures you send are used to answer the call, then dropped. That is the same promise the privacy page makes for the site. All we record is which key called, and when.