Public Pricing API Guide

Everything an external app needs to call the rate quote API.

Manage Keys
Training another tool? Click Copy Full Guide above — it copies the complete documentation (endpoint, auth, request/response schemas, examples, error codes) as one markdown block you can paste directly.
COMPLETE API GUIDE — everything in one block
# Public Pricing API Guide

## Overview
Read-only mortgage rate quote API. Send basic loan parameters, receive up to 10 live rate options.
All pricing runs through a fixed corporate channel — internal settings cannot be overridden by callers.

## Endpoint
POST https://base44.app/api/apps/6932b9b82c3e2d87f434aa49/functions/publicPricingApi

## Authentication
Every request requires an API key, passed either as:
- HTTP header: `x-api-key: YOUR_API_KEY`  (preferred)
- OR JSON body field: `"api_key": "YOUR_API_KEY"`

Requests without a valid, active key are rejected with 401.

## Rate Limit
20 requests per minute per IP. Exceeding it returns 429.

## Request Body (JSON)
| Field | Type | Required | Rules |
|---|---|---|---|
| list_price | number | yes | Home price. 50,000 – 10,000,000 |
| down_payment | number | yes | Dollars (not %). Must be >= 0 and less than list_price |
| zipcode | string | yes | 5-digit US zip code of the property |
| credit_score | number | no | 300 – 850. Defaults to 740 |
| loan_term | number | no | Months: 120, 180, 240, 300, or 360. Defaults to 360 |

Any other fields sent are ignored. The API always prices as:
purchase, single-family home, primary residence, conforming fixed-rate, 30-day lock.

## Example Request (curl)
```bash
curl -X POST https://base44.app/api/apps/6932b9b82c3e2d87f434aa49/functions/publicPricingApi \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "list_price": 600000,
    "down_payment": 120000,
    "zipcode": "11716",
    "credit_score": 760,
    "loan_term": 360
  }'
```

## Example Request (JavaScript)
```js
const response = await fetch("https://base44.app/api/apps/6932b9b82c3e2d87f434aa49/functions/publicPricingApi", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "YOUR_API_KEY"
  },
  body: JSON.stringify({
    list_price: 600000,
    down_payment: 120000,
    zipcode: "11716",
    credit_score: 760,
    loan_term: 360
  })
});
const data = await response.json();
// data.rates[0] = best rate (lowest rate first)
```

## Success Response (200)
```json
{
  "success": true,
  "loan_amount": 480000,
  "ltv": 80,
  "rates": [
    {
      "rate": 5.375,
      "apr": 5.813,
      "points": 4.255,
      "monthly_payment": 2688,
      "monthly_mi": 0,
      "loan_term_months": 360
    }
    // ... up to 10 rate options, sorted by rate (lowest first)
  ]
}
```

### Response Fields
- `loan_amount` — list_price minus down_payment
- `ltv` — loan-to-value ratio as a percentage (e.g. 80 = 80%)
- `rates[]` — up to 10 options, sorted by rate ascending (best rate first)
  - `rate` — note rate (%)
  - `apr` — annual percentage rate (%)
  - `points` — discount points as % of loan amount (positive = cost, negative = credit)
  - `monthly_payment` — monthly principal & interest ($)
  - `monthly_mi` — monthly mortgage insurance ($, 0 when LTV <= 80%)
  - `loan_term_months` — amortization term in months

## Error Responses
| Status | Body | Meaning |
|---|---|---|
| 400 | {"error": "Invalid list_price"} | list_price missing or out of range |
| 400 | {"error": "Invalid down_payment"} | down_payment negative or >= list_price |
| 400 | {"error": "Invalid zipcode"} | zipcode not 5 digits |
| 400 | {"error": "Invalid credit_score"} | credit_score outside 300–850 |
| 400 | {"error": "Invalid request"} | body is not valid JSON |
| 401 | {"error": "Missing API key"} | no x-api-key header or api_key field |
| 401 | {"error": "Invalid API key"} | key unknown or revoked |
| 429 | {"error": "Too many requests"} | rate limit exceeded (20/min/IP) |
| 500/502/503 | {"error": "Pricing unavailable"} | upstream pricing engine unavailable — retry later |

## Integration Tips
- Always check `success === true` before reading `rates`.
- `rates[0]` is the headline/best rate.
- Treat any non-200 as a soft failure and show a "rates unavailable" state; do not retry more than once per minute.
- Keep your API key server-side. Never embed it in public client-side code.
Endpoint
POST https://base44.app/api/apps/6932b9b82c3e2d87f434aa49/functions/publicPricingApi
Authentication
Every request needs an active API key from the Keys page, sent as an x-api-key header (preferred) or an api_key field in the JSON body. Rate limit: 20 requests/minute per IP.
Request Fields
FieldRequiredRules
list_priceYesHome price, $50,000 – $10,000,000
down_paymentYesDollars, ≥ 0 and less than list_price
zipcodeYes5-digit US property zip
credit_scoreNo300 – 850, defaults to 740
loan_termNoMonths: 120 / 180 / 240 / 300 / 360, defaults to 360

All other fields are ignored. Pricing is always: purchase · single-family · primary residence · conforming fixed · 30-day lock.

Example Request · curl
curl -X POST https://base44.app/api/apps/6932b9b82c3e2d87f434aa49/functions/publicPricingApi \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "list_price": 600000,
    "down_payment": 120000,
    "zipcode": "11716",
    "credit_score": 760,
    "loan_term": 360
  }'
Example Request · JavaScript
const response = await fetch("https://base44.app/api/apps/6932b9b82c3e2d87f434aa49/functions/publicPricingApi", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "YOUR_API_KEY"
  },
  body: JSON.stringify({
    list_price: 600000,
    down_payment: 120000,
    zipcode: "11716",
    credit_score: 760,
    loan_term: 360
  })
});
const data = await response.json();
// data.rates[0] = best rate (lowest rate first)
Success Response (200) · JSON
{
  "success": true,
  "loan_amount": 480000,
  "ltv": 80,
  "rates": [
    {
      "rate": 5.375,
      "apr": 5.813,
      "points": 4.255,
      "monthly_payment": 2688,
      "monthly_mi": 0,
      "loan_term_months": 360
    }
    // ... up to 10 rate options, sorted by rate (lowest first)
  ]
}
Error Responses
StatusErrorMeaning
400Invalid list_price / down_payment / zipcode / credit_scoreA field failed validation
401Missing API key / Invalid API keyKey absent, unknown, or revoked
429Too many requestsOver 20 requests/minute from one IP
500/502/503Pricing unavailableUpstream engine unavailable — retry later