Set up custom conditions and receive instant webhook notifications when rates match your criteria. Full decision context in every payload.
Stop polling for rate changes. Get notified instantly when conditions are met, with full context about why the alert triggered.
Sub-second delivery when rates change. No polling delays, no missed opportunities.
Every webhook includes a complete decision snapshot with recommendations, not just raw rate data.
Set thresholds for APR, rate, monthly payment, or percentage changes. Trigger only when it matters.
HMAC-SHA256 signatures on every webhook. Verify authenticity and prevent replay attacks.
Create a monitor with your conditions, and we'll evaluate every rate change against them. When conditions are met, your webhook fires with full context.
Define your decision context (state, loan amount, intent) and trigger conditions.
Our system continuously monitors rate changes across 5,000+ lenders.
When rates change, we evaluate your conditions against the new decision.
If conditions are met, your endpoint receives a signed webhook with the full decision snapshot.
Get your first webhook firing in under 5 minutes.
Create a free API key to authenticate your requests.
# Basic (20 requests/month)
curl -X POST https://api.rateapi.dev/keys
# With email for 50 requests/month
curl -X POST https://api.rateapi.dev/keys \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com"}'
Set up a monitor with your conditions and webhook URL.
curl -X POST https://api.rateapi.dev/v1/monitors \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "CA Rate Alert",
"decision_context": {
"state": "CA",
"intent": "purchase",
"amount": 400000
},
"conditions": [
{ "field": "apr", "operator": "lt", "value": 6.5 }
],
"webhook_url": "https://your-app.com/webhooks/rates"
}'
Save the webhook_signing_secret from the response. You'll need it to verify webhook signatures.
Use the simulation endpoint to verify your webhook handler works correctly.
Need a test endpoint? Use webhook-test.com to generate a temporary URL and inspect incoming webhook payloads.
curl -X POST https://api.rateapi.dev/v1/monitors/{monitor_id}/simulate \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rate_change": {
"state": "CA",
"product_type": "mortgage",
"previous_rate": 6.75,
"new_rate": 6.25
},
"options": { "deliver_webhook": true }
}'
Every webhook includes the full decision context, not just rate data. Here's what you'll receive:
{
"event": "decision.monitor.triggered",
"event_id": "evt_abc123def456",
"monitor_id": "mon_xyz789",
"customer_id": "key_your_api_key_id",
"evaluated_at": "2024-01-15T10:30:00Z",
"trigger_type": "condition_met",
"test": false,
"why_now": [
"Rate decreased by 0.25% in CA",
"APR 6.25% meets threshold < 6.5%",
"Estimated monthly savings: $125.50"
],
"rate_change": {
"state": "CA",
"product_type": "mortgage",
"previous_rate": 6.75,
"new_rate": 6.25,
"rate_delta": -0.5
},
"decision_snapshot": {
// Full /v1/decisions response
"request_id": "req_...",
"summary": { ... },
"actions": [ ... ],
"disclosures": [ ... ]
}
}
| Field | Type | Description |
|---|---|---|
event |
string | decision.monitor.triggered or decision.monitor.test |
event_id |
string | Unique ID for idempotency. Use for deduplication. |
trigger_type |
string | condition_met, threshold_crossed, recommendation_changed, or new_offer_detected |
why_now |
string[] | Human-readable explanations of why this alert fired |
decision_snapshot |
object | Complete /v1/decisions response at time of trigger |
test |
boolean | true if this is a simulation/test webhook |
Every webhook is signed with HMAC-SHA256. Always verify signatures before processing.
| Header | Description |
|---|---|
X-RateAPI-Signature |
HMAC-SHA256 signature of the payload |
X-RateAPI-Timestamp |
Unix timestamp when the webhook was sent |
X-RateAPI-Event-Id |
Unique event ID for idempotency |
import crypto from 'crypto';
function verifyWebhook(payload, signature, timestamp, secret) {
// Reject if timestamp is too old (5 min tolerance)
const age = Date.now() - (timestamp * 1000);
if (age > 300000) return false;
// Compute expected signature
const signedPayload = `${timestamp}.${payload}`;
const expected = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
import hmac
import hashlib
import time
def verify_webhook(payload, signature, timestamp, secret):
# Reject if timestamp is too old (5 min tolerance)
age = time.time() - int(timestamp)
if age > 300:
return False
# Compute expected signature
signed_payload = f"{timestamp}.{payload}"
expected = hmac.new(
secret.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
Define precise trigger conditions using field/operator/value combinations.
| Field | Description |
|---|---|
rate |
Base interest rate (e.g., 6.25) |
apr |
Annual Percentage Rate including fees |
monthly_payment |
Estimated monthly payment in dollars |
| Operator | Description | Example |
|---|---|---|
lt |
Less than | APR < 6.5% |
lte |
Less than or equal | Rate ≤ 6.0% |
gt |
Greater than | Rate > 5.5% |
gte |
Greater than or equal | APR ≥ 7.0% |
eq |
Equal to | Rate = 6.0% |
change_pct |
Percentage change | Rate changed by ≥ 5% |
// Alert when APR drops below 6.5%
{ "field": "apr", "operator": "lt", "value": 6.5 }
// Alert when monthly payment is under $2000
{ "field": "monthly_payment", "operator": "lt", "value": 2000 }
// Alert on significant rate movement (5%+ change)
{ "field": "rate", "operator": "change_pct", "value": 5 }
Full CRUD operations for managing your monitors.
Follow these guidelines for a robust webhook integration.
Set a cooldown (e.g., 6 hours) to prevent alert fatigue from rapid rate fluctuations.
Use event_id to deduplicate webhooks. Store processed IDs and skip duplicates.
Return 2xx within 5 seconds. Do heavy processing async to avoid timeouts.
We retry failed webhooks with exponential backoff. Design for at-least-once delivery.
Never process unsigned webhooks. Reject requests with invalid or expired signatures.
Log all webhook payloads with event_id for debugging and audit trails.