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_type—fixed|variableterm_months— 12, 24, 36, 48, 60, 84, 120insured—true|falselimit— 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/matchPOST /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.