---
title: "Simulate a rate change event"
method: POST
path: "/v1/monitors/{id}/simulate"
tags: ["Decision Monitors"]
---

# Simulate a rate change event

`POST /v1/monitors/{id}/simulate`

## Request

- Base URL: `https://api.rateapi.dev`
- URL: `https://api.rateapi.dev/v1/monitors/{id}/simulate`
- Auth: API key in header `X-API-Key`

Simulates a rate change event to test your monitor configuration and webhook integration. The simulation evaluates your monitor's conditions against the provided rate change and optionally delivers a test webhook.

**Simulation Options:**
- `dry_run: true` - Evaluate conditions without delivering webhook
- `deliver_webhook: false` - Skip webhook delivery
- `override_cooldown: true` (default) - Ignore cooldown for testing

**Test vs Production Webhooks:**
- Simulation webhooks have `event_type: "decision.monitor.test"`
- Production webhooks have `event_type: "decision.monitor.triggered"`
- Both include `test: true/false` field for easy identification

**Authentication required**: Pass your API key in the `X-API-Key` header.

## Path parameters

- `id` string, required

## Request body

- SimulateRequest: Request body for simulating a rate change event
  - `rate_change` SimulateRateChange, required: Simulated rate change event
    - `state` string, required: 2-letter US state code
    - `product_type` string, required: Product type (e.g., mortgage)
    - `previous_rate` number, required: Previous interest rate (percentage)
    - `new_rate` number, required: New interest rate (percentage)
    - `credit_union_id` string: Optional credit union ID for the rate change
  - `options` SimulateOptions: Options for simulation behavior
    - `deliver_webhook` boolean: Whether to deliver the webhook (default: true)
    - `dry_run` boolean: If true, evaluate conditions but don't deliver webhook (default: false)
    - `override_cooldown` boolean: Ignore cooldown period for testing (default: true)

## Response `200`

Simulation completed

- SimulateResponse: Response from simulation
  - `simulation_id` string, required: Unique simulation ID
  - `monitor_id` string, required: Monitor that was simulated
  - `evaluation` object, required: What the simulated run produced: whether the monitor would have fired, the decision behind it, how each condition scored, and the cooldown state.
    - `triggered` boolean, required: Whether all conditions were met
    - `decision` DecisionSummary, required: Summary of the decision evaluation
      - `recommended_action` 'shop_providers' | 'refinance' | 'lock_now' | 'wait_and_watch' | 'do_nothing', required: Type of recommended action
      - `confidence` number, required: Confidence score (0-1)
      - `monthly_savings` number, required: Estimated monthly savings in dollars
      - `providers` Offer[], required: Top offers from the decision
        - `rank` integer, required: Ranking within this action (1 = best offer)
        - `credit_union_id` string, required: Unique identifier for the credit union
        - `credit_union_name` string, required: Full name of the credit union
        - `credit_union_url` string, uri, nullable, required: URL to the credit union's website. Use evidence.source_url for the page proving this published rate.
        - `rateapi_url` string, uri, nullable: Link to this credit union's profile page on rateapi.dev (null if unresolvable)
        - `state` string, required: US state where credit union is located
        - `product_type` string, required: Type of mortgage product
        - `product_name` string, required: Specific product name
        - `display_name` string, nullable: Readable product label; product_name is the raw source name
        - `loan_program` string: Loan program type (e.g., conventional, FHA, VA, USDA, jumbo). Only present for mortgage products.
        - `rate` number, required: Interest rate as percentage
        - `apr` number, required: APR as percentage including fees
        - `points` number, required: Discount points required
        - `monthly_payment` number, required: Calculated monthly payment (P&I only)
        - `verification_confidence` number, nullable, required: Confidence score for rate accuracy (0-1). Null if unavailable.
        - `as_of` string, date-time, required: Observation time for this specific published rate. Alias of last_updated.
        - `last_updated` string, date-time, required: When this rate was last scraped
        - `evidence` object, required: Verbatim source proof for the published rate.
          - `source_url` string, uri, required: Credit-union page where this rate was observed.
          - `quote` string, required: Verbatim page excerpt supporting the published rate.
          - `proof_verified` true, required: Whether the retained proof passed RateAPI verification.
        - `estimated_monthly_savings` number: Estimated monthly savings vs current offer
        - `estimated_total_savings` number: Estimated total savings over loan term
        - `eligibility` Eligibility: Membership-eligibility guidance for this credit union (design doc §4). Present only when the CU has a cu_eligibility record; absent otherwise. Guidance based on public charter data and institution websites — final determination is made by the institution. Current open-world records never assert ineligibility.
          - `status` 'open_to_anyone' | 'likely_eligible' | 'eligible_via_employer' | 'eligible_via_military' | 'geo_mismatch' | 'unknown', required: Eligibility assessment. `open_to_anyone`: a documented open path matched. `likely_eligible`: positive geo, school, worship, or occupation evidence matched. `eligible_via_employer`: the supplied employer matches a verified SEG list. `eligible_via_military`: the supplied military affiliation matches. `unknown`: cannot be determined from available data, including geographic non-matches. `geo_mismatch` is retained only for wire compatibility and is not emitted from current unattested records.
          - `join_path` string: Reserved legacy field. Current person-specific offer annotations omit unbound flat join paths; use graph-backed eligibility_explanation.conditions instead.
          - `eligibility_type` string, required: Legacy field-of-membership type on flat annotations. Graph-authoritative offer annotations use the neutral value `graph` rather than a stale flat path label.
          - `confidence` number, required: Flat-record confidence for legacy annotations; graph verdict confidence when an active publication is authoritative.
          - `matched_rule` object: The concrete rule that produced a positive `status`. Explanatory only — never present on `geo_mismatch` or `unknown` (those carry no positive rule).
            - `type` 'county' | 'state' | 'employer' | 'occupation' | 'military' | 'school' | 'worship' | 'association_open', required: Exact positive rule category: geographic county/state, employer, occupation, military, school, worship, or an open association path.
            - `detail` string: Human-readable specifics of the match (e.g. the matched county name or employer entry).
        - `eligibility_explanation` EligibilityExplanation: Deterministic person-specific eligibility explanation. Action conditions and access cost are present only for the one selected graph path when overall status is conditionally_eligible.
          - `status` 'eligible' | 'conditionally_eligible' | 'possibly_eligible' | 'unknown' | 'ineligible', required: Person-specific graph vocabulary. `ineligible` is reserved for compatibility and is not emitted without a future typed closed-world attestation.
          - `reason` string, required: Deterministic sentence explaining the status.
          - `conditions` string[]: The single selected path's remaining action. Present only when overall status is conditionally_eligible; alternative OR paths are never combined.
          - `access_cost_usd` number: Known nonnegative cost of the same selected conditional graph path. Absent means unknown, not free.
          - `evidence_url` string, uri: Legacy evidence page when no graph verdict is authoritative. Omitted for graph verdicts until graph paths carry source-bound evidence.
          - `legacy_status` string: Compatibility status projected from the same verdict.
          - `source` 'graph' | 'annotation' | 'authority_unavailable' | 'absent', required: Authority that produced the explanation.
          - `publication` EligibilityPublicationRef: Exact immutable active eligibility generation evaluated for this response.
            - `publication_id` integer, required: Database identifier of the active publication.
            - `ruleset_sha256` string, required: SHA-256 digest of the complete ordered rule set.
            - `activated_at` string, date-time, required: When this generation became serving authority.
            - `proposal_coverage` EligibilityProposalCoverage: How many model-proposed claims from the source page survived evidence verification. This is not an attestation that every real-world field-of-membership path is known.
              - …
        - `true_cost` TrueCost: Total numeric ranking basis for an eligibility-evaluated offer: borrowing cost plus points plus any selected path-bound access cost. No-record offers keep this wire field absent, while the engine still uses an internal numeric baseline for total ordering.
          - `true_total_cost_usd` number, required: Borrowing cost plus points cost plus selected access cost.
          - `cost_of_borrowing_usd` number, required: Total borrowing cost over the modeled term, or the annual proxy.
          - `points_cost_usd` number, required: Dollar cost of discount points for the requested amount.
          - `access_cost_usd` number, required: Known one-time cost of the selected conditional access path; zero means none was known.
          - `basis` 'amortized_term' | 'annual_interest_proxy', required: Calculation basis used for borrowing cost.
          - `access_cost_breakdown` EligibilityAccessCost: Auditable path-bound access cost used in true-cost ranking.
            - `total_usd` number, required: Known total one-time cost of the selected access path.
            - `membership_fee_usd` number: Known membership-fee component, when path-bound.
            - `min_deposit_usd` number: Known minimum-deposit component, when path-bound.
            - `source` 'annotation' | 'graph' | 'none', required: Provenance of the cost; current personalized ranking emits only graph-bound costs.
        - `institution_context` InstitutionContext: Compact NCUA quarterly facts for relationship-aware offer comparison. Present only when explicitly requested and available.
          - `source` string, required: The dataset these institution facts came from.
          - `cycle_date` string, date, required: Quarter-end date of the call report cycle these facts describe.
          - `members` integer, nullable, required: Current members, or null when not reported.
          - `locations` integer, required: Number of branch locations reported.
          - `total_assets` number, nullable, required: Total assets in US dollars, or null when not reported.
          - `year_opened` integer, nullable, required: Year the credit union began operating, or null when not reported.
          - `services` object, required: The subset of reported services most relevant to acting on a decision.
            - `online_membership` boolean, nullable, required: True when membership can be applied for online, or null when not reported.
            - `online_loan_application` boolean, nullable, required: True when loans can be applied for online, or null when not reported.
            - `financial_counseling` boolean, nullable, required: True when financial counseling is offered, or null when not reported.
    - `conditions_matched` ConditionMatchResult, required: Detailed results for each condition check
      - `min_monthly_savings` object: How the monthly-savings threshold was evaluated: what was required, what was observed, and whether it passed.
        - `required` number: Required minimum savings
        - `actual` number: Actual calculated savings
        - `passed` boolean: Whether this condition passed
      - `min_confidence` object: How the confidence threshold was evaluated: what was required, what was observed, and whether it passed.
        - `required` number: Required minimum confidence
        - `actual` number: Actual confidence score
        - `passed` boolean: Whether this condition passed
      - `action_types` object: How the action-type filter was evaluated: which types were allowed, which was produced, and whether it passed.
        - `required` ActionType[]: Required action types
        - `actual` 'shop_providers' | 'refinance' | 'lock_now' | 'wait_and_watch' | 'do_nothing': Type of recommended action
        - `passed` boolean: Whether this condition passed
    - `cooldown_status` CooldownStatus, required: Cooldown period status
      - `would_be_blocked` boolean, required: Whether this would be blocked by cooldown in production
      - `last_triggered_at` string, date-time, nullable, required: Last time the monitor triggered
      - `cooldown_hours` integer, required: Configured cooldown hours
      - `next_eligible_at` string, date-time, nullable, required: When the monitor will next be eligible to trigger
  - `webhook_delivery` WebhookDeliveryResult: Result of webhook delivery attempt
    - `attempted` boolean, required: Whether delivery was attempted
    - `success` boolean, required: Whether delivery succeeded
    - `status_code` integer, nullable, required: HTTP status code from webhook endpoint
    - `error` string, nullable, required: Error message if delivery failed
    - `response_time_ms` number, required: Response time in milliseconds
    - `payload_preview` object, required: First 1KB of the payload sent
  - `simulated_at` string, date-time, required: When the simulation was run
  - `is_test` boolean, required: Always true for simulations

## Other responses

- `400`: Invalid request - validation errors
- `401`: Missing or invalid API key
- `404`: Monitor not found
- `429`: Rate limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/rateapi/apis/rate-api.md) · [All operations](https://skmtc.dev/rateapi/apis/rate-api/llms.txt) · [OpenAPI document](https://skmtc.dev/rateapi/apis/rate-api/revisions/06a6db76995f?raw)
