LoansExpert

Developer API v1

Build on the Loans Expert rate platform

A JSON REST API over our Canadian mortgage rate sheet, matching engine, and scenario intake. Designed for comparison sites, broker back-office tools, and lead-gen partners.

Getting started

The Developer API uses bearer-token auth. Request a key by emailing hello@loansexpert.ca. Keys follow the format le_pub_ + 32 hex chars. We'll show you the plain-text key once at issue time and store only its SHA-256 hash — if you lose it, we rotate.

Every request should set:

Authorization: Bearer le_pub_<your-key>
Content-Type: application/json

Base URL: https://loansexpert.ca/api/v1

Rate limits & errors

  • Default: 60 req/min for authenticated, 30 req/min for unauthenticated (rates endpoint only).
  • Per-key overrides available — tell us your expected volume.
  • All errors return { data: null, error: { code, message, details? } }.
  • Common codes: missing_authorization, invalid_token_format, insufficient_scope, rate_limited, validation_failed.

GET /api/v1/rates

Returns the active Canadian rate sheet, ordered by rate ascending. Unauthenticated callers get a minimal view; authenticated callers with rates:read scope get the full product metadata (prepayment privilege, portability, penalty type, lender name).

Query parameters (optional):

  • product_typefixed | variable
  • term_months — 12, 24, 36, 48, 60, 84, 120
  • insuredtrue | false
  • limit — 1–50, default 20

Example:

curl -H "Authorization: Bearer le_pub_..." \
     "https://loansexpert.ca/api/v1/rates?product_type=fixed&term_months=60&limit=10"

Response (200):

{
  "data": [
    {
      "product_type": "fixed",
      "term_months": 60,
      "rate_percent": 3.94,
      "insured": false,
      "prepayment_privilege_percent": 20,
      "penalty_type": "3_months_interest",
      "portable": true,
      "lender": { "name": "First National Financial", "slug": "first-national", "lender_type": "monoline" }
    }
  ],
  "meta": { "count": 1, "authenticated": true },
  "error": null
}

POST /api/v1/match

Runs the matching engine against the active rate sheet for a specific scenario and returns ranked offers with payment + savings-vs-posted calculations pre-computed. Requiresmatch:read scope.

Request body:

{
  "mortgage_amount": 500000,
  "ltv_percent": 75,
  "is_insured": false,
  "preferred_type": "fixed",
  "preferred_term_months": 60,
  "amortization_years": 25,
  "scenario_type": "purchase"
}

Example:

curl -X POST \
     -H "Authorization: Bearer le_pub_..." \
     -H "Content-Type: application/json" \
     -d '{"mortgage_amount":500000,"ltv_percent":75,"preferred_type":"fixed","preferred_term_months":60}' \
     https://loansexpert.ca/api/v1/match

POST /api/v1/scenarios

Submits a consumer scenario (lead) for a licensed broker to follow up on. Resolves the consumer by email (creates if missing) and returns a claim URL the end-user can visit to take ownership. Requires scenarios:write scope.

Request body:

{
  "email": "consumer@example.com",
  "first_name": "Sam",
  "last_name": "Tan",
  "phone": "604-555-0199",
  "scenario_type": "renewal",
  "mortgage_amount": 500000,
  "property_value": 750000,
  "property_province": "BC",
  "gross_annual_income": 140000
}

Response (201):

{
  "data": {
    "id": "3b3b...-...",
    "consumer_id": "acc1...-...",
    "claim_url": "https://loansexpert.ca/auth/signup?scenario=3b3b..."
  },
  "error": null
}

Scopes

  • rates:read — read the active rate sheet.
  • match:read — run the matching engine.
  • scenarios:write — submit consumer scenarios.

Scopes are additive and issued per-key. Tell us which ones you need when you request access.

Status & SLA

The API is in public v1. We commit to:

  • Additive-only changes within v1. Breaking changes get a v2 path.
  • 99.5 % monthly uptime (best-effort on Vercel).
  • 30 days deprecation notice for any field removal or scope rename.

API use requires a signed partnership agreement. Questions? hello@loansexpert.ca.