Webhooks & Monitoring

Never Miss a Rate Drop

Set up custom conditions and receive instant webhook notifications when rates match your criteria. Full decision context in every payload.

On This Page

Why Use Webhooks

Stop polling for rate changes. Get notified instantly when conditions are met, with full context about why the alert triggered.

Instant Notifications

Sub-second delivery when rates change. No polling delays, no missed opportunities.

📊

Full Decision Context

Every webhook includes a complete decision snapshot with recommendations, not just raw rate data.

🎯

Precise Conditions

Set thresholds for APR, rate, monthly payment, or percentage changes. Trigger only when it matters.

🔒

Cryptographically Signed

HMAC-SHA256 signatures on every webhook. Verify authenticity and prevent replay attacks.

How It Works

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.

1

Create a Monitor

Define your decision context (state, loan amount, intent) and trigger conditions.

2

We Watch the Rates

Our system continuously monitors rate changes across 5,000+ lenders.

3

Conditions Evaluated

When rates change, we evaluate your conditions against the new decision.

4

Webhook Fires

If conditions are met, your endpoint receives a signed webhook with the full decision snapshot.

Getting Started

Get your first webhook firing in under 5 minutes.

1

Get an API Key

Create a free API key to authenticate your requests.

terminal
# 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"}'
2

Create a Monitor

Set up a monitor with your conditions and webhook URL.

create-monitor.sh
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.

3

Test Your Webhook

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.

simulate.sh
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 }
  }'

Webhook Payload

Every webhook includes the full decision context, not just rate data. Here's what you'll receive:

webhook-payload.json
{
  "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": [ ... ]
  }
}

Payload Fields

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

Webhook Signatures

Every webhook is signed with HMAC-SHA256. Always verify signatures before processing.

Security Headers

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

Verification Example (Node.js)

verify-webhook.js
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)
  );
}

Verification Example (Python)

verify_webhook.py
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)

Monitor Conditions

Define precise trigger conditions using field/operator/value combinations.

Available Fields

Field Description
rate Base interest rate (e.g., 6.25)
apr Annual Percentage Rate including fees
monthly_payment Estimated monthly payment in dollars

Available Operators

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%

Example Conditions

conditions.json
// 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 }

API Reference

Full CRUD operations for managing your monitors.

POST /v1/monitors Create a new monitor
GET /v1/monitors List all monitors
GET /v1/monitors/:id Get a specific monitor
PATCH /v1/monitors/:id Update a monitor
DELETE /v1/monitors/:id Delete a monitor
POST /v1/monitors/:id/simulate Test webhook delivery

Best Practices

Follow these guidelines for a robust webhook integration.

🕐 Use Cooldown Periods

Set a cooldown (e.g., 6 hours) to prevent alert fatigue from rapid rate fluctuations.

🔑 Implement Idempotency

Use event_id to deduplicate webhooks. Store processed IDs and skip duplicates.

⚡ Respond Quickly

Return 2xx within 5 seconds. Do heavy processing async to avoid timeouts.

🔁 Handle Retries

We retry failed webhooks with exponential backoff. Design for at-least-once delivery.

🔒 Always Verify Signatures

Never process unsigned webhooks. Reject requests with invalid or expired signatures.

📋 Log Everything

Log all webhook payloads with event_id for debugging and audit trails.