RateAPI — live US mortgage, auto, HELOC, personal & deposit rates
Was dieses MCP kann
Supplies live US lending and deposit rates, financing comparisons, affordability and amortization calculations, eligibility checks, and rate monitoring.
Tools
Eingabeschema
{'type': 'object', 'required': ['id', 'recipients'], 'properties': {'id': {'type': 'string', 'description': 'Campaign id. Required.'}, 'recipients': {'type': 'array', 'items': {'type': 'object', 'required': ['email'], 'properties': {'name': {'type': 'string'}, 'email': {'type': 'string'}}}, 'description': 'Recipients to add.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'added': {'type': 'number', 'description': 'Recipients newly inserted by this call.'}, 'total': {'type': 'number', 'description': 'Total recipients on the campaign afterwards (capped at 200).'}}, 'description': 'Counts after adding recipients. Duplicates within the request and addresses already on the campaign are skipped, so `added` can be lower than the number submitted.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['home_price', 'monthly_rent'], 'properties': {'rate': {'type': 'number', 'description': 'Annual interest rate, e.g. 6.5. If omitted, best market rate for the state is used.'}, 'state': {'type': 'string', 'description': '2-letter US state code for the market-rate lookup. Default CA.'}, 'pmi_rate': {'type': 'number', 'description': 'Annual PMI as % of loan balance. Default 0.5, applied only when LTV > 80%.'}, 'home_price': {'type': 'number', 'description': 'Purchase price in dollars. Required.'}, 'monthly_hoa': {'type': 'number', 'description': 'HOA dues in dollars/month. Default 0.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months. Default 360.'}, 'down_payment': {'type': 'number', 'description': 'Cash down payment in dollars. Default 20% of home_price.'}, 'monthly_rent': {'type': 'number', 'description': 'Current monthly rent in dollars. Required.'}, 'annual_insurance': {'type': 'number', 'description': 'Homeowners insurance in dollars/year. Default max(800, 0.35% of home price).'}, 'closing_cost_pct': {'type': 'number', 'description': 'Buying closing costs as % of home price. Default 3.0.'}, 'maintenance_rate': {'type': 'number', 'description': 'Annual maintenance as % of home value. Default 1.0.'}, 'rent_growth_rate': {'type': 'number', 'description': 'Annual rent growth as %. Default 3.0.'}, 'selling_cost_pct': {'type': 'number', 'description': 'Selling costs as % of sale price. Default 6.0.'}, 'marginal_tax_rate': {'type': 'number', 'description': 'Marginal tax rate as %, used to model mortgage-interest/property-tax deduction. Default 0 (no deduction).'}, 'property_tax_rate': {'type': 'number', 'description': 'Annual property tax as % of home value. Default 1.1.'}, 'holding_period_years': {'type': 'number', 'description': 'How many years you plan to own. Default 7.'}, 'home_appreciation_rate': {'type': 'number', 'description': 'Annual home appreciation as %. Default 3.0.'}, 'investment_return_rate': {'type': 'number', 'description': 'Opportunity cost return on invested savings as %. Default 5.0.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'buy': {'type': 'object', 'properties': {'monthly_piti': {'type': ['number', 'null'], 'description': 'Total monthly housing cost in dollars when buying: principal, interest, taxes, insurance, plus PMI, HOA, and maintenance where modeled.'}, 'year_by_year': {'type': 'array', 'description': 'One entry per year of the holding period, tracking equity, home value, loan balance, and cumulative cost in dollars.'}, 'monthly_breakdown': {'type': 'object', 'description': 'The monthly cost split into principal_interest, tax, insurance, pmi, hoa, and maintenance, each in dollars.'}, 'net_proceeds_at_sale': {'type': ['number', 'null'], 'description': 'Cash in dollars left after selling at the end of the period and paying off the loan and selling costs.'}, 'net_cost_after_equity': {'type': ['number', 'null'], 'description': 'True cost of owning in dollars: total paid less the proceeds recovered at sale. This is the figure to compare with renting.'}, 'total_cost_over_period': {'type': ['number', 'null'], 'description': 'All dollars paid out while owning over the holding period, including the down payment and monthly costs.'}, 'year_by_year_truncated_from': {'type': ['number', 'null'], 'description': 'Full number of years modeled before the array above was shortened for display. Null when nothing was omitted.'}}, 'description': 'The full economics of buying over the holding period.', 'additionalProperties': True}, 'rent': {'type': 'object', 'properties': {'year_by_year': {'type': 'array', 'description': 'One entry per year, with the annual rent and cumulative cost in dollars as rent escalates.'}, 'starting_monthly_rent': {'type': ['number', 'null'], 'description': 'Monthly rent in dollars at the start of the period, before the assumed annual increases.'}, 'total_cost_over_period': {'type': ['number', 'null'], 'description': 'All rent paid in dollars over the holding period.'}, 'year_by_year_truncated_from': {'type': ['number', 'null'], 'description': 'Full number of years modeled before the array above was shortened. Null when nothing was omitted.'}, 'opportunity_value_of_invested_savings': {'type': ['number', 'null'], 'description': 'Dollars the renter is assumed to accumulate by investing the down payment and any monthly difference — this is credited to the rent side.'}}, 'description': 'The full economics of renting over the same holding period.', 'additionalProperties': True}, 'breakeven': {'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Plain-English statement of the crossover and whether it falls inside the modeled horizon.'}, 'year': {'type': ['number', 'null'], 'description': 'Year in which buying becomes cheaper than renting. Null when it never does within the horizon.'}, 'months': {'type': ['number', 'null'], 'description': 'The same crossover expressed in months from the start.'}}, 'description': 'When buying overtakes renting on the assumptions used.', 'additionalProperties': True}, 'rate_used': {'type': ['number', 'null'], 'description': 'Mortgage rate in percent used for the buy path (6 = 6.00%). Check rate_source to see whether it was supplied or resolved from live market data.'}, 'confidence': {'type': ['string', 'null'], 'description': "Qualitative confidence in the recommendation — 'high' when the margin is wide relative to the assumptions."}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'rate_source': {'type': ['string', 'null'], 'description': "Where rate_used came from: 'provided' means the caller supplied it, 'market' means it was resolved from the best live published rate for this state and product."}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'summary_note': {'type': ['string', 'null'], 'description': 'One-sentence bottom line with the dollar gap between the two paths, safe to quote.'}, 'recommendation': {'type': ['string', 'null'], 'description': "Which path the model favors on these assumptions: 'buy' or 'rent'."}, 'assumed_defaults': {'type': 'array', 'items': {'type': 'object', 'properties': {'field': {'type': ['string', 'null'], 'description': "Name of the defaulted input, e.g. 'rate', 'property_tax_rate', 'annual_insurance'."}, 'value': {'type': ['string', 'null'], 'description': 'Value used for that input, formatted as a percent or dollar string.'}, 'reason': {'type': ['string', 'null'], 'description': 'Why that value was chosen, e.g. resolved from live market data for the state or a national default.'}}, 'additionalProperties': True}, 'description': 'Every input that was defaulted rather than supplied. Rent-vs-buy swings hard on these, so surface them.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product_type', 'state', 'loan_amount'], 'properties': {'since': {'enum': ['1w', '2w', '4w'], 'type': 'string', 'description': 'Movement window (default 4w)'}, 'state': {'type': 'string', 'description': '2-letter US state code'}, 'loan_amount': {'type': 'number', 'description': 'Loan amount in dollars — drives break-even sensitivity'}, 'term_months': {'type': 'number', 'description': 'Loan term in months (default 360 for mortgage)'}, 'current_rate': {'type': 'number', 'description': "Borrower's existing or quoted rate %, enables refi-now framing"}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Loan product'}, 'closing_costs': {'type': 'number', 'description': 'Closing/refi costs in dollars (default 0)'}, 'rate_shift_bps': {'type': 'number', 'description': 'Hypothetical bps move if waiting; default derived from observed movement'}}}
Ausgabeschema
{'type': 'object', 'properties': {'now': {'type': 'object', 'properties': {'best_rate': {'type': ['number', 'null'], 'description': 'Best published rate in percent available right now for this product and state.'}, 'best_lender': {'type': ['string', 'null'], 'description': 'Credit union publishing that best rate.'}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly principal-and-interest payment in dollars at that best rate.'}}, 'description': 'The best deal available today, for comparison against waiting.', 'additionalProperties': True}, 'note': {'type': ['string', 'null'], 'description': 'A caveat about the DATA behind this call, not an error — e.g. limited rate history for that product and state, so the answer is a snapshot rather than a timing judgement. Present only when such a caveat applies; carry it into any answer.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'window': {'type': ['string', 'null'], 'description': "Lookback period used for the comparison, expressed as a short duration string such as '4w', '90d', or '180d'."}, 'movement': {'type': 'object', 'properties': {'now': {'type': 'object', 'description': 'Current market snapshot (min, median, max APR in percent, offer count, and as-of timestamp).'}, 'then': {'type': 'object', 'description': 'Market snapshot at the start of the window, for comparison against `now`. Its `count` is often much smaller because history is retention-bounded.'}, 'direction': {'type': ['string', 'null'], 'description': "Direction of the median move over the window: 'up', 'down', or 'flat'."}, 'median_delta_pct': {'type': ['number', 'null'], 'description': 'Change in the median APR over the window, in percentage points (0.25 = 25 basis points). Negative means rates fell.'}}, 'description': 'How the market has moved over the comparison window, from the earlier snapshot to now.', 'additionalProperties': True}, 'rationale': {'type': ['string', 'null'], 'description': 'Plain-English explanation of why this recommendation was reached; safe to quote to the user as the reasoning.'}, 'break_even': {'type': 'object', 'properties': {'break_even_months': {'type': ['number', 'null'], 'description': 'Months of the projected monthly saving needed to repay the cost of waiting.'}, 'net_cost_of_waiting': {'type': ['number', 'null'], 'description': 'Net dollars waiting would cost. A negative value means waiting would save money on these assumptions.'}, 'payment_swing_per_25bps': {'type': ['number', 'null'], 'description': 'Dollars the monthly payment moves for every 25 basis point change in rate; a quick sensitivity yardstick.'}}, 'description': 'How the cost of waiting nets out against the hoped-for saving.', 'additionalProperties': True}, 'confidence': {'type': ['string', 'null'], 'description': "Qualitative confidence in the recommendation — 'high', 'medium', or 'low' — driven by how much data and how large the margin is."}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}, 'wait_scenario': {'type': 'object', 'properties': {'monthly_delta': {'type': ['number', 'null'], 'description': 'Change in monthly payment in dollars if the assumed shift happens; negative means waiting would be cheaper per month.'}, 'projected_rate': {'type': ['number', 'null'], 'description': "Rate in percent implied by applying that shift to today's best rate."}, 'assumed_shift_bps': {'type': ['number', 'null'], 'description': 'Rate change in basis points the wait scenario assumes (-25 = rates fall a quarter point). Supplied by the caller, not predicted.'}, 'projected_monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly payment in dollars at the projected rate.'}}, 'description': "A what-if for waiting, built from the caller's assumed rate shift. It is a sensitivity test, not a forecast.", 'additionalProperties': True}, 'recommendation': {'type': ['string', 'null'], 'description': "The suggested move, e.g. 'buy_now' or 'wait'."}, 'assumed_defaults': {'type': 'object', 'properties': {'since': {'type': ['string', 'null'], 'description': 'Lookback window assumed for the rate-movement comparison because the caller did not supply one.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months assumed because the caller did not supply one.'}, 'closing_costs': {'type': ['number', 'null'], 'description': 'Closing costs in dollars assumed because the caller did not supply them.'}, 'rate_shift_bps': {'type': ['number', 'null'], 'description': 'Rate shift in basis points assumed for the wait scenario because the caller did not supply one.'}}, 'description': 'Inputs the caller did not supply that were filled in with defaults. State these explicitly to the user, since they drive the numbers.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product_type', 'state', 'loan_amount', 'lock_expiration_date', 'locked_rate'], 'properties': {'since': {'enum': ['1w', '2w', '4w'], 'type': 'string', 'description': 'movement window; default 4w'}, 'state': {'type': 'string', 'description': '2-letter state code'}, 'loan_amount': {'type': 'number'}, 'locked_rate': {'type': 'number', 'description': '% already locked'}, 'term_months': {'type': 'number', 'description': 'default 360'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string'}, 'float_down_bps': {'type': 'number', 'description': 'optional improvement in bps if float_down_rate omitted'}, 'float_down_cost': {'type': 'number', 'description': '$ to exercise float-down; default 0'}, 'float_down_rate': {'type': 'number', 'description': 'optional explicit floated rate %'}, 'lock_expiration_date': {'type': 'string', 'description': 'ISO date YYYY-MM-DD'}}}
Ausgabeschema
{'type': 'object', 'properties': {'lock': {'type': 'object', 'properties': {'expired': {'type': ['boolean', 'null'], 'description': 'True when the lock has already lapsed, in which case the float-down analysis no longer applies.'}, 'locked_rate': {'type': ['number', 'null'], 'description': 'Rate in percent the borrower has locked.'}, 'days_remaining': {'type': ['number', 'null'], 'description': 'Days left before the lock expires; the decision window for acting.'}, 'lock_expiration_date': {'type': ['string', 'null'], 'description': 'Date the lock expires (ISO date).'}}, 'description': "The borrower's existing rate lock and how much time is left on it.", 'additionalProperties': True}, 'note': {'type': ['string', 'null'], 'description': 'A caveat about the inputs or data behind this call, not an error — e.g. the supplied lock-expiration date is already in the past, so the economics assume a fresh re-lock at current market. Present only when such a caveat applies; carry it into any answer.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'window': {'type': ['string', 'null'], 'description': "Lookback period used for the comparison, expressed as a short duration string such as '4w', '90d', or '180d'."}, 'movement': {'type': 'object', 'properties': {'now': {'type': 'object', 'description': 'Current market snapshot (min, median, max APR in percent, offer count, and as-of timestamp).'}, 'then': {'type': 'object', 'description': 'Market snapshot at the start of the window, for comparison against `now`. Its `count` is often much smaller because history is retention-bounded.'}, 'direction': {'type': ['string', 'null'], 'description': "Direction of the median move over the window: 'up', 'down', or 'flat'."}, 'median_delta_pct': {'type': ['number', 'null'], 'description': 'Change in the median APR over the window, in percentage points (0.25 = 25 basis points). Negative means rates fell.'}}, 'description': 'How the market has moved over the comparison window, from the earlier snapshot to now.', 'additionalProperties': True}, 'rationale': {'type': ['string', 'null'], 'description': 'Plain-English explanation of why this recommendation was reached; safe to quote to the user as the reasoning.'}, 'confidence': {'type': ['string', 'null'], 'description': "Qualitative confidence in the recommendation — 'high', 'medium', or 'low' — driven by how much data and how large the margin is."}, 'float_down': {'type': 'object', 'properties': {'worth_it': {'type': ['boolean', 'null'], 'description': 'True when the float-down clears its cost on these assumptions.'}, 'net_benefit': {'type': ['number', 'null'], 'description': 'Lifetime savings less the float-down fee, in dollars — the honest headline number.'}, 'projected_rate': {'type': ['number', 'null'], 'description': 'Rate in percent the borrower would move to by floating down.'}, 'float_down_cost': {'type': ['number', 'null'], 'description': 'Fee in dollars the lender charges to exercise the float-down.'}, 'monthly_savings': {'type': ['number', 'null'], 'description': 'Dollars per month saved at the improved rate.'}, 'lifetime_savings': {'type': ['number', 'null'], 'description': 'Total interest in dollars saved over the full term, before the float-down fee.'}, 'break_even_months': {'type': ['number', 'null'], 'description': 'Months of savings needed to repay the float-down fee.'}, 'available_improvement_bps': {'type': ['number', 'null'], 'description': 'How far the market sits below the locked rate, in basis points (87.5 = 0.875 percentage points).'}}, 'description': "Economics of exercising a float-down to today's market rate.", 'additionalProperties': True}, 'market_now': {'type': 'object', 'properties': {'best_rate': {'type': ['number', 'null'], 'description': 'Best published rate in percent available right now.'}, 'best_lender': {'type': ['string', 'null'], 'description': 'Credit union publishing that best rate.'}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly principal-and-interest payment in dollars at that best rate.'}}, 'description': 'Best deal currently available in the market, for comparison against the locked rate.', 'additionalProperties': True}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}, 'recommendation': {'type': ['string', 'null'], 'description': "The suggested move, e.g. 'exercise_float_down', 'hold_lock', or 'relock'."}, 'assumed_defaults': {'type': 'object', 'properties': {'since': {'type': ['string', 'null'], 'description': 'Lookback window assumed for the rate-movement comparison because the caller did not supply one.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months assumed because the caller did not supply one.'}, 'closing_costs': {'type': ['number', 'null'], 'description': 'Closing costs in dollars assumed because the caller did not supply them.'}, 'float_down_cost': {'type': ['number', 'null'], 'description': 'Float-down fee in dollars assumed because the caller did not supply one.'}}, 'description': 'Inputs the caller did not supply that were filled in with defaults. State these explicitly to the user, since they drive the numbers.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['scenarios'], 'properties': {'state': {'type': 'string', 'description': 'Optional 2-letter default state applied to scenarios lacking one'}, 'scenarios': {'type': 'array', 'items': {'type': 'object', 'required': ['product_type', 'intent', 'amount'], 'properties': {'id': {'type': 'string', 'description': 'Caller correlation id, echoed back'}, 'state': {'type': 'string', 'description': 'Overrides top-level state'}, 'amount': {'type': 'number'}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string'}, 'term_months': {'type': 'number'}, 'credit_score': {'type': 'number', 'description': 'Overrides top-level credit_score'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'personal_loan', 'heloc', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string'}, 'down_payment_percent': {'type': 'number'}}}, 'maxItems': 25, 'minItems': 1, 'description': 'Inline scenarios to score in one stateless call (no persisted cohorts).'}, 'credit_score': {'type': 'number', 'description': 'Optional default credit score applied to scenarios lacking one'}, 'max_providers': {'type': 'number', 'description': 'Top-N offers returned per scenario (default 3)'}}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of scenarios evaluated in this batch.'}, 'totals': {'type': 'object', 'properties': {'scenarios_no_offer': {'type': ['number', 'null'], 'description': 'How many scenarios found nothing; those results carry no pricing and should not be reported as expensive.'}, 'scenarios_with_offer': {'type': ['number', 'null'], 'description': 'How many scenarios found at least one live offer.'}}, 'description': 'Batch-level tallies across all scenarios.', 'additionalProperties': True}, 'results': {'type': 'array', 'items': {'type': 'object', 'properties': {'id': {'type': ['string', 'null'], 'description': "The caller's own identifier for this scenario, used to match results back to inputs."}, 'rank': {'type': ['number', 'null'], 'description': 'Ranking of this scenario against the others in the batch, 1 = strongest opportunity.'}, 'index': {'type': ['number', 'null'], 'description': 'Zero-based position of this scenario in the submitted array.'}, 'offers': {'type': 'array', 'description': 'All ranked offers found for this scenario, each with rank, lender, APR, rate, and monthly payment.'}, 'status': {'type': ['string', 'null'], 'description': "Whether the scenario resolved: 'ok' means offers were found; other values mean no usable pricing."}, 'best_offer': {'type': 'object', 'description': 'The single best offer for this scenario, with lender, APR and rate in percent, and monthly payment in dollars.'}, 'recommended_action': {'type': ['string', 'null'], 'description': "Recommended move for this scenario, e.g. 'shop_providers'."}}, 'additionalProperties': True}, 'description': 'One result per scenario, ordered by rank rather than by the order submitted — match them back with `id`.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['loan_amount', 'term_months'], 'properties': {'rate': {'type': 'number', 'description': 'Annual interest rate as a percent (e.g. 6.5). If omitted, the market rate is resolved from real credit-union offers via the decision engine.'}, 'state': {'type': 'string', 'description': '2-letter US state code; required only when rate is omitted (for market-rate lookup).'}, 'loan_amount': {'type': 'number', 'description': 'Loan principal in dollars (required, > 0).'}, 'term_months': {'type': 'number', 'description': 'Loan term in months, e.g. 360 or 180 (required).'}, 'credit_score': {'type': 'number', 'description': 'Optional borrower credit score used to qualify the market offer.'}, 'product_type': {'enum': ['mortgage', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Loan product; required only when rate is omitted. Default mortgage.'}, 'schedule_granularity': {'enum': ['year', 'month'], 'type': 'string', 'description': 'Schedule row granularity. Default year.'}, 'extra_monthly_payment': {'type': 'number', 'description': 'Optional extra principal paid each month. Drives the payoff-acceleration analysis (months saved, interest saved).'}, 'extra_one_time_payment': {'type': 'number', 'description': 'Optional one-time extra principal payment.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'rate': {'type': ['number', 'null'], 'description': 'Annual note rate in percent used for the schedule.'}, 'reason': {'type': ['string', 'null'], 'description': 'Why no schedule could be built, present only in that case — e.g. no qualifying market offer for that product and state, in which case supply an explicit rate and retry.'}, 'baseline': {'type': 'object', 'properties': {'total_paid': {'type': ['number', 'null'], 'description': 'Principal plus interest in dollars over the full term.'}, 'payoff_months': {'type': ['number', 'null'], 'description': 'Months to payoff on the scheduled payment, equal to the term.'}, 'total_interest': {'type': ['number', 'null'], 'description': 'Total interest in dollars over the full term with scheduled payments only.'}}, 'description': 'The loan as scheduled, with no extra payments.', 'additionalProperties': True}, 'schedule': {'type': 'array', 'items': {'type': 'object', 'properties': {'label': {'type': ['string', 'null'], 'description': "Human-readable label for the row, e.g. 'Year 1'."}, 'period': {'type': ['number', 'null'], 'description': 'Sequential index of this row: month number or year number depending on the granularity requested.'}, 'interest_paid': {'type': ['number', 'null'], 'description': 'Interest in dollars paid during this period.'}, 'ending_balance': {'type': ['number', 'null'], 'description': 'Loan balance in dollars remaining at the end of this period.'}, 'principal_paid': {'type': ['number', 'null'], 'description': 'Scheduled principal in dollars retired during this period; it grows every period as interest falls.'}, 'extra_principal_paid': {'type': ['number', 'null'], 'description': 'Additional principal in dollars paid during this period beyond the scheduled payment.'}}, 'additionalProperties': True}, 'description': 'The amortization rows at the requested granularity (per month or per year).'}, 'with_extra': {'type': 'object', 'properties': {'total_paid': {'type': ['number', 'null'], 'description': 'Principal plus interest in dollars under the accelerated schedule.'}, 'months_saved': {'type': ['number', 'null'], 'description': 'Months knocked off the payoff by the extra payment.'}, 'payoff_months': {'type': ['number', 'null'], 'description': 'Months to payoff with the extra payment, shorter than the scheduled term.'}, 'interest_saved': {'type': ['number', 'null'], 'description': 'Interest in dollars avoided by the extra payment — the headline benefit.'}, 'total_interest': {'type': ['number', 'null'], 'description': 'Total interest in dollars paid when the extra payment is made every month.'}, 'monthly_payment_total': {'type': ['number', 'null'], 'description': 'Total monthly outlay in dollars including the extra principal.'}}, 'description': "The same loan with the caller's extra monthly principal payment applied.", 'additionalProperties': True}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'loan_amount': {'type': ['number', 'null'], 'description': 'Principal in dollars the schedule amortizes.'}, 'rate_source': {'type': ['string', 'null'], 'description': "Where rate_used came from: 'provided' means the caller supplied it, 'market' means it was resolved from the best live published rate for this state and product."}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months (360 = 30 years, 180 = 15 years, 60 = 5 years).'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'market_lender': {'description': 'Credit union whose published rate was used when the rate came from market data. Null when the caller supplied the rate.'}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Scheduled principal-and-interest payment in dollars, excluding any extra payment.'}, 'assumed_defaults': {'type': 'object', 'properties': {'schedule_granularity': {'type': ['string', 'null'], 'description': "Row granularity used, 'year' or 'month'."}, 'extra_monthly_payment': {'type': ['number', 'null'], 'description': 'Extra monthly principal in dollars assumed when the caller did not specify it.'}}, 'description': 'Inputs the caller did not supply that were filled in with defaults. State these explicitly to the user, since they drive the numbers.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['scenario'], 'properties': {'scenario': {'type': 'object', 'required': ['product_type', 'state', 'amount', 'term_months'], 'properties': {'state': {'type': 'string', 'description': 'US state code (2-letter).'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars.'}, 'intent': {'type': 'string', 'description': 'The loan intent (purchase/refinance/etc.).'}, 'term_months': {'type': 'number', 'description': 'Loan term in months.'}, 'credit_score': {'type': 'number', 'description': "Borrower's credit score (300-850)."}, 'monthly_debt': {'type': 'number', 'description': "Borrower's existing monthly debt payments in dollars."}, 'product_type': {'enum': ['auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'mortgage', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product.'}, 'monthly_income': {'type': 'number', 'description': "Borrower's gross monthly income in dollars."}}, 'description': 'The borrower scenario.'}, 'recommendation': {'type': 'object', 'properties': {'apr': {'type': 'number', 'description': 'Recommended APR as a percentage.'}, 'rate': {'type': 'number', 'description': 'Recommended rate as a percentage.'}, 'monthly_payment': {'type': 'number', 'description': 'Recommended monthly payment in dollars.'}}, 'description': 'Optional recommended offer to evaluate.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'flags': {'type': 'array', 'items': {'type': 'object', 'properties': {'code': {'type': ['string', 'null'], 'description': "Machine-readable identifier of the rule that fired, e.g. 'dti_exceeds_50'."}, 'level': {'type': ['string', 'null'], 'description': "Severity of the flag: 'red' blocks the recommendation, lower levels warn without stopping it."}, 'message': {'type': ['string', 'null'], 'description': 'Plain-English explanation of the problem and the threshold that was breached; quote this rather than paraphrasing it.'}}, 'additionalProperties': True}, 'description': 'Guardrail violations found in the proposed recommendation. An empty array means nothing was tripped.'}, 'overall': {'type': ['string', 'null'], 'description': "Aggregate verdict on the proposed recommendation: 'stop' when a red flag blocks it, otherwise a pass or caution outcome."}, 'disclaimers': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Statements that must be attached to any advice built on this scenario, such as that this is not financial advice and not an offer of credit.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'product', 'rate'], 'properties': {'apr': {'type': 'number', 'description': "The lender's published APR. Optional — falls back to rate."}, 'rate': {'type': 'number', 'description': "The lender's OWN published note rate as a percentage (e.g. 6.49). Required."}, 'state': {'type': 'string', 'description': 'US state code (2-letter, e.g. CA, TX). Required.'}, 'product': {'enum': ['30yr_fixed', '15yr_fixed'], 'type': 'string', 'description': 'Mortgage product the lender publishes. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Ready-to-quote sentence stating how this offer ranks against live offers and by how many basis points.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'market': {'type': 'object', 'properties': {'max': {'type': ['number', 'null'], 'description': 'Highest APR, in percent, among the live offers in this segment.'}, 'min': {'type': ['number', 'null'], 'description': 'Lowest APR, in percent, among the live offers in this market segment — the single best published deal, not a typical one.'}, 'as_of': {'type': ['string', 'null'], 'description': 'UTC timestamp of the newest rate in the market comparison set.'}, 'count': {'type': ['number', 'null'], 'description': 'Number of live published offers the min/median/max were computed from. Small counts make the median unreliable.'}, 'median': {'type': ['number', 'null'], 'description': "Median APR, in percent, across the live offers in this segment; the fairest single number to describe 'the market'."}}, 'description': 'Distribution of live offers this position was measured against.', 'additionalProperties': True}, 'product': {'type': ['string', 'null'], 'description': "Product key the offer was compared against, e.g. '30yr_fixed'."}, 'verdict': {'type': ['string', 'null'], 'description': "Qualitative placement of the offer against the market, e.g. 'competitive', 'above_market', 'market_leading'."}, 'percentile': {'type': ['number', 'null'], 'description': 'Where this offer sits in the market distribution, 0-100, lower being cheaper. 43 means about 43% of live offers are cheaper than it.'}, 'your_offer': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': 'The supplied APR in percent, including fees; this is what the percentile is computed on.'}, 'rate': {'type': ['number', 'null'], 'description': 'The supplied note rate in percent, excluding fees.'}}, 'description': 'The rate and APR the caller supplied for comparison.', 'additionalProperties': True}, 'bps_vs_median': {'type': ['number', 'null'], 'description': 'Distance from the market median in basis points (-4 = 4 basis points below, i.e. better than median).'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['credit_union_ids'], 'properties': {'zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit ZIP or ZIP+4. Resolves to a county server-side; when state is supplied, the ZIP crosswalk must agree with it."}, 'state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "User's valid 50-state/DC code for geographic field-of-membership matching. Lowercase is accepted and normalized."}, 'county': {'type': 'string', 'description': "User's home county for residence matching. Original name; home_county is an equivalent merge-and-retry alias."}, 'school': {'type': 'string', 'description': "User's school/college/university. Supply school_relationship too; the school name alone does not affirm eligibility."}, 'worship': {'type': 'string', 'description': "User's place of worship, matched against worship-org affinity lists (yields likely_eligible)."}, 'employer': {'type': 'string', 'description': "User's employer, matched against credit union employer/SEG membership lists."}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Alias for zip, accepted so missing_facts can be merged into this same tool request. It must agree with state/home_state when either is supplied; conflicting duplicate forms are rejected.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit work ZIP or ZIP+4. Resolves to a work county server-side; when work_state is supplied, the crosswalk must agree with it."}, 'home_city': {'type': 'string', 'description': "User's Census-recognized home city. Requires state or a recognized zip that uniquely identifies one state; unresolved labels are rejected rather than guessed."}, 'work_city': {'type': 'string', 'description': 'Census-recognized city where the user works. Requires work_state or a recognized work_zip that uniquely identifies one state.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Alias for state, accepted so missing_facts can be merged into this same tool request. Conflicting duplicate forms are rejected.'}, 'occupation': {'type': 'string', 'description': "User's occupation, matched against trade/industry/profession (TIP) charters."}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC code where the user works, for work-area membership matching. Lowercase is accepted and normalized.'}, 'home_county': {'type': 'string', 'description': 'Alias for county, accepted so missing_facts can be merged into this same tool request. Conflicting duplicate forms are rejected.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "ZIP from which the user's employer issues payroll. This is distinct from the worksite ZIP."}, 'work_county': {'type': 'string', 'description': 'County where the user works, for work-area membership matching.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "ZIP where the user's business maintains a location. Distinct from the worksite ZIP."}, 'payroll_city': {'type': 'string', 'description': 'Census-recognized payroll city. Requires payroll_state or a recognized payroll_zip that uniquely identifies one state.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the user OWNS REAL PROPERTY. A door of its own — never inferred from where they live, and an absentee owner qualifies.'}, 'facility_city': {'type': 'string', 'description': "Census-recognized city where the user's business maintains a location. Requires facility_state or a recognized facility_zip that uniquely identifies one state."}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "Valid state code from which the user's employer issues payroll. This is distinct from work_state."}, 'property_city': {'type': 'string', 'description': 'Census-recognized city where the user owns real property. Requires property_state or a recognized property_zip that uniquely identifies one state.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant IS. Some charters admit entities as well as people. Absent means a natural person; a person is never rejected by an entity-only door, only left unknown.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "State where the user's business maintains a location."}, 'payroll_county': {'type': 'string', 'description': "County from which the user's employer issues payroll. This is distinct from work_county."}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State where the user owns real property. Distinct from home_state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids selected through resolve_eligibility_entities; never populate these from prose extraction.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'description': "County where the user's business maintains a location."}, 'family_relation': {'type': 'string', 'description': "How the user relates to a RELATIVE whose own affiliations may qualify them (e.g. 'spouse', 'child', 'immediate family'). Required alongside relative_employers/relative_schools/relative_associations — without it there is nobody for those organizations to belong to. Many SEG lists read 'Employees of the following companies AND THEIR IMMEDIATE FAMILIES are eligible'; this is how that door is answered."}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': "User's military affiliation, matched against military field-of-membership (yields eligible_via_military)."}, 'property_county': {'type': 'string', 'description': 'County where the user owns real property. Distinct from home_county.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical worship-organization ids selected through resolve_eligibility_entities.', 'uniqueItems': True}, 'credit_union_ids': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 50, 'minItems': 1, 'description': 'Credit union ids to check (1-50), e.g. from get_financing_decision offers or list_credit_unions. Required.'}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids selected through resolve_eligibility_entities. The API revalidates entity type and active-publication authority before use.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Schools the RELATIVE named by family_relation attends. Optional; same unknown-by-default contract as relative_employers.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string'}, 'description': "Employers of the RELATIVE named by family_relation (not the user's own employer). Optional; omitting it leaves compound family doors undecided (unknown), never negative."}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids selected through resolve_eligibility_entities; each is type- and publication-revalidated.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the user relates to the named school. Required with school to affirm a typed student, alumni, or school-employee path.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string'}, 'relation': {'type': 'string', 'description': "The relative's relationship to the applicant."}, 'credit_union_id': {'type': 'string', 'description': 'The exact target credit union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships scoped to one exact credit union. A membership at one institution is never reused for another; omit unconfirmed memberships and the corresponding family door remains unknown.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Associations the RELATIVE named by family_relation belongs to. Optional; same unknown-by-default contract as relative_employers.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'The state the user serves, or served, in. State National Guard doors ("Oklahoma National Guard") need this; without it such a door reads unknown.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 20, 'description': 'Narrowings the user asserts about themselves, quoted back from a missing_facts question (e.g. "assigned as Recruiters or ROTC Instructors within the State of Arkansas"). Absence caps a narrowed door rather than closing it.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Required caveat that eligibility is guidance from published criteria and the credit union makes the final decision.'}, 'engine': {'type': ['string', 'null'], 'description': '`eligibility_publication_v1` when at least one verdict was decided from an exact active publication; `legacy+graph_shadow` for compatibility output.'}, 'checked': {'type': ['number', 'null'], 'description': 'Number of credit unions evaluated in this call, matching the length of `verdicts`.'}, 'summary': {'type': ['string', 'null'], 'description': 'One-sentence plain-English summary of this result, safe to quote directly to the user.'}, 'verdicts': {'type': 'array', 'items': {'type': 'object', 'properties': {'graph': {'type': 'object', 'properties': {'paths': {'type': 'array', 'items': {'type': 'object', 'properties': {'reason': {'type': ['string', 'null'], 'description': 'Neutral deterministic explanation of the path outcome.'}, 'status': {'type': ['string', 'null'], 'description': 'Path outcome; reserved `ineligible` instances are normalized to `unknown` without a typed closed-world attestation.'}, 'conditional_on': {'type': 'object', 'description': 'Action that unlocks a proven conditional path. Present only when both the graph verdict and this path are conditionally_eligible.', 'additionalProperties': True}, 'unknown_reason': {'type': ['string', 'null'], 'description': 'Machine-readable open-world reason, including `fom_completeness_unaffirmed`.'}, 'conditions_matched': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Conditions proven on this path. A pending conditional action is never labelled matched; the array resets to empty when a failed or non-winning path is neutralized.'}, 'conditions_unknown': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Conditions still unresolved on a non-negative path. Omitted when a failed path is neutralized.'}}, 'additionalProperties': True}, 'description': 'Structured membership-path evaluations. Unattested negatives and alternate paths that did not produce the overall verdict are retained only as actionless `unknown` diagnostics with neutral wording.'}, 'status': {'enum': ['eligible', 'conditionally_eligible', 'possibly_eligible', 'ineligible', 'unknown'], 'type': 'string', 'description': 'Five-value wire vocabulary. `ineligible` is reserved for compatibility and is not emitted by MCP without a future typed closed-world attestation.'}, 'explain': {'type': 'string', 'description': 'Deterministic human-readable explanation of the verdict.'}, 'confidence': {'type': 'number', 'maximum': 1, 'minimum': 0, 'description': 'Confidence in the graph verdict, from 0 to 1.'}, 'publication': {'type': 'object', 'properties': {'activated_at': {'type': 'string', 'format': 'date-time', 'description': 'When this publication became serving authority.'}, 'publication_id': {'type': 'integer', 'description': 'Database identifier of the active publication.'}, 'ruleset_sha256': {'type': 'string', 'pattern': '^[0-9a-f]{64}$', 'description': "SHA-256 digest of the publication's complete ordered rule set."}, 'proposal_coverage': {'type': 'object', 'description': 'Counts of source-page model proposals that were verified, published, or withheld; not a closed-world FOM attestation.', 'additionalProperties': True}}, 'description': 'Exact immutable active publication evaluated for this verdict.'}, 'unknown_reason': {'type': 'string', 'description': 'Machine-readable reason the supplied facts or corpus could not support a positive decision.'}}, 'description': 'Deterministic eligibility-graph verdict. Its optional publication binds an authoritative active generation; without publication it is a non-authoritative compatibility shadow. Current unattested negatives are normalized to open-world `unknown` without removing the evaluated credit union.', 'additionalProperties': True}, 'status': {'type': ['string', 'null'], 'description': 'Machine-readable compatibility outcome. Only a graph carrying exact active-publication lineage is authoritative and conservatively projected here; a publication-less shadow graph cannot replace the flat result. `geo_mismatch` remains reserved and current unattested instances become `unknown`.'}, 'details': {'type': ['string', 'null'], 'description': 'Relative REST API path for the full eligibility record; an API reference, not a page to show the user.'}, 'verdict': {'type': ['string', 'null'], 'description': 'Full user-facing sentence combining the outcome and the reason; the best single field to quote.'}, 'confidence': {'type': ['number', 'null'], 'description': 'Confidence in the authoritative graph verdict when exact publication lineage is present; otherwise the legacy record confidence. Forced to 0 when publication authority is unavailable. From 0 to 1.'}, 'evidence_url': {'type': ['string', 'null'], 'description': 'Legacy record source page when no published graph authority is present. Omitted beside an authoritative published graph, and when publication authority is unavailable, because a flat URL may back an unrelated or stale path.'}, 'matched_rule': {'type': 'object', 'description': 'The specific flat rule that produced a legacy verdict. Omitted when an exact published graph is authoritative because graph paths carry the bound match provenance.'}, 'unknown_reason': {'type': ['string', 'null'], 'description': 'Machine-readable reason for `unknown`; `fom_completeness_unaffirmed` means no closed-world membership-corpus attestation exists.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE' of the credit union assessed."}, 'eligibility_type': {'type': ['string', 'null'], 'description': '`graph` when a graph carrying exact active-publication lineage is authoritative; otherwise the legacy charter shape such as community, multi, or unknown.'}, 'record_confidence': {'type': ['number', 'null'], 'description': 'Aligned to authoritative graph confidence when exact publication lineage is present; otherwise confidence in the underlying legacy eligibility record. Forced to 0 when publication authority is unavailable. From 0 to 1.'}}, 'additionalProperties': True}, 'description': 'One eligibility assessment per credit union requested, in the order supplied.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['baseline_person', 'candidate_person', 'products'], 'properties': {'products': {'type': 'array', 'items': {'type': 'object', 'required': ['product_type'], 'properties': {'amount': {'type': 'number', 'description': 'Loan or credit amount in USD.', 'exclusiveMinimum': 0}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'Transaction intent when relevant.'}, 'balance': {'type': 'number', 'minimum': 0, 'description': 'Deposit balance in USD.'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': 'Product audience.'}, 'occupancy': {'enum': ['primary', 'secondary', 'investment'], 'type': 'string', 'description': 'Property occupancy.'}, 'term_months': {'type': 'integer', 'maximum': 600, 'minimum': 1, 'description': 'Requested term in months.'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan', 'credit_card', 'savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'Exact product family.'}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'any'], 'type': 'string', 'description': 'Vehicle condition.'}}, 'description': 'Exact product request used for both eligibility-backed rate evaluation and ranking.', 'additionalProperties': False}, 'maxItems': 19, 'minItems': 1, 'uniqueItems': True}, 'total_limit': {'type': 'integer', 'maximum': 100, 'minimum': 1}, 'baseline_person': {'type': 'object', 'properties': {'school': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied school name; school_relationship is needed for a typed positive path.'}, 'worship': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied place of worship.'}, 'employer': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied employer name; use employer_org_ids after authoritative resolution.'}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Home ZIP; never inferred from another role.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Worksite ZIP, separate from home and payroll.'}, 'home_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized home city.'}, 'work_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized worksite city.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC home state.'}, 'occupation': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Person-supplied occupation.'}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC worksite state.'}, 'home_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Home county.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Payroll-origin ZIP, separate from the worksite.'}, 'work_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Worksite county.'}, 'associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations the person already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the applicant organization maintains a facility.'}, 'payroll_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized payroll-origin city.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the person owns real property; never inferred from home.'}, 'facility_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized facility city.'}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC payroll-origin state.'}, 'property_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized city where the person owns real property.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant is; absence means a natural person.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC facility state.'}, 'payroll_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Payroll-origin county.'}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC property state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit school ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the applicant organization maintains a facility.'}, 'family_relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relationship to the relative whose affiliations are supplied.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': 'Person-supplied military affiliation.'}, 'property_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the person owns real property.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit worship-organization ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit employer ids returned by resolve_eligibility_entities; rates-api revalidates type and active-publication authority.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Schools of the named relative, not the applicant.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Employers of the named relative, not the applicant.'}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit association ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the person relates to the supplied school.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string', 'description': 'Confirmed membership status.'}, 'relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relative relationship.'}, 'credit_union_id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships, each scoped to one exact institution.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations of the named relative, not the applicant.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State tied to a state-scoped military affiliation.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200, 'minLength': 1}, 'maxItems': 20, 'description': 'Narrow conditions the person explicitly asserted; never infer them.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Whether documented joinable-association actions may be considered.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids belonging to the named relative, not the applicant.', 'uniqueItems': True}}, 'description': 'Explicit caller-supplied person facts. Unknown facts stay absent; do not infer them.', 'additionalProperties': False}, 'candidate_person': {'type': 'object', 'properties': {'school': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied school name; school_relationship is needed for a typed positive path.'}, 'worship': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied place of worship.'}, 'employer': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied employer name; use employer_org_ids after authoritative resolution.'}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Home ZIP; never inferred from another role.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Worksite ZIP, separate from home and payroll.'}, 'home_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized home city.'}, 'work_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized worksite city.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC home state.'}, 'occupation': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Person-supplied occupation.'}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC worksite state.'}, 'home_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Home county.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Payroll-origin ZIP, separate from the worksite.'}, 'work_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Worksite county.'}, 'associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations the person already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the applicant organization maintains a facility.'}, 'payroll_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized payroll-origin city.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the person owns real property; never inferred from home.'}, 'facility_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized facility city.'}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC payroll-origin state.'}, 'property_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized city where the person owns real property.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant is; absence means a natural person.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC facility state.'}, 'payroll_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Payroll-origin county.'}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC property state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit school ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the applicant organization maintains a facility.'}, 'family_relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relationship to the relative whose affiliations are supplied.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': 'Person-supplied military affiliation.'}, 'property_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the person owns real property.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit worship-organization ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit employer ids returned by resolve_eligibility_entities; rates-api revalidates type and active-publication authority.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Schools of the named relative, not the applicant.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Employers of the named relative, not the applicant.'}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit association ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the person relates to the supplied school.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string', 'description': 'Confirmed membership status.'}, 'relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relative relationship.'}, 'credit_union_id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships, each scoped to one exact institution.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations of the named relative, not the applicant.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State tied to a state-scoped military affiliation.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200, 'minLength': 1}, 'maxItems': 20, 'description': 'Narrow conditions the person explicitly asserted; never infer them.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Whether documented joinable-association actions may be considered.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids belonging to the named relative, not the applicant.', 'uniqueItems': True}}, 'description': 'Explicit caller-supplied person facts. Unknown facts stay absent; do not infer them.', 'additionalProperties': False}, 'limit_per_product': {'type': 'integer', 'maximum': 10, 'minimum': 1}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'deltas': {'type': 'object', 'properties': {'products': {'type': 'array', 'items': {'type': 'object', 'properties': {'best_published_price': {'type': 'object', 'description': 'Like-for-like APY, APR, or nominal-rate comparison. APR and nominal rate are never mixed; prices and delta are null when neither measure exists on both sides.', 'additionalProperties': True}, 'reachable_now_counts': {'type': 'object', 'description': 'Exact baseline, candidate, and net reachable-now product-offer row counts.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'Selector-aligned exact count and cap-scoped identity deltas.'}, 'portfolio': {'type': 'object', 'description': 'Portfolio totals, including exact reachable_now_counts in product-offer rows.', 'additionalProperties': True}, 'completeness': {'type': 'object', 'description': 'Returned-detail identity-delta completeness disclosure.', 'additionalProperties': True}}, 'description': 'Per-product and portfolio reachability, membership-path, and published-price deltas. Per-product and portfolio reachable_now_counts contain exact baseline, candidate, and net product-offer-row counts; identity churn remains returned-detail scoped.', 'additionalProperties': True}, 'baseline': {'type': 'object', 'description': 'Full baseline access catalog.', 'additionalProperties': True}, 'snapshot': {'type': 'object', 'description': 'Pinned eligibility rules time and immutable graph generation; rates retain independent row as_of.', 'additionalProperties': True}, 'candidate': {'type': 'object', 'description': 'Full candidate access catalog.', 'additionalProperties': True}, 'semantics': {'type': ['string', 'null'], 'description': 'Positive-evidence-only interpretation; absence is not denial.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'No savings, underwriting, approval, denial, or final-terms claim.'}, 'comparison_version': {'type': ['string', 'null'], 'description': 'Stable comparison response contract version.'}}, 'description': 'Two full access catalogs and evidence-linked changes under one immutable eligibility snapshot.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'amount', 'product_types'], 'properties': {'state': {'type': 'string', 'description': 'US state code, e.g. "CA"'}, 'amount': {'type': 'number', 'description': 'Loan/credit amount in dollars'}, 'intent': {'type': 'string', 'description': 'purchase | refinance | cash_out | balance_transfer | new_credit'}, 'term_months': {'type': 'number', 'description': 'Optional loan term in months'}, 'credit_score': {'type': 'number', 'description': 'Optional borrower credit score'}, 'product_types': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Products to compare, e.g. ["mortgage","heloc"]. Any of: mortgage, mortgage_arm, auto, rv, boat, motorcycle, powersports, heloc, personal_loan, credit_card, student_loan. "mortgage" is fixed-rate and "mortgage_arm" is adjustable — comparing them side by side is meaningful, but they are never blended into one ranking. Boats/RVs/motorcycles/powersports are first-class product types; auto means cars.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Plain-English interpretation of the numbers above, already phrased for the user; quote it rather than re-deriving the comparison.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'amount': {'type': ['number', 'null'], 'description': 'Loan amount in dollars every product was priced at, so the rows are comparable.'}, 'intent': {'type': ['string', 'null'], 'description': "Borrowing purpose the pricing assumes, e.g. 'purchase' or 'refinance'."}, 'products': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['string', 'null'], 'description': 'Best APR for this product as a percent string, including fees where published; this is what the rows were ranked on.'}, 'rate': {'type': ['string', 'null'], 'description': 'Best note rate for this product as a percent string, excluding fees.'}, 'available': {'type': ['boolean', 'null'], 'description': 'True when live offers were found for this product; false means the row has no pricing rather than that the product is unattractive.'}, 'best_lender': {'type': ['string', 'null'], 'description': 'Credit union offering the best deal for this product type.'}, 'display_name': {'type': ['string', 'null'], 'description': "Normalized name of the specific product that won this row, e.g. '15-Year Fixed'. Note that the winning term may differ between rows."}, 'product_type': {'type': ['string', 'null'], 'description': "Product category for this row, e.g. 'mortgage', 'heloc'."}, 'monthly_payment': {'type': ['string', 'null'], 'description': 'Estimated monthly payment as a formatted dollar string. Payments across rows are not like-for-like when the terms differ.'}}, 'additionalProperties': True}, 'description': "One row per requested product type, each showing that product's single best lender."}, 'best_overall': {'type': ['string', 'null'], 'description': "Product type with the lowest true cost across the compared rows, e.g. 'heloc'."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['baseline_person', 'candidate_person', 'product'], 'properties': {'limit': {'type': 'integer', 'default': 10, 'maximum': 50, 'minimum': 1, 'description': 'Visible items per bucket and delta list.'}, 'product': {'type': 'object', 'required': ['product_type'], 'properties': {'amount': {'type': 'number', 'description': 'Loan or credit amount in USD.', 'exclusiveMinimum': 0}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'Transaction intent when relevant.'}, 'balance': {'type': 'number', 'minimum': 0, 'description': 'Deposit balance in USD.'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': 'Product audience.'}, 'occupancy': {'enum': ['primary', 'secondary', 'investment'], 'type': 'string', 'description': 'Property occupancy.'}, 'term_months': {'type': 'integer', 'maximum': 600, 'minimum': 1, 'description': 'Requested term in months.'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan', 'credit_card', 'savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'Exact product family.'}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'any'], 'type': 'string', 'description': 'Vehicle condition.'}}, 'description': 'Exact product request used for both eligibility-backed rate evaluation and ranking.', 'additionalProperties': False}, 'baseline_person': {'type': 'object', 'properties': {'school': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied school name; school_relationship is needed for a typed positive path.'}, 'worship': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied place of worship.'}, 'employer': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied employer name; use employer_org_ids after authoritative resolution.'}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Home ZIP; never inferred from another role.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Worksite ZIP, separate from home and payroll.'}, 'home_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized home city.'}, 'work_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized worksite city.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC home state.'}, 'occupation': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Person-supplied occupation.'}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC worksite state.'}, 'home_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Home county.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Payroll-origin ZIP, separate from the worksite.'}, 'work_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Worksite county.'}, 'associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations the person already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the applicant organization maintains a facility.'}, 'payroll_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized payroll-origin city.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the person owns real property; never inferred from home.'}, 'facility_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized facility city.'}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC payroll-origin state.'}, 'property_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized city where the person owns real property.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant is; absence means a natural person.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC facility state.'}, 'payroll_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Payroll-origin county.'}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC property state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit school ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the applicant organization maintains a facility.'}, 'family_relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relationship to the relative whose affiliations are supplied.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': 'Person-supplied military affiliation.'}, 'property_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the person owns real property.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit worship-organization ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit employer ids returned by resolve_eligibility_entities; rates-api revalidates type and active-publication authority.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Schools of the named relative, not the applicant.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Employers of the named relative, not the applicant.'}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit association ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the person relates to the supplied school.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string', 'description': 'Confirmed membership status.'}, 'relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relative relationship.'}, 'credit_union_id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships, each scoped to one exact institution.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations of the named relative, not the applicant.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State tied to a state-scoped military affiliation.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200, 'minLength': 1}, 'maxItems': 20, 'description': 'Narrow conditions the person explicitly asserted; never infer them.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Whether documented joinable-association actions may be considered.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids belonging to the named relative, not the applicant.', 'uniqueItems': True}}, 'description': 'Confirmed facts before the proposed change.', 'additionalProperties': False}, 'candidate_person': {'type': 'object', 'properties': {'school': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied school name; school_relationship is needed for a typed positive path.'}, 'worship': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied place of worship.'}, 'employer': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied employer name; use employer_org_ids after authoritative resolution.'}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Home ZIP; never inferred from another role.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Worksite ZIP, separate from home and payroll.'}, 'home_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized home city.'}, 'work_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized worksite city.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC home state.'}, 'occupation': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Person-supplied occupation.'}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC worksite state.'}, 'home_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Home county.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Payroll-origin ZIP, separate from the worksite.'}, 'work_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Worksite county.'}, 'associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations the person already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the applicant organization maintains a facility.'}, 'payroll_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized payroll-origin city.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the person owns real property; never inferred from home.'}, 'facility_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized facility city.'}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC payroll-origin state.'}, 'property_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized city where the person owns real property.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant is; absence means a natural person.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC facility state.'}, 'payroll_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Payroll-origin county.'}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC property state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit school ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the applicant organization maintains a facility.'}, 'family_relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relationship to the relative whose affiliations are supplied.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': 'Person-supplied military affiliation.'}, 'property_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the person owns real property.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit worship-organization ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit employer ids returned by resolve_eligibility_entities; rates-api revalidates type and active-publication authority.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Schools of the named relative, not the applicant.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Employers of the named relative, not the applicant.'}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit association ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the person relates to the supplied school.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string', 'description': 'Confirmed membership status.'}, 'relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relative relationship.'}, 'credit_union_id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships, each scoped to one exact institution.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations of the named relative, not the applicant.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State tied to a state-scoped military affiliation.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200, 'minLength': 1}, 'maxItems': 20, 'description': 'Narrow conditions the person explicitly asserted; never infer them.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Whether documented joinable-association actions may be considered.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids belonging to the named relative, not the applicant.', 'uniqueItems': True}}, 'description': 'Confirmed facts after the proposed change.', 'additionalProperties': False}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'deltas': {'type': 'object', 'description': 'Newly reachable, no-longer-reachable-or-unknown, changed-path, and best-offer comparisons with truncation flags.', 'additionalProperties': True}, 'product': {'type': 'object', 'description': 'Exact product request shared by both evaluations.', 'additionalProperties': True}, 'baseline': {'type': 'object', 'description': 'Eligibility-backed offer buckets for the baseline facts.', 'additionalProperties': True}, 'snapshot': {'type': 'object', 'description': 'Shared rules clock, serving-generation context, publication identities, and stated database consistency boundary.', 'additionalProperties': True}, 'candidate': {'type': 'object', 'description': 'Eligibility-backed offer buckets for the candidate facts.', 'additionalProperties': True}, 'semantics': {'type': ['string', 'null'], 'description': 'Positive-evidence-only and unknown-is-never-ineligible contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required limits on interpreting missing or changed results.'}}, 'description': 'Snapshot-consistent comparison of two caller-supplied person fact panels.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product_type', 'state', 'amount'], 'properties': {'fees': {'type': 'object', 'properties': {'flat_fees': {'type': 'number'}, 'origination_percent': {'type': 'number'}}}, 'state': {'type': 'string', 'description': '2-letter US state'}, 'amount': {'type': 'number', 'description': 'Loan principal'}, 'intent': {'enum': ['purchase', 'refinance'], 'type': 'string', 'description': 'default purchase'}, 'max_lenders': {'type': 'number', 'description': 'cap on ranked rows (default 10, max 25)'}, 'term_months': {'type': 'number'}, 'credit_score': {'type': 'number'}, 'product_type': {'enum': ['mortgage', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'personal_loan', 'heloc', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Loan product to rank'}, 'down_payment_percent': {'type': 'number'}, 'holding_period_months': {'type': 'number', 'description': 'Horizon for total-cost; defaults to term_months'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Plain-English interpretation of the numbers above, already phrased for the user; quote it rather than re-deriving the comparison.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'amount': {'type': ['number', 'null'], 'description': 'Loan amount in dollars used for every lender in the comparison.'}, 'intent': {'type': ['string', 'null'], 'description': "Borrowing purpose the pricing assumes, e.g. 'purchase' or 'refinance'."}, 'ranked': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': 'APR in percent, including fees where published.'}, 'rank': {'type': ['number', 'null'], 'description': 'Position by total cost over the holding period, 1 = cheapest.'}, 'rate': {'type': ['number', 'null'], 'description': 'Note rate in percent, excluding fees.'}, 'lender': {'type': ['string', 'null'], 'description': 'Credit union offering this loan.'}, 'total_cost': {'type': ['number', 'null'], 'description': 'Upfront fees plus interest over the holding period, in dollars — the ranking metric. It excludes principal, which is not a cost.'}, 'upfront_fees': {'type': ['number', 'null'], 'description': "Origination and lender fees in dollars paid at closing, as modeled from the caller's fee assumptions."}, 'headline_rank': {'type': ['number', 'null'], 'description': 'Where this lender would rank on headline APR alone; compare with `rank` to see when fees change the winner.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE'."}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Principal-and-interest payment in dollars per month; excludes taxes, insurance, PMI, and HOA.'}, 'credit_union_url': {'type': ['string', 'null'], 'description': "The credit union's own website."}, 'remaining_balance': {'type': ['number', 'null'], 'description': 'Loan balance in dollars still owed at the end of the holding period.'}, 'total_cost_vs_best': {'type': ['number', 'null'], 'description': 'Dollars more expensive than the cheapest lender over the holding period. 0 marks the winner.'}, 'interest_over_holding': {'type': ['number', 'null'], 'description': 'Interest in dollars paid over the holding period only, not the full term.'}, 'principal_paid_over_holding': {'type': ['number', 'null'], 'description': 'Principal in dollars retired over the holding period; this is equity built, not a cost.'}}, 'additionalProperties': True}, 'description': 'Lenders ordered cheapest-first by total cost over the holding period.'}, 'cheapest': {'type': 'object', 'properties': {'lender': {'type': ['string', 'null'], 'description': 'Name of the lowest-total-cost lender.'}, 'total_cost': {'type': ['number', 'null'], 'description': "That lender's total cost in dollars over the holding period."}}, 'description': 'The lender with the lowest total cost over the holding period.', 'additionalProperties': True}, 'reranked': {'type': ['boolean', 'null'], 'description': 'True when accounting for fees changed the winner from the headline rate leader — the key finding to surface when it is true.'}, 'ranked_by': {'type': ['string', 'null'], 'description': "The metric the list is sorted by — 'total_cost' means cheapest over the holding period, which can differ from the lowest rate."}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'rate_leader': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': "That lender's APR in percent."}, 'lender': {'type': ['string', 'null'], 'description': 'Name of the lowest-APR lender.'}}, 'description': 'The lender with the lowest headline APR, which is not always the cheapest overall.', 'additionalProperties': True}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months (360 = 30 years, 180 = 15 years, 60 = 5 years).'}, 'next_actions': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Suggested follow-up tools, as bare tool names.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}, 'holding_period_months': {'type': ['number', 'null'], 'description': 'How long the borrower is assumed to keep the loan. Total cost is measured over this period, not the full term, so a shorter hold favors low-fee lenders.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['name', 'target_credit_union', 'webhook_url'], 'properties': {'name': {'type': 'string', 'description': 'Descriptive monitor name. Required.'}, 'state': {'type': 'string', 'description': '2-letter state for the CU published rate.'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': "Scope offers by WHO they are for: 'business' returns business-audience products (DSCR mortgages, commercial vehicle loans, SBA); 'consumer' excludes them. Omit for both."}, 'occupancy': {'enum': ['primary', 'secondary', 'investment'], 'type': 'string', 'description': "MORTGAGE/HELOC: property occupancy. 'investment' returns investor / non-owner-occupied / DSCR pricing; 'secondary' second-home pricing. Omit for standard primary-residence offers."}, 'conditions': {'type': 'object', 'properties': {'min_change_bps': {'type': 'number', 'description': 'Min basis-point move to alert. Default 0.'}, 'change_direction': {'enum': ['up', 'down', 'any'], 'type': 'string'}}, 'description': 'Alert conditions on the named CU rate. Default: any change.'}, 'webhook_url': {'type': 'string', 'description': 'HTTPS webhook. Required.'}, 'loan_program': {'type': 'string', 'description': "e.g. '30-year-fixed'."}, 'product_type': {'enum': ['mortgage', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Default mortgage.'}, 'cooldown_hours': {'type': 'number', 'description': '1-168, default 24.'}, 'target_credit_union': {'type': 'object', 'properties': {'name': {'type': 'string', 'description': 'Optional human label / lookup by name.'}, 'credit_union_id': {'type': 'string', 'description': 'CU id from list_credit_unions/get_credit_union.'}}, 'description': 'The specific credit union whose published rate to watch. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'monitor': {'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Monitor id.'}, 'name': {'type': 'string', 'description': 'Caller-supplied label.'}, 'status': {'type': 'string', 'description': "Lifecycle state, typically 'active'."}, 'competitor': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'Two-letter state code.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Institution id, when resolved.'}, 'credit_union_name': {'type': ['string', 'null'], 'description': 'Institution name.'}}, 'description': 'The watched institution.', 'additionalProperties': True}, 'conditions': {'type': ['object', 'array', 'null'], 'description': 'Change-direction and minimum-bps trigger conditions.'}, 'created_at': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'target_type': {'type': 'string', 'description': "Always 'competitor' for this tool."}, 'webhook_url': {'type': ['string', 'null'], 'description': 'URL that fires on a trigger.'}, 'current_rate': {'type': ['object', 'null'], 'properties': {'apr': {'type': ['number', 'null'], 'description': 'Current APR percent.'}, 'rate': {'type': ['number', 'null'], 'description': 'Current note rate percent.'}, 'as_of': {'type': ['string', 'null'], 'description': 'ISO-8601 timestamp of the baseline rate.'}}, 'description': "The competitor's rate at creation time, the baseline for future comparisons.", 'additionalProperties': True}, 'loan_program': {'type': ['string', 'null'], 'description': 'Loan program filter, when given.'}, 'product_type': {'type': ['string', 'null'], 'description': 'Product the monitor watches.'}, 'cooldown_hours': {'type': ['number', 'null'], 'description': 'Minimum hours between triggers.'}, 'webhook_signing_secret_prefix': {'type': ['string', 'null'], 'description': 'Non-secret prefix of the signing secret, for identifying it later.'}}, 'description': 'The created competitor monitor.', 'additionalProperties': True}, 'summary': {'type': 'string', 'description': 'One-line confirmation naming the monitor and the credit union it watches.'}, 'important': {'type': 'string', 'description': 'Warning that the signing secret is shown only once.'}, 'disclosures': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Scope caveats about what this monitor does and does not alert on.'}, 'next_actions': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Suggested follow-up tool names.'}, 'webhook_signing_secret': {'type': ['string', 'null'], 'description': 'Full HMAC signing secret. Shown once, at creation.'}}, 'description': 'Result of creating a competitor-watch monitor targeting one named credit union.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['name'], 'properties': {'name': {'type': 'string', 'description': 'Campaign label. Required.'}, 'region': {'enum': ['east_coast', 'west_coast', 'midwest', 'south', 'northeast', 'southeast', 'southwest', 'mountain_west', 'new_england', 'mid_atlantic', 'pacific_northwest'], 'type': 'string', 'description': 'Named region preset (e.g. east_coast); expands server-side to its member states.'}, 'cadence': {'enum': ['daily', 'weekly', 'monthly'], 'type': 'string', 'description': 'Send cadence (default weekly).'}, 'products': {'type': 'array', 'items': {'type': 'object'}, 'description': "1-5 products to feature (no duplicates). Each is {category:'mortgage', subtype:'30-year-fixed'|'15-year-fixed'}, {category:'auto', condition:'new'|'used'|'any', term_months?:36|48|60|72|84}, or {category:'rv'|'boat'|'motorcycle', condition:'new'|'used'|'any'}."}, 'state_code': {'type': 'string', 'description': 'Legacy single 2-letter US state code (e.g. CA). Prefer state_codes or region for multi-state coverage.'}, 'state_codes': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 25, 'description': '2-letter US state codes (up to 25) — best rates are ranked ACROSS all of them, not per state.'}, 'intro_text_override': {'type': 'string', 'description': 'Per-campaign intro; falls back to branding intro_text.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Campaign id (camp_...) — pass to the other campaign tools.'}, 'name': {'type': 'string', 'description': 'Campaign label.'}, 'amount': {'type': ['number', 'null'], 'description': 'Loan amount used when pricing the featured rates.'}, 'status': {'type': ['string', 'null'], 'description': "'draft', 'active', or 'paused'. New campaigns start as 'draft'."}, 'cadence': {'type': ['string', 'null'], 'description': "'daily', 'weekly', or 'monthly'."}, 'products': {'type': ['array', 'null'], 'description': 'Parsed list of products the email covers.'}, 'created_at': {'type': ['number', 'null'], 'description': 'Epoch-ms creation time.'}, 'state_code': {'type': ['string', 'null'], 'description': 'Legacy scalar state — always the first entry of state_codes.'}, 'updated_at': {'type': ['number', 'null'], 'description': 'Epoch-ms last-modified time.'}, 'last_run_at': {'type': ['number', 'null'], 'description': 'Epoch-ms of the last send, null if never.'}, 'state_codes': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Full list of two-letter state codes the campaign covers.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Term in months.'}, 'credit_score': {'type': ['number', 'null'], 'description': 'Assumed borrower credit score.'}, 'product_type': {'type': ['string', 'null'], 'description': "Primary product type, e.g. '30-year-fixed'."}, 'region_preset': {'type': ['string', 'null'], 'description': 'Region preset key when the campaign was scoped by region, else null.'}, 'organization_id': {'type': 'string', 'description': 'Owning organization.'}, 'product_subtype': {'type': ['string', 'null'], 'description': 'Product subtype, when set.'}, 'product_category': {'type': ['string', 'null'], 'description': "'mortgage', 'auto', 'heloc', or 'personal'."}, 'intro_text_override': {'type': ['string', 'null'], 'description': 'Per-campaign intro, overriding the org default.'}}, 'description': 'The created branded rate-email campaign. Requires a Pro (tier 2+) organization.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['name', 'decision_context', 'conditions', 'webhook_url'], 'properties': {'name': {'type': 'string', 'description': 'A descriptive name for the monitor. Required.'}, 'conditions': {'type': 'array', 'items': {'type': 'object', 'required': ['field', 'operator', 'value'], 'properties': {'field': {'enum': ['rate', 'apr', 'monthly_payment'], 'type': 'string', 'description': 'The field to evaluate.'}, 'value': {'type': 'number', 'description': 'The value to compare against.'}, 'operator': {'enum': ['lt', 'lte', 'gt', 'gte', 'eq', 'change_pct'], 'type': 'string', 'description': 'Comparison operator (lt=less than, lte=less than or equal, gt=greater than, gte=greater than or equal, eq=equal, change_pct=percentage change).'}}}, 'description': 'Array of conditions that must be met to trigger the monitor. Required.'}, 'webhook_url': {'type': 'string', 'description': 'The URL to send webhook notifications to. Required.'}, 'cooldown_hours': {'type': 'number', 'description': 'Minimum hours between webhook triggers (1-168). Defaults to 24.'}, 'decision_context': {'type': 'object', 'required': ['state', 'intent', 'amount'], 'properties': {'state': {'type': 'string', 'description': 'US state code (2-letter, e.g., CA, TX, NY). Required.'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars (minimum 1000). Required.'}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'The loan intent. Required.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months (12-480). Defaults to 360 (30-year mortgage).'}, 'product_type': {'type': 'string', 'description': 'Type of loan product. Defaults to "mortgage".'}}, 'description': 'The context for evaluating rate changes. Required.'}, 'subscribed_states': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Optional array of state codes to monitor. If not provided, monitors all states.'}, 'subscribed_product_types': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Optional array of product types to monitor (e.g., ["30yr_fixed", "15yr_fixed"]).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'monitor': {'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Monitor id, used by get_monitor / update_monitor / delete_monitor.'}, 'name': {'type': 'string', 'description': 'Caller-supplied monitor label.'}, 'status': {'type': 'string', 'description': "Lifecycle state, typically 'active' or 'paused'."}, 'conditions': {'type': ['array', 'null'], 'description': 'Trigger conditions evaluated against rate changes.'}, 'created_at': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'webhook_url': {'type': ['string', 'null'], 'description': 'URL that fires when the monitor triggers.'}, 'cooldown_hours': {'type': ['number', 'null'], 'description': 'Minimum hours between two triggers of this monitor.'}, 'decision_context': {'type': ['object', 'null'], 'description': 'Stored decision context (loan amount, term, intent) used when evaluating triggers.', 'additionalProperties': True}, 'subscribed_states': {'type': ['array', 'null'], 'description': 'Two-letter state codes the monitor watches.'}, 'webhook_signing_secret': {'type': ['string', 'null'], 'description': 'HMAC secret for verifying webhook payloads. Shown only on creation.'}, 'subscribed_product_types': {'type': ['array', 'null'], 'description': 'Product types the monitor watches.'}}, 'description': 'The created monitor.', 'additionalProperties': True}, 'summary': {'type': 'string', 'description': 'One-line confirmation naming the monitor that was created.'}, 'important': {'type': 'string', 'description': 'Warning that the signing secret will not be shown again.'}}, 'description': 'Result of creating a rate monitor. The webhook signing secret is returned once and never again.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Cohort id. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'success': {'type': 'boolean', 'description': 'True when the cohort was deleted.'}}, 'description': 'Deletion acknowledgement. The route replies 204 with no body, which the client renders as a bare success flag.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'The digest id to delete.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'success': {'type': 'boolean', 'description': 'True when the digest was deleted.'}}, 'description': 'Deletion acknowledgement. The route replies 204 with no body, which the client renders as a bare success flag.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Campaign id. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'success': {'type': 'boolean', 'description': 'True when the campaign was deleted.'}}, 'description': 'Deletion acknowledgement. The route deletes the campaign and its recipients, then replies 204 with no body, which the client renders as a bare success flag.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['monitor_id'], 'properties': {'monitor_id': {'type': 'string', 'description': 'The unique identifier of the monitor to delete. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'error': {'type': ['string', 'null'], 'description': "Present and set to 'not_found' when the monitor id does not exist."}, 'deleted': {'type': 'boolean', 'description': 'True when the monitor was deleted. Absent on not-found.'}, 'summary': {'type': 'string', 'description': 'Confirmation of deletion, or a not-found message.'}, 'monitor_id': {'type': 'string', 'description': 'The id that was deleted.'}}, 'description': 'Result of deleting a monitor. On a missing id the tool returns a not-found shape instead of throwing.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Scenario id'}}}
Ausgabeschema
{'type': 'object', 'properties': {'success': {'type': 'boolean', 'description': 'True when the scenario was deleted.'}}, 'description': 'Deletion acknowledgement. The route replies 204 with no body, which the client renders as a bare success flag.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['monitor_id', 'rate_change'], 'properties': {'monitor_id': {'type': 'string', 'description': 'The unique identifier of the monitor to test. Required.'}, 'rate_change': {'type': 'object', 'required': ['state', 'product_type', 'previous_rate', 'new_rate'], 'properties': {'state': {'type': 'string', 'description': 'US state code where the rate changed. Required.'}, 'new_rate': {'type': 'number', 'description': 'The new rate value. Required.'}, 'product_type': {'type': 'string', 'description': 'The product type that changed (e.g., "30yr_fixed"). Required.'}, 'previous_rate': {'type': 'number', 'description': 'The previous rate value. Required.'}}, 'description': 'The simulated rate change event. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'error': {'type': ['string', 'null'], 'description': "Present and set to 'not_found' when the monitor id does not exist."}, 'summary': {'type': 'string', 'description': 'Whether the test webhook was delivered and whether the monitor would have triggered, or a not-found message.'}, 'evaluation': {'type': 'object', 'properties': {'conditions_met': {'type': ['boolean', 'array', 'null'], 'description': 'Whether the trigger conditions were satisfied.'}, 'conditions_summary': {'type': ['string', 'array', 'null'], 'description': 'Per-condition explanation.'}}, 'description': 'Why the monitor did or did not fire.', 'additionalProperties': True}, 'rate_change': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'Two-letter state code.'}, 'new_rate': {'type': ['string', 'null'], 'description': 'New rate as a percent string.'}, 'change_pct': {'type': ['string', 'null'], 'description': 'Signed change as a percent string.'}, 'product_type': {'type': ['string', 'null'], 'description': 'Product type.'}, 'previous_rate': {'type': ['string', 'null'], 'description': 'Prior rate as a percent string.'}}, 'description': 'The simulated change, with rates pre-formatted as percent strings.', 'additionalProperties': True}, 'would_trigger': {'type': 'boolean', 'description': "Whether the monitor's conditions were satisfied by the supplied change."}, 'webhook_delivery': {'type': ['object', 'null'], 'properties': {'error': {'type': ['string', 'null'], 'description': 'Failure reason when delivery did not succeed.'}, 'delivered': {'type': ['boolean', 'null'], 'description': 'True when the endpoint accepted the payload.'}, 'status_code': {'type': ['number', 'null'], 'description': 'HTTP status returned by the endpoint.'}}, 'description': "Outcome of the HTTP POST to the monitor's webhook URL. Omitted when the backend reported no delivery attempt.", 'additionalProperties': True}}, 'description': "Result of firing a real test webhook at the monitor's stored URL, overriding the cooldown. On a missing id the tool returns a not-found shape instead of throwing.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['income_annual'], 'properties': {'rate': {'type': 'number', 'description': 'Optional annual interest rate, e.g. 6.5. If omitted, best market rate is used.'}, 'state': {'type': 'string', 'description': 'US state code for the market-rate lookup. Default CA.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months. Default 360.'}, 'back_end_dti': {'type': 'number', 'description': 'Total-debt DTI cap as a decimal. Default 0.36.'}, 'down_payment': {'type': 'number', 'description': 'Cash down payment in dollars. Default 0.'}, 'product_type': {'type': 'string', 'description': 'Product for the market-rate lookup. Default mortgage.'}, 'front_end_dti': {'type': 'number', 'description': 'Housing-payment DTI cap as a decimal. Default 0.28.'}, 'income_annual': {'type': 'number', 'description': 'Gross annual income in dollars'}, 'monthly_debts': {'type': 'number', 'description': 'Existing recurring monthly debt payments. Default 0.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Explanation of how the front-end and back-end DTI caps interact and which one binds.'}, 'reason': {'type': ['string', 'null'], 'description': "Why the affordable amount is constrained or zero, present only in that case — e.g. 'Existing debts exceed the back-end DTI budget.'"}, 'rate_used': {'type': ['string', 'null'], 'description': 'Interest rate, in percent, used for every calculation in this result. Check rate_source to see whether it came from the caller or from live market data.'}, 'affordable': {'type': ['boolean', 'null'], 'description': 'True when the income supports a meaningful loan after debts; false means the DTI budget is exhausted, not that nothing is purchasable.'}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'rate_source': {'type': ['string', 'null'], 'description': "Where rate_used came from: 'provided' means the caller supplied it, 'market' means it was resolved from the best live published rate for this state and product."}, 'down_payment': {'type': ['string', 'null'], 'description': 'Down payment in dollars assumed, as a formatted string.'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'max_home_price': {'type': ['string', 'null'], 'description': 'Largest purchase price in dollars, being the max loan amount plus the down payment.'}, 'max_loan_amount': {'type': ['string', 'null'], 'description': 'Largest loan principal in dollars that payment supports at the rate and term used.'}, 'assumed_defaults': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'State code assumed for market-rate lookups because the caller did not supply one.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months assumed because the caller did not supply one.'}, 'back_end_dti': {'type': ['number', 'null'], 'description': 'Back-end (total-debt) DTI cap assumed, as a decimal (0.36 = 36%).'}, 'down_payment': {'type': ['number', 'null'], 'description': 'Down payment in dollars assumed.'}, 'product_type': {'type': ['string', 'null'], 'description': 'Product type assumed when resolving the market rate.'}, 'front_end_dti': {'type': ['number', 'null'], 'description': 'Front-end (housing-only) DTI cap assumed, as a decimal (0.28 = 28%).'}, 'monthly_debts': {'type': ['number', 'null'], 'description': 'Existing monthly debt payments in dollars assumed.'}}, 'description': 'Inputs the caller did not supply that were filled in with defaults. State these explicitly to the user, since they drive the numbers.', 'additionalProperties': True}, 'max_payment_value': {'type': ['number', 'null'], 'description': 'The same maximum housing payment as a raw number in dollars, for further math.'}, 'binding_constraint': {'type': ['string', 'null'], 'description': "Which limit caps the budget: 'front_end_dti' (housing payment alone) or 'back_end_dti' (all debts). This tells the user what to fix to buy more."}, 'max_monthly_payment': {'type': ['string', 'null'], 'description': 'Largest housing payment in dollars supported by the binding DTI constraint, as a formatted string.'}, 'back_end_budget_value': {'type': ['number', 'null'], 'description': 'Total monthly debt budget in dollars under the back-end DTI cap, including existing debts. Compare with max_payment_value to see the headroom.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': [], 'properties': {'rate': {'type': 'number', 'description': 'Annual interest rate, e.g. 6.5. If omitted, best market rate for the state is used.'}, 'state': {'type': 'string', 'description': '2-letter US state code for the market-rate lookup. Default CA.'}, 'pmi_rate': {'type': 'number', 'description': 'Annual PMI as % of loan balance. Default 0.5, applied only when LTV > 80%.'}, 'home_price': {'type': 'number', 'description': 'Purchase price in dollars. Required unless loan_amount is given.'}, 'loan_amount': {'type': 'number', 'description': 'Optional explicit loan amount; overrides home_price - down_payment.'}, 'monthly_hoa': {'type': 'number', 'description': 'HOA dues in dollars/month. Default 0.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months. Default 360.'}, 'credit_score': {'type': 'number', 'description': 'Optional borrower credit score, used for the market-rate lookup.'}, 'down_payment': {'type': 'number', 'description': 'Cash down payment in dollars. Default 0. loan_amount = home_price - down_payment.'}, 'annual_insurance': {'type': 'number', 'description': 'Homeowners insurance in dollars/year. Default max(800, 0.35% of home price).'}, 'property_tax_rate': {'type': 'number', 'description': 'Annual property tax as % of home value. Default 1.1.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'ltv': {'type': ['string', 'null'], 'description': 'Loan-to-value ratio as a percent string. PMI generally applies above 80%.'}, 'breakdown': {'type': 'object', 'properties': {'hoa_pct': {'type': ['string', 'null'], 'description': 'Share of the total payment that is HOA dues.'}, 'pmi_pct': {'type': ['string', 'null'], 'description': "Share of the total payment that is PMI; '0%' when PMI does not apply."}, 'tax_pct': {'type': ['string', 'null'], 'description': 'Share of the total payment that is property tax.'}, 'p_and_i_pct': {'type': ['string', 'null'], 'description': 'Share of the total payment that is principal and interest.'}, 'insurance_pct': {'type': ['string', 'null'], 'description': 'Share of the total payment that is homeowners insurance.'}}, 'description': 'Share of the total monthly payment taken by each component, as percent strings.', 'additionalProperties': True}, 'rate_used': {'type': ['string', 'null'], 'description': 'Interest rate, in percent, used for every calculation in this result. Check rate_source to see whether it came from the caller or from live market data.'}, 'home_price': {'type': ['string', 'null'], 'description': 'Purchase price in dollars, as a formatted string.'}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'loan_amount': {'type': ['string', 'null'], 'description': 'Amount borrowed in dollars, being the home price less the down payment.'}, 'monthly_hoa': {'type': ['string', 'null'], 'description': 'Monthly HOA dues in dollars, as supplied or defaulted.'}, 'monthly_pmi': {'type': ['string', 'null'], 'description': 'Monthly private mortgage insurance in dollars. $0 when LTV is at or below 80%.'}, 'pmi_applies': {'type': ['boolean', 'null'], 'description': 'True when the LTV requires private mortgage insurance.'}, 'rate_source': {'type': ['string', 'null'], 'description': "Where rate_used came from: 'provided' means the caller supplied it, 'market' means it was resolved from the best live published rate for this state and product."}, 'annual_total': {'type': ['string', 'null'], 'description': 'Twelve months of the total monthly payment, in dollars.'}, 'down_payment': {'type': ['string', 'null'], 'description': 'Cash in dollars put down at closing.'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'assumed_defaults': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'State code assumed for market-rate lookups because the caller did not supply one.'}, 'pmi_rate': {'type': ['string', 'null'], 'description': 'Annual PMI rate assumed, as a percent of the loan balance.'}, 'monthly_hoa': {'type': ['string', 'null'], 'description': 'Monthly HOA dues in dollars assumed.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months assumed because the caller did not supply one.'}, 'annual_insurance': {'type': ['string', 'null'], 'description': 'Annual homeowners insurance premium in dollars assumed.'}, 'property_tax_rate': {'type': ['string', 'null'], 'description': 'Annual property tax rate assumed, as a percent string. Real county rates vary widely from this.'}}, 'description': 'Inputs the caller did not supply that were filled in with defaults. State these explicitly to the user, since they drive the numbers.', 'additionalProperties': True}, 'monthly_insurance': {'type': ['string', 'null'], 'description': 'Monthly homeowners insurance in dollars, one twelfth of the annual premium used.'}, 'monthly_property_tax': {'type': ['string', 'null'], 'description': 'Estimated monthly property tax in dollars, derived from the assumed tax rate rather than an actual county assessment.'}, 'total_monthly_payment': {'type': ['string', 'null'], 'description': 'Full monthly housing cost in dollars: principal, interest, taxes, insurance, plus PMI and HOA where they apply.'}, 'principal_and_interest': {'type': ['string', 'null'], 'description': 'Monthly principal-and-interest payment in dollars — only part of the total housing cost.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['profiles', 'product'], 'properties': {'limit': {'type': 'integer', 'default': 50, 'maximum': 200, 'minimum': 1, 'description': 'Maximum aggregate institutions and deduplicated offers returned.'}, 'product': {'type': 'object', 'required': ['product_type'], 'properties': {'amount': {'type': 'number', 'description': 'Loan or credit amount in USD.', 'exclusiveMinimum': 0}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'Transaction intent when relevant.'}, 'balance': {'type': 'number', 'minimum': 0, 'description': 'Deposit balance in USD.'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': 'Product audience.'}, 'occupancy': {'enum': ['primary', 'secondary', 'investment'], 'type': 'string', 'description': 'Property occupancy.'}, 'term_months': {'type': 'integer', 'maximum': 600, 'minimum': 1, 'description': 'Requested term in months.'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan', 'credit_card', 'savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'Exact product family.'}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'any'], 'type': 'string', 'description': 'Vehicle condition.'}}, 'description': 'Exact product request used for both eligibility-backed rate evaluation and ranking.', 'additionalProperties': False}, 'profiles': {'type': 'array', 'items': {'type': 'object', 'required': ['name', 'person'], 'properties': {'name': {'type': 'string', 'maxLength': 120, 'minLength': 1, 'description': 'Unique neutral panel label, such as profile-01; do not put PII here.'}, 'person': {'type': 'object', 'properties': {'school': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied school name; school_relationship is needed for a typed positive path.'}, 'worship': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied place of worship.'}, 'employer': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied employer name; use employer_org_ids after authoritative resolution.'}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Home ZIP; never inferred from another role.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Worksite ZIP, separate from home and payroll.'}, 'home_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized home city.'}, 'work_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized worksite city.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC home state.'}, 'occupation': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Person-supplied occupation.'}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC worksite state.'}, 'home_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Home county.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Payroll-origin ZIP, separate from the worksite.'}, 'work_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Worksite county.'}, 'associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations the person already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the applicant organization maintains a facility.'}, 'payroll_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized payroll-origin city.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the person owns real property; never inferred from home.'}, 'facility_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized facility city.'}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC payroll-origin state.'}, 'property_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized city where the person owns real property.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant is; absence means a natural person.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC facility state.'}, 'payroll_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Payroll-origin county.'}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC property state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit school ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the applicant organization maintains a facility.'}, 'family_relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relationship to the relative whose affiliations are supplied.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': 'Person-supplied military affiliation.'}, 'property_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the person owns real property.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit worship-organization ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit employer ids returned by resolve_eligibility_entities; rates-api revalidates type and active-publication authority.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Schools of the named relative, not the applicant.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Employers of the named relative, not the applicant.'}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit association ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the person relates to the supplied school.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string', 'description': 'Confirmed membership status.'}, 'relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relative relationship.'}, 'credit_union_id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships, each scoped to one exact institution.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations of the named relative, not the applicant.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State tied to a state-scoped military affiliation.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200, 'minLength': 1}, 'maxItems': 20, 'description': 'Narrow conditions the person explicitly asserted; never infer them.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Whether documented joinable-association actions may be considered.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids belonging to the named relative, not the applicant.', 'uniqueItems': True}}, 'description': 'Explicit caller-supplied person facts. Unknown facts stay absent; do not infer them.', 'additionalProperties': False}}, 'additionalProperties': False}, 'maxItems': 10, 'minItems': 1, 'description': 'Caller-supplied named panel. Names must be unique within this request.'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'product': {'type': 'object', 'description': 'Exact product request evaluated for the panel.', 'additionalProperties': True}, 'profiles': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Per-profile counts, best evidenced offer, and observation timestamp.'}, 'snapshot': {'type': 'object', 'description': 'Shared rules clock and database observation boundaries.', 'additionalProperties': True}, 'aggregate': {'type': 'object', 'description': 'Deduplicated reachable institutions and exact offers, profile reach, counts, and truncation flags.', 'additionalProperties': True}, 'semantics': {'type': ['string', 'null'], 'description': 'Positive-evidence-only and unknown-is-never-ineligible contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required warning that the panel is not a population estimate, conversion rate, approval forecast, or rejection.'}, 'methodology': {'type': 'object', 'description': 'Panel size/source, deduplication identities, and explicit no-extrapolation/no-conversion semantics.', 'additionalProperties': True}}, 'description': 'One-snapshot evaluation of a small caller-supplied panel.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'intent', 'amount'], 'properties': {'state': {'type': 'string', 'description': 'US state code (2-letter). Required.'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars. Required.'}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'The loan intent.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months.'}, 'credit_score': {'type': 'number', 'description': "Borrower's credit score (300-850)."}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'personal_loan', 'heloc', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product.'}, 'max_providers': {'type': 'number', 'description': 'Maximum number of lenders to explain (1-5). Defaults to 5.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'offers': {'type': 'array', 'items': {'type': 'object', 'properties': {'rank': {'type': ['number', 'null'], 'description': 'Position in the ranking, 1 = best weighted score.'}, 'lender': {'type': ['string', 'null'], 'description': 'Credit union publishing this offer.'}, 'signals': {'type': 'array', 'description': 'Scoring signals with their raw value, weight, and contribution to the final score; use them to explain why one lender outranked another.'}, 'beats_next_by': {'type': 'object', 'description': 'Margin over the next-ranked offer, in APR percentage points, dollars per month, and dollars of lifetime interest. All zeros mean it is effectively a tie.'}, 'cost_breakdown': {'type': 'object', 'description': 'The cost inputs behind this offer: rate and APR in percent, points, fees and monthly payment in dollars, and lifetime interest in dollars.'}, 'signals_truncated_from': {'type': ['number', 'null'], 'description': 'Full number of signals scored before the list above was shortened. Null when nothing was omitted.'}}, 'additionalProperties': True}, 'description': 'Ranked offers with the scoring inputs that produced each position.'}, 'summary': {'type': ['string', 'null'], 'description': 'Plain-English statement of the weighting scheme used and what separated the top offers; quote this when explaining the ranking.'}, 'request_id': {'type': ['string', 'null'], 'description': 'Opaque identifier for this call, useful only for support or debugging; never show it to the user.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['text'], 'properties': {'text': {'type': 'string', 'maxLength': 2000, 'description': "The person's own words, up to 2000 characters. Do not paraphrase or pre-structure it — the extractor needs the original sentence to anchor evidence spans."}, 'known_facts': {'type': 'object', 'description': 'Optional. Fields you already know, in PersonSearch shape. These are echoed as source="supplied" and never overwritten.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Standing disclosure plus the next step: confirm the flagged facts, then call find_eligible_credit_unions.'}, 'facts': {'type': 'array', 'items': {'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'A plain-language question or explanation to put to the user.'}, 'field': {'type': ['string', 'null'], 'description': "A field name that find_eligible_credit_unions accepts, e.g. 'occupation' or 'home_state'."}, 'value': {'description': 'The typed value, coerced deterministically from what the person said. null means it could not be turned into a usable value - ask the user, do not guess.'}, 'source': {'type': ['string', 'null'], 'description': "'extracted' (read from the text) or 'supplied' (echoed from known_facts, untouched)."}, 'evidence': {'type': ['object', 'null'], 'properties': {'end': {'type': ['number', 'null'], 'description': "Character offset one past the quote's last character."}, 'quote': {'type': ['string', 'null'], 'description': "The person's own words, verbatim."}, 'start': {'type': ['number', 'null'], 'description': "Character offset of the quote's first character in the text you sent."}}, 'description': "The words in the user's own text this fact was read from.", 'additionalProperties': True}, 'confidence': {'type': ['number', 'null'], 'description': "The extraction model's own uncalibrated self-report, 0-1. It gates autofill only. Quote the evidence to the user, not this number."}, 'conflict_with': {'type': ['string', 'null'], 'description': 'Set when this value contradicts one you supplied in known_facts. Both are returned; no winner is picked.'}, 'needs_confirmation': {'type': ['boolean', 'null'], 'description': "True when the user must confirm this before it is relied on. Always true for family relationships, relatives' details, applicant kind and asserted qualifiers."}}, 'additionalProperties': True}, 'description': "Facts read from the person's words, each returned FOR CONFIRMATION. Never a decision, and never a credit union."}, 'model': {'type': ['string', 'null'], 'description': 'Extraction model identifier.'}, 'sandbox': {'type': ['boolean', 'null'], 'description': 'True when this is the frozen sandbox fixture rather than a real extraction.'}, 'billed_units': {'type': ['number', 'null'], 'description': 'API units billed for this call: 3 for a live extraction, 0 for a sandbox fixture.'}, 'unparsed_spans': {'type': 'array', 'items': {'type': 'object', 'properties': {'end': {'type': ['number', 'null'], 'description': 'Character offset one past the last character.'}, 'note': {'type': ['string', 'null'], 'description': 'Why it was not turned into a fact, and what to ask.'}, 'quote': {'type': ['string', 'null'], 'description': 'The phrase, verbatim from the text.'}, 'start': {'type': ['number', 'null'], 'description': 'Character offset of the first character.'}}, 'additionalProperties': True}, 'description': 'Phrases recognized as meaningful but not mapped to a field, including anything said in the past tense or hypothetically. Ask about these.'}, 'extractor_version': {'type': ['string', 'null'], 'description': "Version of the extractor's prompt and post-processing."}, 'person_search_body': {'type': ['object', 'null'], 'description': "A ready-to-send argument set for find_eligible_credit_unions, containing only confirmed-or-supplied facts. Add the user's confirmations to it before calling.", 'additionalProperties': True}, 'extraction_available': {'type': ['boolean', 'null'], 'description': 'False when extraction was unavailable. That carries no eligibility signal whatsoever - ask the user for fields directly, never read it as a negative answer.'}, 'confirmation_required': {'type': ['boolean', 'null'], 'description': 'True when anything needs confirming. Show the facts to the user before searching.'}, 'confidence_is_model_self_reported': {'type': ['boolean', 'null'], 'description': "Always true when present. A standing warning that 'confidence' is the model's own number, not a measured accuracy."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['zip'], 'properties': {'zip': {'type': 'string', 'pattern': '^[0-9]{5}$', 'description': 'Five-digit US ZIP code used as the center of the nearest-branch search.'}, 'max_results': {'type': 'number', 'maximum': 25, 'minimum': 1, 'description': 'Maximum credit unions to return (1-25, default 10).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'query': {'type': 'object', 'properties': {'zip': {'type': ['string', 'null'], 'description': 'Five-digit ZIP code that was searched around.'}, 'max_results': {'type': ['number', 'null'], 'description': 'Maximum number of credit unions the caller asked for; the summary states how many were found in total.'}}, 'description': 'The lookup that was performed, echoed back.', 'additionalProperties': True}, 'summary': {'type': ['string', 'null'], 'description': 'One-sentence plain-English summary of this result, safe to quote directly to the user.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Precision and methodology caveat for the distances and locations above; carry it into any answer that quotes them.'}, 'credit_unions': {'type': 'array', 'items': {'type': 'object', 'properties': {'id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE'; pass it to tools that take credit_union_ids."}, 'city': {'type': ['string', 'null'], 'description': 'City of the matched branch.'}, 'name': {'type': ['string', 'null'], 'description': 'Credit union name as displayed.'}, 'slug': {'type': ['string', 'null'], 'description': 'URL-safe identifier used in rateapi.dev links.'}, 'match': {'type': ['string', 'null'], 'description': "How this credit union was matched: 'same_zip' (a branch is in the requested ZIP) or 'distance' (ranked by computed distance)."}, 'state': {'type': ['string', 'null'], 'description': 'Two-letter state code of the matched branch.'}, 'branch': {'type': 'object', 'description': 'The specific nearest branch (name and street address) the distance was measured to.'}, 'distance_miles': {'type': ['number', 'null'], 'description': 'Straight-line miles from the ZIP centroid to the nearest branch, not driving distance. Null when NCUA publishes no usable geocode for any branch.'}, 'distance_method': {'type': ['string', 'null'], 'description': "Precision of the distance: 'branch_coordinate' (an actual branch geocode) or 'zip_centroid' (only the branch's ZIP was known, so it is coarser)."}}, 'additionalProperties': True}, 'description': 'Nearest credit unions, closest first.'}, 'match_quality': {'type': ['string', 'null'], 'description': "How precise the proximity ranking is overall, e.g. 'ZIP-centroid straight-line estimate'. Distances are as-the-crow-flies, not driving distance."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'limit': {'type': 'number', 'description': 'Maximum entries per bucket (1-200). Default 50.'}, 'school': {'type': 'string', 'description': "User's school/college/university, resolved to a canonical organization. Supply school_relationship too; a name alone is not a positive match."}, 'worship': {'type': 'string', 'description': "User's place of worship, resolved to a canonical organization."}, 'employer': {'type': 'string', 'description': "User's employer, resolved to a canonical organization for SEG matching."}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit home ZIP or ZIP+4. Resolves to candidate counties; when home_state is supplied, the crosswalk must agree with it."}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit work ZIP or ZIP+4. Resolves to candidate work counties; when work_state is supplied, the crosswalk must agree with it."}, 'home_city': {'type': 'string', 'description': "User's Census-recognized home city. Requires home_state or a recognized home_zip that uniquely identifies one state; unresolved labels are rejected rather than guessed."}, 'work_city': {'type': 'string', 'description': 'Census-recognized city where the user works. Requires work_state or a recognized work_zip that uniquely identifies one state.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "User's valid 50-state/DC code (e.g., CA, TX, NY). Lowercase is accepted and normalized."}, 'occupation': {'type': 'string', 'description': "User's occupation, matched against trade, industry, and profession fields of membership."}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC code where the user works (e.g., CA, TX, NY). Lowercase is accepted and normalized.'}, 'home_county': {'type': 'string', 'description': "User's county. Wins over the ZIP-derived counties when supplied."}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "ZIP from which the user's employer issues payroll; distinct from the worksite ZIP. When payroll_state is supplied, the ZIP must agree with it."}, 'work_county': {'type': 'string', 'description': 'County where the user works. Wins over work-ZIP-derived counties when supplied.'}, 'associations': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 20, 'description': 'Associations, unions, or member organizations the user already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "ZIP where the user's business maintains a location. Distinct from the worksite ZIP."}, 'payroll_city': {'type': 'string', 'description': 'Census-recognized city from which payroll is issued. Requires payroll_state or a recognized payroll_zip that uniquely identifies one state.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the user OWNS REAL PROPERTY. A door of its own — never inferred from where they live, and an absentee owner qualifies.'}, 'facility_city': {'type': 'string', 'description': "Census-recognized city where the user's business maintains a location. Requires facility_state or a recognized facility_zip that uniquely identifies one state."}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "State from which the user's employer issues payroll; distinct from work_state."}, 'property_city': {'type': 'string', 'description': 'Census-recognized city where the user owns real property. Requires property_state or a recognized property_zip that uniquely identifies one state.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant IS. Some charters admit entities as well as people. Absent means a natural person; a person is never rejected by an entity-only door, only left unknown.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "State where the user's business maintains a location."}, 'payroll_county': {'type': 'string', 'description': "County from which the user's employer issues payroll; distinct from work_county."}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State where the user owns real property. Distinct from home_state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids selected through resolve_eligibility_entities; never populate these from prose extraction.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'description': "County where the user's business maintains a location."}, 'family_relation': {'type': 'string', 'description': "How the user relates to a RELATIVE whose own affiliations may qualify them (e.g. 'spouse', 'child', 'immediate family'). Required alongside relative_employers/relative_schools/relative_associations — without it there is nobody for those organizations to belong to. Many SEG lists read 'Employees of the following companies AND THEIR IMMEDIATE FAMILIES are eligible'; this is how that door is answered."}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': "User's military affiliation, matched against military fields of membership."}, 'property_county': {'type': 'string', 'description': 'County where the user owns real property. Distinct from home_county.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical worship-organization ids selected through resolve_eligibility_entities.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids selected through resolve_eligibility_entities. The API revalidates entity type and active-publication authority before use.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Schools the RELATIVE named by family_relation attends. Optional; same unknown-by-default contract as relative_employers.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string'}, 'description': "Employers of the RELATIVE named by family_relation (not the user's own employer). Optional; omitting it leaves compound family doors undecided (unknown), never negative."}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids selected through resolve_eligibility_entities; each is type- and publication-revalidated.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the user relates to the school. Required with school to affirm a typed student, alumni, or school-employee path.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string'}, 'relation': {'type': 'string', 'description': "The relative's relationship to the applicant."}, 'credit_union_id': {'type': 'string', 'description': 'The exact target credit union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships scoped to one exact credit union. A membership at one institution is never reused for another; omit unconfirmed memberships and the corresponding family door remains unknown.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Associations the RELATIVE named by family_relation belongs to. Optional; same unknown-by-default contract as relative_employers.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'The state the user serves, or served, in. State National Guard doors ("Oklahoma National Guard") need this; without it such a door reads unknown.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 20, 'description': 'Narrowings the user asserts about themselves, quoted back from a missing_facts question (e.g. "assigned as Recruiters or ROTC Instructors within the State of Arkansas"). Absence caps a narrowed door rather than closing it.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Set true to search documented joinable-association paths (valid as the sole discriminator). Set false only to suppress paths that require joining an association; false alone is not a discriminating search fact.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}}}
Ausgabeschema
{'type': 'object', '$defs': {'eligibilityMatch': {'type': 'object', 'properties': {'name': {'type': ['string', 'null'], 'description': 'Credit union name, safe to show the user.'}, 'paths': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Structured membership paths behind the verdict. Non-matches and non-winning alternatives retain no partial conditions, join action, URL, cost, or pending action labelled as matched.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter state code of the credit union's headquarters."}, 'engine': {'type': ['string', 'null'], 'description': 'Graph or legacy source for this verdict.'}, 'status': {'type': ['string', 'null'], 'description': 'eligible | conditionally_eligible | possibly_eligible | unknown. Reserved legacy negative values are normalized to unknown by MCP.'}, 'reasons': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Deterministic explanation sentences.'}, 'join_url': {'type': ['string', 'null'], 'description': 'Where a proven graph conditionally_eligible step is completed, when known. Omitted for legacy-engine projections and every other status.'}, 'confidence': {'type': ['number', 'null'], 'description': '0-1 confidence in this verdict.'}, 'publication': {'type': 'object', 'properties': {'activated_at': {'type': 'string', 'format': 'date-time', 'description': 'When this publication became serving authority.'}, 'publication_id': {'type': 'integer', 'description': 'Database identifier of the active publication.'}, 'ruleset_sha256': {'type': 'string', 'pattern': '^[0-9a-f]{64}$', 'description': 'SHA-256 digest of the complete ordered rule set.'}, 'proposal_coverage': {'type': 'object', 'description': 'Counts of source-page model proposals that were verified, published, or withheld; not a closed-world FOM attestation.', 'additionalProperties': True}}, 'description': 'Exact immutable active generation evaluated for this entry.'}, 'join_cost_usd': {'type': ['number', 'null'], 'description': 'Up-front cost of a proven graph conditionally_eligible step, when known. Omitted for legacy-engine projections and every other status.'}, 'unknown_reason': {'type': ['string', 'null'], 'description': 'Machine-readable reason for unknown, including `fom_completeness_unaffirmed` when the published corpus is not attested complete.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Internal composite identifier of the credit union.'}}, 'additionalProperties': True}}, 'properties': {'note': {'type': ['string', 'null'], 'description': 'Liability framing to surface alongside any eligibility claim.'}, 'limit': {'type': ['number', 'null'], 'description': 'Maximum entries returned per bucket for this call.'}, 'counts': {'type': 'object', 'description': 'Size of each bucket within the bounded candidate set before the per-bucket `limit` is applied; not fleet-wide totals.', 'additionalProperties': True}, 'engine': {'type': ['string', 'null'], 'description': 'Which engines produced these verdicts.'}, 'unknown': {'type': 'array', 'items': {'$ref': '#/$defs/eligibilityMatch'}, 'description': 'Credit unions whose rules could not be decided from the supplied facts. Never an assertion of ineligibility.'}, 'eligible': {'type': 'array', 'items': {'$ref': '#/$defs/eligibilityMatch'}, 'description': 'Credit unions with a verified membership path that already applies to this person.'}, 'resolved': {'type': 'object', 'description': 'Canonical organizations and geography keys resolved from the supplied facts.', 'additionalProperties': True}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required disclosure that eligibility is guidance and the institution decides.'}, 'unanswerable': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'A deterministic sentence a UI can show verbatim.'}, 'reason': {'type': ['string', 'null'], 'description': 'Why no question is emitted: no_rules, low_confidence_rules, unresolved_organization, unmodeled_condition, radius_centre_unidentified, radius_centre_ungeocoded, road_miles_unproven, or fom_completeness_unaffirmed.'}, 'cu_count': {'type': ['integer', 'null'], 'description': 'How many evaluated institutions fall under this reason.'}, 'condition_kinds': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'The evaluator condition kinds behind this entry, when any are known.'}}, 'additionalProperties': True}, 'description': 'What no question can fix, and why. Do not ask the user about these. Absent when everything unresolved is askable.'}, 'next_questions': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'kind': {'type': ['string', 'null'], 'description': 'The evaluator condition kind these questions share.'}, 'question': {'type': ['string', 'null'], 'description': 'The generic phrasing of the question, as it should be put to a person.'}, 'fact_field': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'The request field(s) an answer populates.'}, 'unlocks_cu_ids': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Institutions this question unlocks, capped at 20. unlocks_cu_count remains the true total.'}, 'unlocks_cu_count': {'type': ['integer', 'null'], 'description': 'How many evaluated institutions this one question would move out of unknown. The true total, even when the id list is capped.'}, 'example_evidence_quote': {'type': ['string', 'null'], 'description': 'One institution`s own words behind this question, as an illustration.'}}, 'additionalProperties': True}, 'description': 'Questions ranked across every institution evaluated, by how many each unlocks. Ask the top one to three, merge the answers into the same request body, and call again. Stop when this is empty, when the top entry`s unlocks_cu_count drops below 2, or after three turns. Absent when there is nothing to ask.'}, 'candidate_limit': {'type': ['number', 'null'], 'description': 'Maximum unique candidates this search can accept for evaluation (currently 400).'}, 'candidate_sources': {'type': 'object', 'properties': {'legacy': {'type': ['number', 'null'], 'description': 'Graph-less candidates surfaced by direct input-gated legacy geography or affinity matches.'}, 'open_graph': {'type': ['number', 'null'], 'description': 'Candidates surfaced by open-to-anyone graph rules.'}, 'exact_graph': {'type': ['number', 'null'], 'description': 'Candidates surfaced by exact graph-key matches.'}, 'legacy_open': {'type': ['number', 'null'], 'description': 'Graph-less candidates added by the bounded broad open-to-anyone legacy fill.'}, 'association_graph': {'type': ['number', 'null'], 'description': 'Candidates surfaced by the bounded association graph scan.'}}, 'description': 'Unique candidates accepted in deterministic priority order from each narrowing source.', 'additionalProperties': True}, 'possibly_eligible': {'type': 'array', 'items': {'$ref': '#/$defs/eligibilityMatch'}, 'description': 'Credit unions where a path may apply but a requirement could not be confirmed.'}, 'candidates_evaluated': {'type': ['number', 'null'], 'description': 'How many credit unions in the bounded, prioritized candidate set were evaluated; not the number of institutions in the fleet.'}, 'conditionally_eligible': {'type': 'array', 'items': {'$ref': '#/$defs/eligibilityMatch'}, 'description': 'Credit unions joinable after one more step, with its cost when known.'}, 'candidate_set_truncated': {'type': ['boolean', 'null'], 'description': 'True when the overall candidate cap or any source-query cap may have omitted additional institutions; absence from the response is never a negative verdict.'}, 'missing_facts_truncated': {'type': ['boolean', 'null'], 'description': 'True when a size cap dropped a question that could otherwise have been asked (3 per institution, 5 in the rollup, 20 unlock ids per rollup entry). The same honesty convention as candidate_set_truncated.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['zip', 'product_type'], 'properties': {'zip': {'type': 'string', 'pattern': '^[0-9]{5}$', 'description': 'Five-digit US ZIP code used as the center of the nearby-branch search.'}, 'max_offers': {'type': 'number', 'maximum': 8, 'minimum': 1, 'description': 'Maximum product-matched offers to return (1-8, default 5).'}, 'term_months': {'type': 'number', 'minimum': 1, 'description': 'Optional comparable loan term. For fixed mortgages, under 300 months selects the 15-year market and 300+ selects 30-year.'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan', 'credit_card'], 'type': 'string', 'description': 'Product whose current published rates should be compared.'}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'cpo'], 'type': 'string', 'description': 'Auto loans only. Omit to use the new-auto market.'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'zip': {'type': ['string', 'null'], 'description': 'Five-digit ZIP code the search was centered on.'}, 'offers': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': "Annual percentage rate in percent, including lender fees. NULL when the lender published no APR — the API deliberately does not substitute the note rate, so never present `rate` as an APR. Some legacy rows still carry an APR equal to the note rate; those heal on that credit union's next scrape."}, 'rate': {'type': ['number', 'null'], 'description': 'Note rate in percent (6.125 = 6.125%), excluding fees.'}, 'branch': {'type': 'object', 'description': 'The nearest branch (name and street address) that the distance was measured to.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for this rate, where 1 point = 1% of the loan amount.'}, 'proximity': {'type': ['string', 'null'], 'description': "How the lender qualified as nearby: 'same_zip' or 'distance'."}, 'rateapi_url': {'type': ['string', 'null'], 'description': 'Public rateapi.dev profile page for this credit union.'}, 'display_name': {'type': ['string', 'null'], 'description': "Normalized product name for comparison across lenders, e.g. '30-Year Fixed'. Prefer this when comparing; quote product_name when citing the lender."}, 'last_updated': {'type': ['string', 'null'], 'description': 'UTC timestamp when this specific rate was last scraped from the lender.'}, 'product_name': {'type': ['string', 'null'], 'description': "The lender's own wording for the product, e.g. '30 Year Fixed - Conforming'."}, 'distance_miles': {'type': ['number', 'null'], 'description': 'Straight-line miles from the ZIP centroid to the nearest branch, not driving distance. Null when no branch geocode is available.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE' for the lender."}, 'distance_method': {'type': ['string', 'null'], 'description': "Precision of the distance: 'branch_coordinate' (exact branch geocode) or 'zip_centroid' (coarser, branch ZIP only)."}, 'credit_union_name': {'type': ['string', 'null'], 'description': 'Credit union name as displayed.'}}, 'additionalProperties': True}, 'description': 'Published offers from nearby credit unions, ordered by the rule in `ranked_by`.'}, 'precision': {'type': ['string', 'null'], 'description': "Overall precision of the distance estimates, e.g. 'ZIP-centroid straight-line estimate'."}, 'ranked_by': {'type': ['string', 'null'], 'description': 'The ordering rule applied to `offers`, e.g. lowest APR among credit unions with nearby reported branches — proximity filters the set, price sorts it.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Precision and methodology caveat for the distances and locations above; carry it into any answer that quotes them.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}, 'unavailable_reason': {'type': ['string', 'null'], 'description': 'Why `offers` is empty, present only when it is — e.g. no credit union near that ZIP publishes the requested product. Quote this rather than telling the user no rates exist.'}, 'nearby_credit_union_count': {'type': ['number', 'null'], 'description': 'How many credit unions were found near this ZIP before filtering to those publishing this product; `offers` is usually shorter.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['person', 'product'], 'properties': {'limit': {'type': 'number', 'description': 'Visible offers per bucket, 1-50. Candidate intersection happens before this cap.'}, 'person': {'type': 'object', 'properties': {'school': {'type': 'string', 'description': "User's school/college/university, resolved to a canonical organization. Supply school_relationship too; a name alone is not a positive match."}, 'worship': {'type': 'string', 'description': "User's place of worship, resolved to a canonical organization."}, 'employer': {'type': 'string', 'description': "User's employer, resolved to a canonical organization for SEG matching."}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit home ZIP or ZIP+4. Resolves to candidate counties; when home_state is supplied, the crosswalk must agree with it."}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit work ZIP or ZIP+4. Resolves to candidate work counties; when work_state is supplied, the crosswalk must agree with it."}, 'home_city': {'type': 'string', 'description': "User's Census-recognized home city. Requires home_state or a recognized home_zip that uniquely identifies one state; unresolved labels are rejected rather than guessed."}, 'work_city': {'type': 'string', 'description': 'Census-recognized city where the user works. Requires work_state or a recognized work_zip that uniquely identifies one state.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "User's valid 50-state/DC code (e.g., CA, TX, NY). Lowercase is accepted and normalized."}, 'occupation': {'type': 'string', 'description': "User's occupation, matched against trade, industry, and profession fields of membership."}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC code where the user works (e.g., CA, TX, NY). Lowercase is accepted and normalized.'}, 'home_county': {'type': 'string', 'description': "User's county. Wins over the ZIP-derived counties when supplied."}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "ZIP from which the user's employer issues payroll; distinct from the worksite ZIP. When payroll_state is supplied, the ZIP must agree with it."}, 'work_county': {'type': 'string', 'description': 'County where the user works. Wins over work-ZIP-derived counties when supplied.'}, 'associations': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 20, 'description': 'Associations, unions, or member organizations the user already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "ZIP where the user's business maintains a location. Distinct from the worksite ZIP."}, 'payroll_city': {'type': 'string', 'description': 'Census-recognized city from which payroll is issued. Requires payroll_state or a recognized payroll_zip that uniquely identifies one state.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the user OWNS REAL PROPERTY. A door of its own — never inferred from where they live, and an absentee owner qualifies.'}, 'facility_city': {'type': 'string', 'description': "Census-recognized city where the user's business maintains a location. Requires facility_state or a recognized facility_zip that uniquely identifies one state."}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "State from which the user's employer issues payroll; distinct from work_state."}, 'property_city': {'type': 'string', 'description': 'Census-recognized city where the user owns real property. Requires property_state or a recognized property_zip that uniquely identifies one state.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant IS. Some charters admit entities as well as people. Absent means a natural person; a person is never rejected by an entity-only door, only left unknown.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': "State where the user's business maintains a location."}, 'payroll_county': {'type': 'string', 'description': "County from which the user's employer issues payroll; distinct from work_county."}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State where the user owns real property. Distinct from home_state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids selected through resolve_eligibility_entities; never populate these from prose extraction.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'description': "County where the user's business maintains a location."}, 'family_relation': {'type': 'string', 'description': "How the user relates to a RELATIVE whose own affiliations may qualify them (e.g. 'spouse', 'child', 'immediate family'). Required alongside relative_employers/relative_schools/relative_associations — without it there is nobody for those organizations to belong to. Many SEG lists read 'Employees of the following companies AND THEIR IMMEDIATE FAMILIES are eligible'; this is how that door is answered."}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': "User's military affiliation, matched against military fields of membership."}, 'property_county': {'type': 'string', 'description': 'County where the user owns real property. Distinct from home_county.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical worship-organization ids selected through resolve_eligibility_entities.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids selected through resolve_eligibility_entities. The API revalidates entity type and active-publication authority before use.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Schools the RELATIVE named by family_relation attends. Optional; same unknown-by-default contract as relative_employers.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string'}, 'description': "Employers of the RELATIVE named by family_relation (not the user's own employer). Optional; omitting it leaves compound family doors undecided (unknown), never negative."}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids selected through resolve_eligibility_entities; each is type- and publication-revalidated.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the user relates to the school. Required with school to affirm a typed student, alumni, or school-employee path.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string'}, 'relation': {'type': 'string', 'description': "The relative's relationship to the applicant."}, 'credit_union_id': {'type': 'string', 'description': 'The exact target credit union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships scoped to one exact credit union. A membership at one institution is never reused for another; omit unconfirmed memberships and the corresponding family door remains unknown.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Associations the RELATIVE named by family_relation belongs to. Optional; same unknown-by-default contract as relative_employers.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'The state the user serves, or served, in. State National Guard doors ("Oklahoma National Guard") need this; without it such a door reads unknown.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 20, 'description': 'Narrowings the user asserts about themselves, quoted back from a missing_facts question (e.g. "assigned as Recruiters or ROTC Instructors within the State of Arkansas"). Absence caps a narrowed door rather than closing it.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Set true to search documented joinable-association paths (valid as the sole discriminator). Set false only to suppress paths that require joining an association; false alone is not a discriminating search fact.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids for the relative named by family_relation, never for the applicant.', 'uniqueItems': True}}, 'description': 'Confirmed person facts accepted by find_eligible_credit_unions, including canonical *_org_ids selected through resolve_eligibility_entities. Unknown facts stay absent and canonical ids are revalidated by rates-api.', 'additionalProperties': False}, 'product': {'type': 'object', 'required': ['product_type'], 'properties': {'amount': {'type': 'number', 'description': 'Loan or credit amount in USD.'}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'Transaction intent when it changes product matching.'}, 'balance': {'type': 'number', 'description': 'Deposit balance in USD.'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': 'Business or consumer product audience.'}, 'occupancy': {'enum': ['primary', 'secondary', 'investment'], 'type': 'string', 'description': 'Property occupancy for mortgage matching.'}, 'term_months': {'type': 'number', 'description': 'Requested term in months.'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan', 'credit_card', 'savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'Canonical product family.'}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'any'], 'type': 'string', 'description': 'Vehicle condition for auto-loan matching.'}}, 'description': 'The financial product and matching attributes to route.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'as_of': {'type': ['string', 'null'], 'description': 'Most recent observation timestamp among returned rates.'}, 'counts': {'type': 'object', 'properties': {'unresolved': {'type': ['number', 'null'], 'description': 'Matches that cannot be promoted because no membership OR-path is proven, rate proof is incomplete, or product suitability is unresolved.'}, 'reachable_now': {'type': ['number', 'null'], 'description': 'Offers with at least one exact-publication-proven membership OR-path and complete rate proof.'}, 'no_published_offer': {'type': ['number', 'null'], 'description': 'Graph-positive institutions without a matching fresh evidenced rate.'}, 'reachable_after_action': {'type': ['number', 'null'], 'description': 'Offers requiring one documented membership action.'}}, 'description': 'Full pre-display-cap counts for each reachability bucket.', 'additionalProperties': True}, 'product': {'type': 'object', 'description': 'Normalized product request used for matching.', 'additionalProperties': True}, 'discovery': {'type': 'object', 'description': 'Graph retrieval telemetry. candidate_scope=active_fleet and candidate_set_truncated=false prove exhaustive evaluation.', 'additionalProperties': True}, 'semantics': {'type': ['string', 'null'], 'description': 'The positive-evidence-only interpretation contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required distinction between evidence-backed routing, published pricing, final availability, and approval.'}, 'unresolved': {'type': 'array', 'items': {'type': 'object', 'properties': {'offer': {'type': 'object', 'description': 'Best matching exact product, its constraints, APY only when explicitly published, lending APR kept distinct from nominal rate, and source evidence.', 'additionalProperties': True}, 'membership': {'type': 'object', 'description': 'Membership verdict and publication lineage. paths are proven winning OR alternatives; unproven_paths preserves other claimed alternatives; proof_completeness distinguishes decision_proven from all-alternatives complete.', 'additionalProperties': True}, 'institution': {'type': 'object', 'description': 'Institution display name, state, and links.', 'additionalProperties': True}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Canonical credit-union identifier.'}, 'product_suitability': {'type': 'object', 'description': 'Separate published-constraint fit for supplied balance, audience, term, intent, vehicle condition, and occupancy where applicable.', 'additionalProperties': True}, 'product_availability': {'type': 'object', 'description': 'Whether a matching fresh evidenced published rate was found.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'Published-rate matches whose membership or rate proof remains incomplete, or whose membership path is only possible; unknown is not unavailable.'}, 'completeness': {'type': 'object', 'description': 'Honest evaluation and display-cap metadata, including current-publication-only membership proof semantics.', 'additionalProperties': True}, 'ranking_basis': {'type': ['string', 'null'], 'description': 'Deposits rank by higher published APY. Lending ranks published APR rows first by lower APR, then separately labeled nominal-rate rows by lower rate; APR and rate are never numerically compared. Membership access cost breaks price ties.'}, 'reachable_now': {'type': 'array', 'items': {'type': 'object', 'properties': {'offer': {'type': 'object', 'description': 'Best matching exact product, its constraints, APY only when explicitly published, lending APR kept distinct from nominal rate, and source evidence.', 'additionalProperties': True}, 'membership': {'type': 'object', 'description': 'Membership verdict and publication lineage. paths are proven winning OR alternatives; unproven_paths preserves other claimed alternatives; proof_completeness distinguishes decision_proven from all-alternatives complete.', 'additionalProperties': True}, 'institution': {'type': 'object', 'description': 'Institution display name, state, and links.', 'additionalProperties': True}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Canonical credit-union identifier.'}, 'product_suitability': {'type': 'object', 'description': 'Separate published-constraint fit for supplied balance, audience, term, intent, vehicle condition, and occupancy where applicable.', 'additionalProperties': True}, 'product_availability': {'type': 'object', 'description': 'Whether a matching fresh evidenced published rate was found.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'Offers with a verified membership path and a fresh, evidenced published rate.'}, 'no_published_offer': {'type': 'array', 'items': {'type': 'object', 'properties': {'offer': {'type': 'object', 'description': 'Best matching exact product, its constraints, APY only when explicitly published, lending APR kept distinct from nominal rate, and source evidence.', 'additionalProperties': True}, 'membership': {'type': 'object', 'description': 'Membership verdict and publication lineage. paths are proven winning OR alternatives; unproven_paths preserves other claimed alternatives; proof_completeness distinguishes decision_proven from all-alternatives complete.', 'additionalProperties': True}, 'institution': {'type': 'object', 'description': 'Institution display name, state, and links.', 'additionalProperties': True}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Canonical credit-union identifier.'}, 'product_suitability': {'type': 'object', 'description': 'Separate published-constraint fit for supplied balance, audience, term, intent, vehicle condition, and occupancy where applicable.', 'additionalProperties': True}, 'product_availability': {'type': 'object', 'description': 'Whether a matching fresh evidenced published rate was found.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'Graph-positive institutions without a matching fresh evidenced rate; absence remains unknown.'}, 'eligibility_snapshot': {'type': 'object', 'properties': {'rules_now': {'type': ['string', 'null'], 'description': 'Pinned eligibility rules clock used throughout the request.'}, 'generation': {'type': ['string', 'null'], 'description': 'Opaque immutable serving-snapshot generation identifier.'}}, 'description': 'Immutable eligibility graph generation and pinned rules clock used for this result when snapshot serving is available.', 'additionalProperties': True}, 'reachable_after_action': {'type': 'array', 'items': {'type': 'object', 'properties': {'offer': {'type': 'object', 'description': 'Best matching exact product, its constraints, APY only when explicitly published, lending APR kept distinct from nominal rate, and source evidence.', 'additionalProperties': True}, 'membership': {'type': 'object', 'description': 'Membership verdict and publication lineage. paths are proven winning OR alternatives; unproven_paths preserves other claimed alternatives; proof_completeness distinguishes decision_proven from all-alternatives complete.', 'additionalProperties': True}, 'institution': {'type': 'object', 'description': 'Institution display name, state, and links.', 'additionalProperties': True}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Canonical credit-union identifier.'}, 'product_suitability': {'type': 'object', 'description': 'Separate published-constraint fit for supplied balance, audience, term, intent, vehicle condition, and occupancy where applicable.', 'additionalProperties': True}, 'product_availability': {'type': 'object', 'description': 'Whether a matching fresh evidenced published rate was found.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'Offers with a documented membership action and a fresh, evidenced published rate.'}}, 'description': 'Exhaustive active-fleet membership and fresh evidenced-rate routing result.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'result': {'type': 'object', 'description': 'The comparison result to format, if not using scenario_id'}, 'client_name': {'type': 'string', 'description': 'Client label, if not using scenario_id'}, 'scenario_id': {'type': 'string', 'description': 'Optional: a saved scenario id to build the report from'}, 'advisor_name': {'type': 'string', 'description': 'Optional advisor/company name for the report header'}}}
Ausgabeschema
{'type': 'object', 'properties': {'format': {'type': 'string', 'description': "Always 'markdown'."}, 'markdown': {'type': 'string', 'description': 'The full report: heading, advisor byline, scenario line, a ranked offer table of up to five lenders, and a not-an-offer-of-credit footer.'}}, 'description': 'A client-ready rate comparison rendered locally by the MCP server. Nothing is persisted and no link is created.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['scenario_id'], 'properties': {'scenario_id': {'type': 'string', 'description': 'The saved scenario id to mint a share link for. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'url': {'type': 'string', 'description': 'Public URL of the hosted report (app.rateapi.dev/r/<token>).'}, 'token': {'type': 'string', 'description': 'Share token — pass to revoke_share to disable the link.'}, 'created_at': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'scenario_id': {'type': 'string', 'description': 'Scenario the link renders.'}}, 'description': 'A public, revocable share link minted for one saved scenario.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'state': {'type': 'string', 'description': 'Filter to a specific US state (2-letter code). If omitted, returns nationwide benchmarks.'}, 'product_type': {'enum': ['mortgage_30yr', 'mortgage_15yr', 'mortgage_arm', 'auto_loan_new', 'auto_loan_used', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan'], 'type': 'string', 'description': 'Filter to a specific product type. If omitted, returns benchmarks for all product types.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'rawData': {'type': 'array', 'items': {'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': "Number of published offers behind this row's statistics."}, 'maxAPR': {'type': ['number', 'null'], 'description': 'Highest published APR in percent.'}, 'minAPR': {'type': ['number', 'null'], 'description': 'Lowest published APR in percent. Extreme lows can be data artifacts such as promotional or calculator-default values, so sanity-check against medianAPR.'}, 'medianAPR': {'type': ['number', 'null'], 'description': 'Median published APR in percent; the robust central number for this product.'}, 'displayName': {'type': ['string', 'null'], 'description': 'Human-readable label for the product category.'}, 'minAPRState': {'type': ['string', 'null'], 'description': 'Two-letter state code of the lender publishing the lowest APR.'}, 'productType': {'type': ['string', 'null'], 'description': "Normalized product category key, e.g. 'auto_loan_new', 'auto_loan_used', 'boat'."}, 'minAPRInstitution': {'type': ['string', 'null'], 'description': 'Credit union publishing the lowest APR for this product.'}, 'minAPRInstitutionId': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE' of that lender."}}, 'additionalProperties': True}, 'description': 'The same benchmarks as unformatted numbers, for calculation rather than display.'}, 'summary': {'type': ['string', 'null'], 'description': 'Plain-English headline of the benchmark set, e.g. the range of 30-year fixed APRs and how many credit unions publish them.'}, 'benchmarks': {'type': 'array', 'items': {'type': 'object', 'properties': {'asOf': {'type': ['string', 'null'], 'description': "UTC timestamp of the newest rate behind this product's benchmark."}, 'product': {'type': ['string', 'null'], 'description': "Human-readable product this row benchmarks, e.g. 'New Auto Loan (60 months)'."}, 'aprSpread': {'type': ['string', 'null'], 'description': 'Distance between highest and lowest APR, written out in percentage points; the size of the shopping-around prize.'}, 'lowestAPR': {'type': ['string', 'null'], 'description': 'Best published APR for this product as a percent string — one outlier deal, not what a typical borrower gets.'}, 'medianAPR': {'type': ['string', 'null'], 'description': "Median published APR as a percent string; the fairest single number for 'the going rate'."}, 'highestAPR': {'type': ['string', 'null'], 'description': 'Highest published APR as a percent string.'}, 'institutions': {'type': ['number', 'null'], 'description': 'Number of credit unions publishing this product; small counts make the median and spread unreliable.'}, 'lowestAPRProvider': {'type': ['string', 'null'], 'description': 'Credit union publishing the lowest APR, with its state in parentheses.'}}, 'additionalProperties': True}, 'description': 'Formatted per-product benchmark rows, one per product category, ready to present.'}, 'generatedAt': {'type': ['string', 'null'], 'description': "UTC timestamp when this benchmark response was assembled; the underlying rates are older, see each row's asOf."}, 'stateFilter': {'type': ['string', 'null'], 'description': "Scope of the benchmark set as a label — 'Nationwide' when no state narrowing was applied. Check this before describing the numbers as local."}, 'totalInstitutions': {'type': ['string', 'null'], 'description': 'Number of institutions behind the benchmark set, returned as a string rather than a number.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Cohort id. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'triage': {'type': 'array', 'items': {'type': 'object', 'properties': {'label': {'type': 'string', 'description': 'Member label.'}, 'best_apr': {'type': ['number', 'null'], 'description': 'Best APR percent, null when none was found.'}, 'best_lender': {'type': ['string', 'null'], 'description': 'Institution with the best offer, null when none was found.'}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly payment on the best offer.'}, 'savings_vs_current': {'type': ['number', 'null'], 'description': "Monthly saving against the member's stated current rate, when one was supplied."}}, 'additionalProperties': True}, 'description': "Every member's current best offer, the work list."}, 'changed': {'type': 'array', 'items': {'type': 'object', 'properties': {'to': {'type': 'object', 'description': 'Current best_lender and best_apr.', 'additionalProperties': True}, 'from': {'type': ['object', 'null'], 'description': 'Prior best_lender and best_apr. Absent for a new member.', 'additionalProperties': True}, 'label': {'type': 'string', 'description': 'Member label.'}, 'change': {'type': 'string', 'description': "'new', 'best_lender_changed', or 'apr_changed'."}, 'apr_delta': {'type': ['number', 'null'], 'description': 'Change in APR in percentage points.'}}, 'additionalProperties': True}, 'description': 'Members whose best offer moved since the previous snapshot.'}, 'scanned': {'type': 'number', 'description': 'Members evaluated in this scan.'}}, 'description': 'IMPORTANT: this tool runs a LIVE re-scan of the cohort and returns the scan result, not the stored cohort record. It does not return the member list. The payload is identical to scan_portfolio.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': [], 'properties': {'state': {'type': 'string', 'description': 'Optional 2-letter US state code to scope the matrix to a single state.'}, 'group_by': {'enum': ['state', 'product', 'state_product'], 'type': 'string', 'description': "Optional segmentation axis. Default 'state'."}, 'freshness_days': {'type': 'number', 'description': 'Optional uniform staleness window in days (1-90). OMIT to use per-category freshness windows — supplying a value overrides every category and is echoed back as freshness_mode=override.'}, 'product_category': {'enum': ['mortgage', 'auto', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal', 'credit_card', 'student', 'equipment'], 'type': 'string', 'description': 'Optional. Restrict the matrix to one product category. Omit for all.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Plain-English description of how this coverage matrix is grouped and what it totals.'}, 'totals': {'type': 'object', 'properties': {'rows': {'type': ['number', 'null'], 'description': 'Number of individual rate rows counted.'}, 'states': {'type': ['number', 'null'], 'description': 'Number of distinct states represented.'}, 'credit_unions': {'type': ['number', 'null'], 'description': 'Number of distinct credit unions contributing those rows.'}, 'product_types': {'type': ['number', 'null'], 'description': 'Number of distinct product types represented.'}}, 'description': 'Overall size of the covered dataset within the freshness window.', 'additionalProperties': True}, 'coverage': {'type': 'object', 'properties': {'states': {'type': 'array', 'description': 'Two-letter state codes present in this coverage snapshot.'}, 'product_types': {'type': 'array', 'description': 'Product type keys present, possibly truncated — see product_types_truncated_from.'}, 'product_types_truncated_from': {'type': ['number', 'null'], 'description': 'Full number of product types before the list above was truncated for display. Null when nothing was truncated.'}}, 'description': 'Which states and product types appear in the data, as flat lists.', 'additionalProperties': True}, 'segments': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': 'object', 'description': 'Observed APR range in this segment, as min and max in percent. Wide ranges usually mean the segment mixes dissimilar products.'}, 'key': {'type': ['string', 'null'], 'description': "Machine key for the segment, e.g. 'CA|30-year-fixed'."}, 'rows': {'type': ['number', 'null'], 'description': 'Number of rate rows in this segment.'}, 'label': {'type': ['string', 'null'], 'description': "Human-readable segment label, e.g. 'California · 30-year-fixed'."}, 'state': {'type': ['string', 'null'], 'description': 'Two-letter state code of the segment. Null when the grouping is not state-based.'}, 'is_fresh': {'type': ['boolean', 'null'], 'description': "True when the segment's newest rate falls inside window_days; false means the segment is stale and should be quoted with caution."}, 'window_days': {'type': ['number', 'null'], 'description': 'Freshness window in days applied to this specific segment.'}, 'last_updated': {'type': ['string', 'null'], 'description': 'UTC timestamp of the newest rate in this segment.'}, 'product_type': {'type': ['string', 'null'], 'description': "Product type of the segment. 'other' is a catch-all for products that did not classify into a named type."}, 'credit_unions': {'type': ['number', 'null'], 'description': 'Number of distinct credit unions contributing to this segment.'}, 'product_category': {'type': ['string', 'null'], 'description': "Broad category the segment belongs to, e.g. 'mortgage'."}}, 'additionalProperties': True}, 'description': 'Coverage broken down by the requested grouping, largest first.'}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'generated_at': {'type': ['string', 'null'], 'description': 'UTC timestamp when this coverage snapshot was computed.'}, 'next_actions': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Suggested follow-up tools given this coverage picture, as bare tool names.'}, 'freshness_days': {'type': ['number', 'null'], 'description': 'Age limit in days a rate must be within to be counted here; rows older than this are excluded from the totals.'}, 'freshness_mode': {'type': ['string', 'null'], 'description': "How the freshness window was chosen: 'per_category' applies a category-specific window instead of one global value."}, 'institution_profiles': {'type': 'object', 'properties': {'source': {'type': ['string', 'null'], 'description': 'Name of the regulatory dataset behind the institution profiles.'}, 'branches': {'type': ['number', 'null'], 'description': 'Total branch records held across all profiles.'}, 'profiles': {'type': ['number', 'null'], 'description': 'Number of institution profiles held.'}, 'websites': {'type': ['number', 'null'], 'description': 'Number of profiles carrying a website URL; the shortfall against `profiles` is the gap.'}, 'cycle_date': {'type': ['string', 'null'], 'description': 'Quarter-end date of the NCUA call report the profiles come from.'}, 'member_counts': {'type': ['number', 'null'], 'description': 'Number of profiles carrying a member count.'}, 'linked_credit_unions': {'type': ['number', 'null'], 'description': 'Number of credit unions successfully linked to an NCUA profile.'}}, 'description': 'Coverage of the NCUA institution reference data that backs lender context, separate from rate coverage.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'slug'], 'properties': {'slug': {'type': 'string', 'description': 'Credit union slug (URL-friendly name, e.g., "navy-federal-credit-union"). Required.'}, 'state': {'type': 'string', 'description': 'US state code (2-letter, e.g., CA, TX, NY). Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'widget': {'type': 'object', 'properties': {'data': {'type': 'object', 'description': 'Rows and labels the widget renders; a restatement of the rates above, not new data.'}, 'type': {'type': ['string', 'null'], 'description': "Widget renderer to use, e.g. 'rate_table'."}}, 'description': "Pre-built embeddable rendering of this credit union's rates for UI surfaces; ignore it when composing a text answer.", 'additionalProperties': True}, 'summary': {'type': ['string', 'null'], 'description': 'One-sentence plain-English summary of this result, safe to quote directly to the user.'}, 'all_rates': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['string', 'null'], 'description': "APR as a percent string, e.g. '6.147%'. The literal string 'not published' when the lender disclosed no APR — never quote `rate` in its place."}, 'rate': {'type': ['string', 'null'], 'description': 'Published rate as a percent string. For deposit products this is the yield the member earns, not a borrowing cost.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for this rate, where 1 point = 1% of the loan amount.'}, 'display_name': {'type': ['string', 'null'], 'description': 'Normalized, human-readable product name for comparison across lenders.'}, 'last_updated': {'type': ['string', 'null'], 'description': 'UTC timestamp when this rate was last scraped from the lender.'}, 'product_name': {'type': ['string', 'null'], 'description': "The lender's own wording for the product, which may be a balance tier such as '$10,000.00+'."}, 'product_type': {'type': ['string', 'null'], 'description': "Normalized product category, e.g. 'savings', 'cd_18mo', '30-year-fixed', 'auto_loan_new'."}}, 'additionalProperties': True}, 'description': 'Every rate currently on file for this credit union, deposits and loans together.'}, 'best_rate': {'type': 'object', 'properties': {'apr': {'type': ['string', 'null'], 'description': "APR of the best-ranked product as a percent string. The literal string 'not published' when the lender disclosed no APR — never quote `rate` in its place."}, 'rate': {'type': ['string', 'null'], 'description': 'Note rate of that product as a percent string.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for that rate, where 1 point = 1% of the loan amount.'}, 'product': {'type': ['string', 'null'], 'description': "Name of the product this best rate belongs to, in the lender's own wording."}}, 'description': 'The single most attractive rate on file for this credit union across every product it publishes — it may be a deposit product, so check `product` before calling it a loan rate.', 'additionalProperties': True}, 'eligibility': {'type': 'object', 'properties': {'rules': {'type': 'array', 'items': {'type': 'object', 'properties': {'kind': {'type': ['string', 'null'], 'description': 'Membership-path category.'}, 'rule_id': {'type': ['integer', 'null'], 'description': 'Stable identifier of the published rule.'}, 'conditions': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Conditions that must all hold for this membership path.'}, 'confidence': {'type': ['number', 'null'], 'description': 'Confidence in this verified rule from 0 to 1.'}, 'source_url': {'type': ['string', 'null'], 'description': 'Source page containing the supporting evidence.'}, 'description': {'type': ['string', 'null'], 'description': 'Deterministic human-readable rendering of the rule.'}, 'observed_at': {'type': ['string', 'null'], 'description': 'UTC timestamp when the source evidence was observed.'}, 'evidence_quote': {'type': ['string', 'null'], 'description': 'Verbatim source excerpt supporting the rule.'}, 'last_confirmed_at': {'type': ['string', 'null'], 'description': 'UTC timestamp of the latest confirmation.'}, 'verification_status': {'type': ['string', 'null'], 'description': 'How far evidence and semantic verification progressed.'}}, 'additionalProperties': True}, 'description': 'Every verified rule in the exact active publication, including machine-readable conditions and evidence provenance. Unverified proposals are not included.'}, 'source': {'type': ['string', 'null'], 'description': "Where the eligibility record came from, e.g. 'scraped' from the credit union's own website."}, 'schools': {'type': 'array', 'description': 'Schools or districts whose students, staff, or alumni qualify.'}, 'military': {'type': 'object', 'description': 'Verified military-service membership paths, when published.', 'additionalProperties': True}, 'employers': {'type': 'array', 'description': 'Employers whose staff qualify for membership. Empty means no employer-based path was found.'}, 'join_path': {'description': 'The easiest documented route to membership when one is known. Null means no simple published path was found, not that none exists.'}, 'confidence': {'type': ['number', 'null'], 'description': 'Confidence in this eligibility record, from 0 to 1. Values below about 0.7 should be presented as uncertain.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required caveat that eligibility is guidance from public data and the credit union makes the final decision.'}, 'geo_cities': {'type': 'array', 'description': 'Cities whose residents or workers qualify. Empty means eligibility is not defined at city level.'}, 'geo_states': {'type': 'array', 'description': 'States whose residents qualify. Empty means eligibility is not defined at state level.'}, 'updated_at': {'type': ['string', 'null'], 'description': 'UTC timestamp when the eligibility record was last refreshed.'}, 'occupations': {'type': 'array', 'description': 'Occupations that qualify for membership, e.g. teachers or first responders.'}, 'publication': {'type': 'object', 'properties': {'activated_at': {'type': ['string', 'null'], 'description': 'UTC timestamp when this publication became serving authority.'}, 'publication_id': {'type': ['integer', 'null'], 'description': 'Database identifier of the active publication.'}, 'ruleset_sha256': {'type': ['string', 'null'], 'description': 'SHA-256 digest of the complete ordered published rule set.'}, 'proposal_coverage': {'type': 'object', 'properties': {'scope': {'type': ['string', 'null'], 'description': 'Always source_page_model_proposals; distinguishes this metric from real-world FOM completeness.'}, 'proposed_claims': {'type': ['integer', 'null'], 'description': 'Claims proposed from the source page.'}, 'published_rules': {'type': ['integer', 'null'], 'description': 'Verified rules published from those claims.'}, 'verified_claims': {'type': ['integer', 'null'], 'description': 'Proposed claims that survived evidence verification.'}, 'withheld_claims': {'type': ['integer', 'null'], 'description': 'Claims withheld because verification did not pass.'}, 'withheld_reasons': {'type': 'object', 'description': 'Counts of withheld claims grouped by machine-readable reason.', 'additionalProperties': True}, 'proposal_survival': {'type': ['number', 'null'], 'description': 'Verified divided by proposed claims, or null when none were proposed.'}}, 'description': 'Coverage of model-proposed claims on the source page. It does not assert that every real-world membership path is known.', 'additionalProperties': True}}, 'description': 'Exact immutable active graph publication backing `rules`.', 'additionalProperties': True}, 'associations': {'type': 'array', 'description': 'Associations or groups whose members qualify, often the easiest path for outsiders.'}, 'evidence_url': {'type': ['string', 'null'], 'description': "Page on the credit union's site that the eligibility rules were read from; cite it when stating who can join."}, 'extracted_at': {'type': ['string', 'null'], 'description': 'UTC timestamp when the eligibility rules were first extracted.'}, 'geo_counties': {'type': 'array', 'description': 'Counties whose residents or workers qualify under a community charter.'}, 'worship_orgs': {'type': 'array', 'description': 'Congregations or religious organizations whose members qualify.'}, 'rules_summary': {'type': 'object', 'description': 'Deterministic counts and freshness summary of the returned verified rules; not a closed-world field-of-membership attestation.', 'additionalProperties': True}, 'open_to_anyone': {'type': ['boolean', 'null'], 'description': 'True when anyone can join, typically via a small association or donation. False means a specific qualification is required.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE'."}, 'min_deposit_usd': {'description': 'Minimum share deposit in dollars required to open membership. Null means none was published.'}, 'eligibility_type': {'type': ['string', 'null'], 'description': "Type of charter driving membership, e.g. 'community' (geography-based), 'multi' (several qualifying paths), 'unknown'."}, 'family_membership': {'type': ['boolean', 'null'], 'description': 'True when a family member of an existing member also qualifies.'}, 'membership_fee_usd': {'description': 'One-time membership or association fee in dollars. Null means no fee was published, not that it is free.'}, 'requirements_summary': {'type': ['string', 'null'], 'description': 'One-line plain-English statement of who qualifies; the best field to quote to the user.'}}, 'description': 'Who may join this credit union, derived from its published membership criteria — guidance, not an underwriting decision.', 'additionalProperties': True}, 'credit_union': {'type': 'object', 'properties': {'url': {'type': ['string', 'null'], 'description': "The credit union's own website."}, 'city': {'type': ['string', 'null'], 'description': 'Headquarters city, lower-cased as stored.'}, 'name': {'type': ['string', 'null'], 'description': 'Full credit union name as displayed.'}, 'state': {'type': ['string', 'null'], 'description': 'Two-letter state code of the headquarters.'}, 'state_name': {'type': ['string', 'null'], 'description': 'Full state name of the headquarters.'}, 'last_verified': {'type': ['string', 'null'], 'description': "UTC timestamp when this credit union's rates were last successfully re-scraped. Null means never successfully scraped."}}, 'description': 'Core identity and freshness facts for this credit union.', 'additionalProperties': True}, 'ncua_profile': {'type': 'object', 'properties': {'source': {'type': ['string', 'null'], 'description': 'Name of the regulatory dataset these institution facts come from.'}, 'services': {'type': 'object', 'description': 'Which services the institution reports offering, such as online membership applications and online loan applications.'}, 'cycleDate': {'type': ['string', 'null'], 'description': 'Quarter-end date of the NCUA call report these figures are from; they can be several months old.'}, 'locations': {'type': 'object', 'description': 'Branch footprint: total branches reported, how many are included here, and the branch records themselves.'}, 'sourceUrl': {'type': ['string', 'null'], 'description': 'NCUA page the call-report data is published on.'}, 'financials': {'type': 'object', 'description': 'Balance-sheet size from the call report: total assets in dollars, current members, and potential members in the field of membership.'}, 'websiteUrl': {'type': ['string', 'null'], 'description': 'Website as reported to NCUA; may be stale or differ from credit_union.url.'}, 'yearOpened': {'type': ['number', 'null'], 'description': 'Four-digit year the credit union was founded.'}, 'charterType': {'type': 'object', 'description': 'Charter code and its label, e.g. federally insured state-chartered versus federally chartered.'}, 'charterState': {'type': ['string', 'null'], 'description': 'State that issued the charter, which can differ from where branches operate.'}, 'designations': {'type': 'object', 'description': 'Special NCUA designations such as low-income or minority depository institution status.'}, 'insuredSince': {'type': ['string', 'null'], 'description': 'Date federal share insurance began for this institution.'}, 'officialName': {'type': ['string', 'null'], 'description': 'Legal name as filed with NCUA, usually upper-cased and often differing from the marketing name.'}, 'charterNumber': {'type': ['string', 'null'], 'description': "The credit union's NCUA charter number."}}, 'description': 'Institution facts from the NCUA quarterly call report — regulator-filed data, independent of the scraped rates.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'limit': {'type': 'number', 'description': 'Top N credit unions to rank (default 10, clamp 1..50).'}, 'state': {'type': 'string', 'description': '2-letter US state code; omit for nationwide.'}, 'metric': {'enum': ['apy'], 'type': 'string', 'description': 'Deposits rank by APY, highest first. No APR.'}, 'product': {'enum': ['savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'MCP field for the deposit product category. Use an exact enum value such as `money_market`; do not use REST field name `product_category`, `mma`, or `money-market`. Omit for all deposit types.'}, 'term_months': {'type': 'number', 'description': 'For CD/share_certificate/ira_cd: filter to a specific term (savings_term_months).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'best': {'type': 'object', 'properties': {'apy': {'type': ['number', 'null'], 'description': 'Highest annual percentage yield in percent (4.1 = 4.10% APY). This is a yield the member earns, not a borrowing cost.'}, 'lender': {'type': ['string', 'null'], 'description': 'Credit union publishing the highest APY.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Term in months of the best offer.'}}, 'description': 'The single highest-yielding offer found.', 'additionalProperties': True}, 'note': {'type': ['string', 'null'], 'description': 'Data caveats for this response, including that APY is shown rather than APR and that history is retention-bounded.'}, 'as_of': {'type': ['string', 'null'], 'description': 'UTC timestamp of the underlying rate data. This is when the rates were last scraped from lender sites, not when this call ran.'}, 'count': {'type': ['number', 'null'], 'description': "Number of rows returned in `table`, capped by the caller's limit."}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'table': {'type': 'array', 'items': {'type': 'object', 'properties': {'apy': {'type': ['number', 'null'], 'description': 'Annual percentage yield in percent, compounding included. Do not describe it as an APR.'}, 'best': {'type': ['boolean', 'null'], 'description': 'True on the single highest-APY row in this table.'}, 'lender': {'type': ['string', 'null'], 'description': 'Credit union publishing this offer.'}, 'position': {'type': ['number', 'null'], 'description': 'Rank in this table, 1 = highest APY.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Term in months for this certificate. Null for products without a fixed term.'}, 'savings_subtype': {'description': 'Subtype of savings product, such as a money-market or youth account. Null when the lender did not distinguish.'}, 'bps_below_leader': {'type': ['number', 'null'], 'description': 'How far this offer sits below the top APY, in basis points (10 = 0.10 percentage points). 0 marks the leader.'}}, 'additionalProperties': True}, 'description': 'Ranked deposit offers, highest APY first.'}, 'market': {'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of offers behind the market statistics. This can exceed total_credit_unions when one credit union publishes several tiers.'}, 'max_apy': {'type': ['number', 'null'], 'description': 'Highest APY in percent published, matching `best.apy` when the table is not filtered further.'}, 'min_apy': {'type': ['number', 'null'], 'description': 'Lowest APY in percent published in this market.'}, 'median_apy': {'type': ['number', 'null'], 'description': 'Median APY in percent; the right comparison for whether an offer is good.'}}, 'description': 'Distribution of APYs across the market for this product, for context around `best`.', 'additionalProperties': True}, 'term_months': {'type': ['number', 'null'], 'description': 'Certificate term in months these rows are scoped to. Null for non-term products like savings.'}, 'product_category': {'type': ['string', 'null'], 'description': "Deposit product benchmarked, e.g. 'cd', 'savings', 'money_market'."}, 'benchmark_balance': {'description': 'Deposit balance in dollars the rates are quoted at. Null means no balance tier was applied, so tiered rates may not be comparable.'}, 'total_credit_unions': {'type': ['number', 'null'], 'description': 'Number of credit unions publishing this deposit product in scope — larger than `count` when the table is truncated.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product'], 'properties': {'state': {'type': 'string', 'description': '2-letter US state code'}, 'window': {'enum': ['90d', '180d', '365d'], 'type': 'string', 'default': '180d'}, 'product': {'enum': ['savings', 'cd', 'share_certificate', 'money_market', 'ira_cd'], 'type': 'string', 'description': 'Required MCP product field. Use one exact underscore enum value; money market is `money_market`, never `mma` or `money-market`.'}, 'group_by': {'enum': ['overall', 'state', 'cu'], 'type': 'string', 'default': 'overall'}, 'benchmark': {'enum': ['cd_top_quartile', 'treasury', 'fed_funds'], 'type': 'string', 'default': 'cd_top_quartile'}, 'term_months': {'type': 'number'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Methodology caveat explaining that this is a short-window beta from retained published history, not a full-cycle beta.'}, 'peer': {'type': 'object', 'properties': {'max_beta': {'description': 'Highest deposit beta among peers, as a ratio. Null when too little history exists.'}, 'min_beta': {'description': 'Lowest deposit beta among peers, as a ratio (0.3 = deposit rates moved 30% as much as the benchmark). Null when too little history exists to compute it.'}, 'median_beta': {'description': 'Median deposit beta among peers, as a ratio. Null when too little history exists.'}}, 'description': 'Distribution of beta across the peer group.', 'additionalProperties': True}, 'state': {'description': 'Two-letter state code the analysis was scoped to. Null means nationwide.'}, 'window': {'type': ['string', 'null'], 'description': "Lookback period used for the comparison, expressed as a short duration string such as '4w', '90d', or '180d'."}, 'product': {'type': ['string', 'null'], 'description': "Deposit product the beta was computed for, e.g. 'savings' or 'cd'."}, 'group_by': {'type': ['string', 'null'], 'description': "How results are grouped, e.g. 'cu' for one segment per credit union."}, 'segments': {'type': 'array', 'description': 'One beta result per group. An empty array means the retained history was too shallow to compute any beta, not that beta is zero.'}, 'confidence': {'type': ['string', 'null'], 'description': "Qualitative reliability of the beta estimate — 'low' when the history window is short relative to a full rate cycle."}, 'data_source': {'type': ['string', 'null'], 'description': "Internal backing store that served this query ('clickhouse'); operational detail, not something to report to the user."}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'term_months': {'description': 'Certificate term in months the analysis was scoped to. Null for non-term products.'}, 'benchmark_used': {'type': ['string', 'null'], 'description': 'The benchmark actually used, which can differ from benchmark_requested when the requested one lacked data.'}, 'history_depth_days': {'type': ['number', 'null'], 'description': 'Days of retained rate history available for this calculation. 0 means no usable history, so every beta is null.'}, 'benchmark_requested': {'type': ['string', 'null'], 'description': "The benchmark the caller asked deposit rates to be measured against, e.g. 'cd_top_quartile'."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'url': {'type': 'string', 'description': 'Alternatively, the canonical published URL of the page.'}, 'slug': {'enum': ['quickstart', 'authentication', 'rate-limits-and-pricing', 'coverage', 'freshness', 'evidence-and-methodology', 'quoting-rules', 'eligibility', 'endpoints', 'mcp-server', 'products-and-parameters', 'errors-and-troubleshooting', 'deprecation-policy'], 'type': 'string', 'description': 'The page identifier returned by search_docs.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'url': {'type': ['string', 'null'], 'description': 'Canonical published URL to cite.'}, 'slug': {'type': ['string', 'null'], 'description': 'The page identifier.'}, 'error': {'type': ['string', 'null'], 'description': 'Present when no page matched the reference given.'}, 'title': {'type': ['string', 'null'], 'description': 'Page title.'}, 'content': {'type': ['string', 'null'], 'description': 'Full page text in markdown, ending with its source URL.'}, 'summary': {'type': ['string', 'null'], 'description': 'One-line description of the page.'}, 'available': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Valid slugs, returned alongside an error.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['since'], 'properties': {'limit': {'type': 'integer', 'default': 100, 'maximum': 200, 'minimum': 1, 'description': 'Maximum publication changes returned.'}, 'since': {'type': 'string', 'format': 'date-time', 'maxLength': 64, 'description': 'Exclusive ISO 8601 activation boundary with an offset.'}, 'cursor': {'type': 'string', 'maxLength': 1000, 'minLength': 1, 'description': 'Opaque next_cursor from the prior page; do not construct or modify it.'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'since': {'type': ['string', 'null'], 'description': 'Normalized exclusive activation boundary.'}, 'changes': {'type': 'array', 'items': {'type': 'object', 'properties': {'change': {'type': 'object', 'description': 'Prior publication id when present and aggregate current membership-kind counts.', 'additionalProperties': True}, 'activated_at': {'type': ['string', 'null'], 'description': 'Publication activation timestamp.'}, 'publication_id': {'type': ['number', 'null'], 'description': 'Current active publication id.'}, 'ruleset_sha256': {'type': ['string', 'null'], 'description': 'Immutable active ruleset digest.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Stable credit-union id whose active publication changed.'}}, 'additionalProperties': True}, 'description': 'Active publication replacements in stable ascending order.'}, 'has_more': {'type': ['boolean', 'null'], 'description': 'Whether another page is available.'}, 'ordering': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Stable ordering columns.'}, 'returned': {'type': ['number', 'null'], 'description': 'Number of changes in this page.'}, 'semantics': {'type': ['string', 'null'], 'description': 'Active-publication incremental cache-invalidation contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required warning that this is not a personal eligibility verdict or full history.'}, 'next_cursor': {'type': ['string', 'null'], 'description': 'Opaque cursor for the next page, or null.'}}, 'description': 'Cursor-paginated active-publication replacement feed for cache invalidation.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'as_of': {'type': ['string', 'null'], 'description': 'Most recent rule confirmation across the live graph (ISO 8601) — the moment the data last moved.'}, 'fleet': {'type': ['object', 'null'], 'properties': {'active_institutions': {'type': ['number', 'null'], 'description': 'Active US credit unions in the directory.'}, 'share_with_live_rules': {'type': ['number', 'null'], 'description': 'institutions_with_live_rules / active_institutions, 0–1.'}, 'institutions_with_live_rules': {'type': ['number', 'null'], 'description': 'Distinct credit unions with at least one live (non-superseded) rule.'}}, 'description': 'The denominator: active institutions and how many the graph holds live rules for.', 'additionalProperties': True}, 'reach': {'type': ['object', 'null'], 'properties': {'counties_named': {'type': ['number', 'null'], 'description': 'Distinct county keys in live, non-negated conditions.'}, 'employers_resolved': {'type': ['number', 'null'], 'description': 'Distinct canonical organizations named by employment conditions.'}, 'states_with_county_rules': {'type': ['number', 'null'], 'description': 'Distinct states those county keys belong to.'}, 'institutions_open_to_anyone': {'type': ['number', 'null'], 'description': 'Institutions with a live open_to_anyone condition (passes a two-vendor gate, so deliberately few).'}, 'institutions_with_county_rules': {'type': ['number', 'null'], 'description': 'Institutions with at least one live county-level condition.'}, 'institutions_with_school_rules': {'type': ['number', 'null'], 'description': 'Institutions with a live student/alumni/school-employee condition.'}, 'institutions_with_worship_rules': {'type': ['number', 'null'], 'description': 'Institutions with a live place-of-worship condition.'}, 'institutions_with_employer_rules': {'type': ['number', 'null'], 'description': 'Institutions with at least one resolved employment condition.'}, 'institutions_with_military_rules': {'type': ['number', 'null'], 'description': 'Institutions with a live military-affiliation condition.'}}, 'description': 'How specific the rules are: distinct places and organizations named, and institutions carrying each path type.', 'additionalProperties': True}, 'rules': {'type': ['object', 'null'], 'properties': {'live': {'type': ['number', 'null'], 'description': 'Rules not superseded.'}, 'auto_validated': {'type': ['number', 'null'], 'description': 'Live rules machine-validated against a second independent read.'}, 'human_verified': {'type': ['number', 'null'], 'description': 'Live rules verified by a person or the institution.'}, 'median_age_days': {'type': ['number', 'null'], 'description': 'Median days since each live rule was last confirmed.'}, 'confirmed_within_30d': {'type': ['number', 'null'], 'description': 'Live rules confirmed within the last 30 days.'}, 'with_verbatim_evidence': {'type': ['number', 'null'], 'description': 'Equals live by construction: a rule cannot be stored without its evidence quote.'}}, 'description': 'Live rule counts, verification split and freshness.', 'additionalProperties': True}, 'by_kind': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'rules': {'type': ['number', 'null'], 'description': 'Live rules of this kind.'}, 'rule_kind': {'type': ['string', 'null'], 'description': 'geography | employment | association | education | military | worship | family | household | open | deposit_or_donation | other.'}, 'institutions': {'type': ['number', 'null'], 'description': 'Distinct institutions with at least one live rule of this kind.'}}, 'additionalProperties': True}, 'description': 'Live rules and distinct institutions per rule kind, largest first.'}, 'headline': {'type': ['string', 'null'], 'description': 'One dated sentence carrying every headline number next to its denominator. Quote it verbatim.'}, 'pipeline': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'status': {'type': ['string', 'null'], 'description': 'published | no_source_found | needs_review | pending | failed.'}, 'institutions': {'type': ['number', 'null'], 'description': 'Institutions currently in this status.'}}, 'additionalProperties': True}, 'description': 'Institutions by eligibility pipeline status — why an institution may be absent from the graph (no source found, needs review, pending).'}, 'authority': {'type': ['object', 'null'], 'properties': {'latest_activation': {'type': ['string', 'null'], 'description': 'Most recent immutable publication activation (ISO 8601).'}, 'active_publications': {'type': ['number', 'null'], 'description': 'Charters governed by an exact immutable active-publication pointer.'}, 'flat_only_institutions': {'type': ['number', 'null'], 'description': 'Active institutions represented only by the lossy flat compatibility record.'}, 'active_publication_rules': {'type': ['number', 'null'], 'description': 'Rules declared by exact active publications.'}, 'legacy_graph_institutions': {'type': ['number', 'null'], 'description': 'Institutions with live graph rules but no immutable active-publication pointer.'}, 'selection_bound_publications': {'type': ['number', 'null'], 'description': 'Active publications carrying selection-bound append-only provenance.'}, 'publications_with_proposal_coverage': {'type': ['number', 'null'], 'description': 'Active publications reporting proposed, verified and withheld claim counts.'}}, 'description': 'Serving-authority adoption. Exact immutable publications are separated from older graph and flat compatibility records.', 'additionalProperties': True}, 'semantics': {'type': ['string', 'null'], 'description': 'How to read the counts: live rules only; absence from the graph is undecided, never ineligible; where row-level verdicts live.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Statement that must accompany any consumer-facing use of eligibility data.'}, 'population': {'type': ['object', 'null'], 'properties': {'kind': {'type': ['string', 'null'], 'description': 'Aggregate graph-inventory population kind.'}, 'rule_scope': {'type': ['string', 'null'], 'description': 'Rule population included in the inventory.'}, 'fleet_scope': {'type': ['string', 'null'], 'description': 'Institution population used for the fleet denominator.'}, 'is_reachable_offer_count': {'type': ['boolean', 'null'], 'description': 'False: this is never a count of proven suitable offers.'}, 'observation_time_semantics': {'type': ['string', 'null'], 'description': 'Why the newest confirmation is not the age of every rule.'}, 'is_personal_eligibility_decision': {'type': ['boolean', 'null'], 'description': 'False: this aggregate is never a decision about a person.'}}, 'description': 'Population disclosure: graph inventory, not a personal eligibility decision or reachable-offer count.', 'additionalProperties': True}, 'credit_data': {'type': ['object', 'null'], 'properties': {'note': {'type': ['string', 'null'], 'description': 'Plain-language statement of the above, safe to quote.'}, 'conditions_referencing_credit': {'type': ['number', 'null'], 'description': 'Always 0: the condition schema has no kind for credit score, income or debt.'}}, 'description': 'Explicit statement that no rule condition references credit data.', 'additionalProperties': True}, 'generated_at': {'type': ['string', 'null'], 'description': 'When the aggregate was computed (ISO 8601). Edge-cached for an hour.'}, 'evidence_sources': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'rules': {'type': ['number', 'null'], 'description': 'Live rules supported by this source class.'}, 'source_type': {'type': ['string', 'null'], 'description': 'Recorded source class, such as membership_page, application_page, ncua or unknown.'}, 'institutions': {'type': ['number', 'null'], 'description': 'Distinct institutions with at least one live rule from this source class.'}}, 'additionalProperties': True}, 'description': 'Live rule counts by recorded evidence source class; institution counts may overlap.'}}, 'description': 'Fleet-wide membership-eligibility coverage, passed through from the Enterprise RateAPI Routes GET /v1/eligibility/coverage operation. Every count sits next to the stage it belongs to; nothing here is institution-level.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'branding': {'type': ['object', 'null'], 'properties': {'logo_url': {'type': ['string', 'null'], 'description': 'Public logo URL.'}, 'intro_text': {'type': ['string', 'null'], 'description': 'Default intro paragraph.'}, 'brand_color': {'type': ['string', 'null'], 'description': 'Accent color as a #hex string.'}, 'display_name': {'type': ['string', 'null'], 'description': 'From-name and CAN-SPAM advertiser identity.'}, 'logo_email_url': {'type': ['string', 'null'], 'description': 'Email-optimized logo variant.'}, 'reply_to_email': {'type': ['string', 'null'], 'description': 'Optional Reply-To address.'}, 'organization_id': {'type': 'string', 'description': 'Owning organization.'}, 'business_address': {'type': ['string', 'null'], 'description': 'CAN-SPAM physical address.'}, 'logo_background_color': {'type': ['string', 'null'], 'description': 'Logo backdrop as a 6-digit #hex string.'}}, 'description': 'The stored branding row, or null when the organization has never set branding.', 'additionalProperties': True}}, 'description': "The organization's email branding, wrapped in a `branding` envelope.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'endTime': {'type': 'string', 'description': 'End of the time range. Supports ISO8601 or relative times. Defaults to "now".'}, 'startTime': {'type': 'string', 'description': 'Start of the time range. Supports ISO8601 (e.g., "2024-01-15T00:00:00Z") or relative times ("now-24h", "now-7d", "now-1m"). Defaults to "now-24h".'}, 'product_type': {'enum': ['mortgage', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'personal_loan', 'heloc', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Filter statistics to a specific product type. If omitted, returns stats for all product types.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'query': {'type': ['object', 'null'], 'description': 'The resolved time window and filters the stats were computed over.', 'additionalProperties': True}, 'stats': {'type': 'object', 'properties': {'totalRates': {'type': 'string', 'description': "Rates extracted in the window, comma-formatted (e.g. '104,522')."}, 'hoursInRange': {'type': ['number', 'string', 'null'], 'description': 'Length of the window in hours.'}, 'ratesPerHour': {'type': 'string', 'description': 'Average rates per hour, comma-formatted.'}, 'activeInstitutions': {'type': 'string', 'description': 'Institutions that produced rates, comma-formatted.'}}, 'description': 'Headline counters. Note the string formatting.', 'additionalProperties': True}, 'summary': {'type': 'string', 'description': 'One-line headline of rates extracted, per-hour throughput, and institution count.'}, 'coverage': {'type': 'object', 'properties': {'states': {'type': ['number', 'array', 'null'], 'description': 'States covered.'}, 'institutions': {'type': 'string', 'description': 'Total institutions, comma-formatted string.'}, 'productTypes': {'type': ['number', 'array', 'null'], 'description': 'Product types covered.'}, 'activeInstitutions': {'type': 'string', 'description': 'Institutions active in the window, comma-formatted string.'}}, 'description': 'Breadth of the dataset.', 'additionalProperties': True}, 'products': {'type': 'array', 'items': {'type': 'object', 'properties': {'name': {'type': ['string', 'null'], 'description': 'Display name.'}, 'type': {'type': ['string', 'null'], 'description': 'Machine product type.'}, 'count': {'type': 'string', 'description': 'Rate count, comma-formatted string.'}, 'percentage': {'type': 'string', 'description': "Share of the window, e.g. '12.3%'."}}, 'additionalProperties': True}, 'description': 'Full product-type breakdown.'}, 'dataQuality': {'type': ['object', 'null'], 'description': 'Data-health indicators, passed through unchanged from /v1/stats.', 'additionalProperties': True}, 'generatedAt': {'type': ['string', 'null'], 'description': 'ISO-8601 time the stats were computed.'}, 'topProducts': {'type': 'string', 'description': "Pre-rendered 'name: count (pct%)' string for the three largest product types."}, 'hourlyTrendSample': {'type': 'array', 'items': {'type': 'object', 'properties': {'hour': {'type': ['string', 'number', 'null'], 'description': 'Bucket label.'}, 'total': {'type': ['number', 'null'], 'description': 'Rates extracted in that hour.'}}, 'additionalProperties': True}, 'description': 'First six hourly buckets of the trend series (a sample, not the full series).'}}, 'description': 'Rate-extraction activity for a time window. The handler reshapes /v1/stats: the headline counts are returned as locale-formatted STRINGS, not numbers.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'intent', 'amount'], 'properties': {'zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': "User's US 5-digit ZIP or ZIP+4. Resolves to a county server-side for membership-eligibility matching; its crosswalk state must agree with state."}, 'state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC code (2-letter, e.g., CA, TX, NY). Required; lowercase is accepted and normalized.'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars (minimum 1000). Required.'}, 'county': {'type': 'string', 'description': "User's county for membership-eligibility matching (credit union field-of-membership). Helps flag which lenders the user can actually join."}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'The loan intent. For mortgages, use "purchase" or "refinance". For auto loans, use "purchase" (new/used car) or "refinance" (existing auto loan). Required.'}, 'school': {'type': 'string', 'description': "User's school/college/university. Supply school_relationship too; a school name alone does not affirm a typed eligibility path."}, 'worship': {'type': 'string', 'description': "User's place of worship, used to annotate offers with worship-org-affinity eligibility."}, 'employer': {'type': 'string', 'description': "User's employer, matched against credit union employer/SEG membership lists for eligibility."}, 'no_points': {'type': 'boolean', 'description': 'If true, prefer no-points loans only. Applies to mortgages.'}, 'current_apr': {'type': 'number', 'description': 'Current offer APR if refinancing (percentage).'}, 'term_months': {'type': 'number', 'description': 'Loan term in months (12-480). Defaults to 360 (30-year) for mortgages, 60 (5-year) for auto loans. Common auto loan terms: 36, 48, 60, 72, 84 months. Common mortgage terms: 180 (15-year), 360 (30-year).'}, 'credit_score': {'type': 'number', 'description': "Borrower's credit score (300-850). Highly recommended for accurate rate matching."}, 'current_rate': {'type': 'number', 'description': 'Current offer rate if refinancing (percentage, e.g., 6.5 for 6.5%).'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'personal_loan', 'heloc', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product: "mortgage" (FIXED-rate home purchase/refinance), "mortgage_arm" (ADJUSTABLE-rate mortgage), "auto_loan" (vehicle financing), "heloc" (home equity line of credit), "personal_loan" (general purpose loans), "credit_card" (credit card offers), "student_loan" (student/education loans, incl. refinance and graduate loans), "equipment_loan" (farm/heavy equipment and tractor financing). Defaults to "mortgage". Pick "mortgage_arm" whenever the user says ARM, adjustable, or names a slash pair ("5/1", "5/5", "7/1", "10/1") — fixed and adjustable are ranked as SEPARATE markets, because an ARM intro rate sits structurally below a comparable fixed rate and a blended list would put every ARM on top and call it cheaper, which is true only until it resets. Within "mortgage", term_months selects 15- vs 30-year; it has no meaning for "mortgage_arm".'}, 'vehicle_type': {'enum': ['car', 'truck', 'suv', 'motorcycle', 'rv', 'boat'], 'type': 'string', 'description': 'AUTO LOANS ONLY: Type of vehicle being financed. Some lenders offer specialized rates by vehicle type.'}, 'vehicle_year': {'type': 'number', 'description': 'AUTO LOANS ONLY: Model year of the vehicle (e.g., 2024, 2020). Used to determine age-based rate tiers.'}, 'eligible_only': {'type': 'boolean', 'description': 'BETA (annotation-only): eligible_only is in beta pending identity-verification thresholds; offers are annotated, not filtered. Setting true adds an eligible_only_status notice to the response — eligibility annotates and re-ranks, but no offers are dropped. When an annotation comes back unknown, that is not a no: call find_eligible_credit_unions or check_membership_eligibility and read `missing_facts` — ask those questions before concluding no offers exist. eligible_only is beta.'}, 'max_providers': {'type': 'number', 'description': 'Maximum number of providers to return (1-5). Defaults to 5.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': "User's military affiliation. Annotates offers with eligible_via_military where the credit union has a military field of membership."}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'any'], 'type': 'string', 'description': 'AUTO LOANS ONLY: Condition of the vehicle being purchased or refinanced. Affects rate eligibility.'}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the user relates to the named school. Required with school to affirm a typed student, alumni, or school-employee path.'}, 'include_out_of_state': {'type': 'boolean', 'description': 'Optional: Include documented out-of-state open or multi-state credit-union candidates. Defaults to false, which preserves the requested-state candidate set.'}, 'include_institution_context': {'type': 'boolean', 'description': 'Optional: Include compact NCUA quarterly facts on each final offer (members, locations, assets, year opened, and selected relationship services).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'why': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Ordered reasons supporting the recommendation, each already written as a user-facing sentence.'}, 'summary': {'type': ['string', 'null'], 'description': "Headline verdict for the user in one line, e.g. 'Shop Around - Better rates available'."}, 'tradeoffs': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Costs, caveats, and conditions the user should weigh before acting, such as closing costs or membership requirements.'}, 'rate_range': {'type': 'object', 'properties': {'max': {'type': ['string', 'null'], 'description': 'Highest rate found, as a percent string.'}, 'min': {'type': ['string', 'null'], 'description': 'Lowest rate found, as a percent string.'}}, 'description': 'Span of rates across the offers considered, for framing how much shopping around is worth.', 'additionalProperties': True}, 'request_id': {'type': ['string', 'null'], 'description': 'Opaque identifier for this call, useful only for support or debugging; never show it to the user.'}, 'top_offers': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['string', 'null'], 'description': "Annual percentage rate as a percent string, e.g. '6.283%'. The literal string 'not published' when the lender disclosed no APR — the API never substitutes the note rate, so do not treat `rate` as the APR."}, 'url': {'type': ['string', 'null'], 'description': "The credit union's own website."}, 'rank': {'type': ['number', 'null'], 'description': 'Position in this list, 1 = best offer by the ranking used here.'}, 'rate': {'type': ['string', 'null'], 'description': "Note rate as a percent string (e.g. '6%') — the rate used to compute the payment, excluding fees."}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required to get this rate, where 1 point = 1% of the loan amount. 0 means no points.'}, 'product': {'type': ['string', 'null'], 'description': "Display name of the lender's product, e.g. '30-Year Fixed'."}, 'provider': {'type': ['string', 'null'], 'description': 'Name of the credit union publishing this offer.'}, 'eligibility': {'type': 'object', 'properties': {'status': {'type': ['string', 'null'], 'description': 'Decision-time compatibility status. A graph-source explanation governs this projection: its safe nonnegative legacy_status is used, otherwise MCP emits conservative likely_eligible; a graph unknown remains unknown. `geo_mismatch` is reserved for wire compatibility.'}, 'unknown_reason': {'type': ['string', 'null'], 'description': 'Machine-readable reason for `unknown`; `fom_completeness_unaffirmed` means the published membership corpus is not attested complete.'}}, 'description': 'Whether the user can likely join this credit union. Open-world non-matches remain `unknown`; MCP does not expose an unattested denial.', 'additionalProperties': True}, 'rateapi_url': {'type': ['string', 'null'], 'description': 'Public rateapi.dev profile page for this credit union, safe to link the user to.'}, 'loan_program': {'type': ['string', 'null'], 'description': "Underwriting program, e.g. 'conventional', 'va', 'fha', 'jumbo'."}, 'credit_union_id': {'type': ['string', 'null'], 'description': 'Stable composite credit-union identifier from REST; use it to join this offer to eligibility check, search, and profile results.'}, 'monthly_payment': {'type': ['string', 'null'], 'description': 'Estimated principal-and-interest payment as a formatted dollar string; excludes taxes, insurance, PMI, and HOA.'}, 'institution_context': {'type': 'object', 'description': 'NCUA call-report facts about the institution (asset size, member count, branch count, year opened, online services) for sizing up the lender.'}, 'eligibility_explanation': {'type': 'object', 'properties': {'reason': {'type': ['string', 'null'], 'description': 'Deterministic explanation safe to quote; an unattested negative is replaced with a neutral open-world explanation.'}, 'source': {'type': ['string', 'null'], 'description': 'Authority used for the decision-time eligibility result: graph, annotation, authority_unavailable, or absent.'}, 'status': {'type': ['string', 'null'], 'description': 'Decision-time eligibility outcome. The reserved `ineligible` value is normalized to `unknown` unless a future typed closed-world attestation is validated.'}, 'conditions': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Proven steps still required by the exact matched graph path. Present only when source is graph and status is conditionally_eligible.'}, 'publication': {'type': 'object', 'properties': {'activated_at': {'type': ['string', 'null'], 'description': 'UTC timestamp when the exact publication became serving authority.'}, 'publication_id': {'type': ['number', 'null'], 'description': 'Database identifier of the exact active eligibility publication evaluated for this offer.'}, 'ruleset_sha256': {'type': ['string', 'null'], 'pattern': '^[0-9a-f]{64}$', 'description': 'SHA-256 digest of the complete ordered rule set in that active publication.'}}, 'description': 'Exact immutable generation lineage, present only when REST evaluated an active graph publication.', 'additionalProperties': True}, 'legacy_status': {'type': ['string', 'null'], 'description': 'Compatibility status from the legacy evaluator. `geo_mismatch` is reserved and normalized to `unknown` by MCP.'}, 'unknown_reason': {'type': ['string', 'null'], 'description': 'Machine-readable reason for an unknown decision, including `fom_completeness_unaffirmed`.'}, 'access_cost_usd': {'type': ['number', 'null'], 'description': 'Known up-front cost of the exact matched graph path. Present only when source is graph and status is conditionally_eligible.'}}, 'description': 'Decision-time eligibility explanation with open-world negative sanitization; exact REST publication lineage is preserved and never synthesized.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'Best live published offers for this scenario, already sorted best-first.'}, 'recommendation': {'type': 'object', 'properties': {'action': {'type': ['string', 'null'], 'description': "Recommended next move, e.g. 'shop_providers' (better rates exist elsewhere) or 'accept'."}, 'confidence': {'type': ['string', 'null'], 'description': "Confidence in the recommendation as a percentage string, e.g. '94%'."}}, 'description': 'The recommended course of action and how strongly it is held.', 'additionalProperties': True}, 'resolved_county': {'type': 'object', 'properties': {'fips': {'type': ['string', 'null'], 'description': "Five-digit Census county FIPS code, zero-padded (e.g. '06075')."}, 'county': {'type': ['string', 'null'], 'description': "County name the ZIP falls in, e.g. 'San Francisco'."}, 'source': {'type': ['string', 'null'], 'description': "How the county was determined: 'zip' means it was derived from the supplied ZIP code."}}, 'description': 'County the supplied ZIP was resolved to, used for eligibility and local branch matching.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'product'], 'properties': {'limit': {'type': 'number', 'description': 'Top N lenders to return (default 10, clamped 1..50)'}, 'state': {'type': 'string', 'description': '2-letter US state code, e.g. CA, TX, NY'}, 'metric': {'enum': ['apr', 'rate'], 'type': 'string', 'description': 'Rank by apr (default) or rate'}, 'product': {'enum': ['30yr_fixed', '15yr_fixed'], 'type': 'string', 'description': 'Mortgage product'}, 'include_institution_context': {'type': 'boolean', 'description': 'Include compact NCUA member, location, asset, founding-year, and selected service facts per lender.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Plain-English interpretation of the numbers above, already phrased for the user; quote it rather than re-deriving the comparison.'}, 'as_of': {'type': ['string', 'null'], 'description': 'UTC timestamp of the underlying rate data. This is when the rates were last scraped from lender sites, not when this call ran.'}, 'count': {'type': ['number', 'null'], 'description': 'Rows actually returned in `table`.'}, 'limit': {'type': ['number', 'null'], 'description': 'Maximum rows the caller asked for.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'table': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': "Annual percentage rate in percent, including lender fees. NULL when the lender published no APR — the API deliberately does not substitute the note rate, so never present `rate` as an APR. Some legacy rows still carry an APR equal to the note rate; those heal on that credit union's next scrape."}, 'best': {'type': ['boolean', 'null'], 'description': 'True on the single top-ranked row.'}, 'rate': {'type': ['number', 'null'], 'description': 'Note rate in percent, excluding fees. It can be lower than the APR on the same row.'}, 'as_of': {'type': ['string', 'null'], 'description': "UTC timestamp when this lender's rate was last scraped."}, 'lender': {'type': ['string', 'null'], 'description': 'Full name of the credit union.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for this rate, where 1 point = 1% of the loan amount.'}, 'product': {'type': ['string', 'null'], 'description': 'Product key this row was matched on, matching the top-level `product`.'}, 'position': {'type': ['number', 'null'], 'description': 'Rank in the table, 1 = best on the chosen metric.'}, 'eligibility': {'type': 'object', 'description': 'Membership-eligibility snapshot for this lender, including status, charter type, and confidence. A great rate is unusable if the user cannot join.'}, 'rateapi_url': {'type': ['string', 'null'], 'description': 'Public rateapi.dev profile page for this lender.'}, 'display_name': {'type': ['string', 'null'], 'description': 'Normalized, human-readable product name for comparison across lenders.'}, 'product_name': {'type': ['string', 'null'], 'description': "The lender's own wording for the product, e.g. 'VA 30 Year Fixed' — note it may be a program-restricted product."}, 'bps_above_leader': {'type': ['number', 'null'], 'description': "How far this row's metric sits above the leader, in basis points (3 = 0.03 percentage points). 0 marks the leader."}, 'institution_context': {'type': 'object', 'description': 'NCUA call-report facts about the institution such as asset size, member count, branches, and year opened.'}}, 'additionalProperties': True}, 'description': 'Lenders ranked best-first by the chosen metric.'}, 'market': {'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of offers behind the market statistics. It can exceed total_lenders when a lender publishes several matching products.'}, 'max_apr': {'type': ['number', 'null'], 'description': 'Highest APR in percent in the whole market.'}, 'min_apr': {'type': ['number', 'null'], 'description': 'Lowest APR in percent in the whole market for this product.'}, 'median_apr': {'type': ['number', 'null'], 'description': "Median APR in percent across the whole market; use this, not min_apr, as 'the going rate'."}}, 'description': 'Distribution across all lenders publishing this product, including those below the table cutoff.', 'additionalProperties': True}, 'metric': {'type': ['string', 'null'], 'description': "Value the ranking is sorted by — 'apr' ranks by true cost including fees, 'rate' by the note rate alone."}, 'product': {'type': ['string', 'null'], 'description': "Product key the table ranks, e.g. '30yr_fixed'."}, 'total_lenders': {'type': ['number', 'null'], 'description': 'Number of lenders publishing this product in this state. `count` is the visible top slice of this larger set.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['monitor_id'], 'properties': {'monitor_id': {'type': 'string', 'description': 'The unique identifier of the monitor. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'error': {'type': ['string', 'null'], 'description': "Present and set to 'not_found' when the monitor id does not exist."}, 'monitor': {'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Monitor id.'}, 'name': {'type': 'string', 'description': 'Monitor label.'}, 'status': {'type': 'string', 'description': "'active' or 'paused'."}, 'conditions': {'type': ['array', 'null'], 'description': 'Full trigger conditions.'}, 'created_at': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'updated_at': {'type': ['string', 'null'], 'description': 'ISO-8601 last-modified timestamp.'}, 'webhook_url': {'type': ['string', 'null'], 'description': 'Delivery URL.'}, 'cooldown_hours': {'type': ['number', 'null'], 'description': 'Minimum hours between triggers.'}, 'decision_context': {'type': ['object', 'null'], 'description': 'Stored loan context used when evaluating triggers.', 'additionalProperties': True}, 'last_triggered_at': {'type': ['string', 'null'], 'description': 'ISO-8601 last trigger, null if never.'}, 'subscribed_states': {'type': ['array', 'null'], 'description': 'Watched state codes.'}, 'subscribed_product_types': {'type': ['array', 'null'], 'description': 'Watched product types.'}}, 'description': 'The monitor. Absent when not found.', 'additionalProperties': True}, 'summary': {'type': 'string', 'description': 'Monitor name and status, or a not-found message.'}}, 'description': 'One monitor in full. On a missing id the tool returns a not-found shape instead of throwing.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'reset_date': {'type': ['string', 'null'], 'description': 'When the monthly counter resets.'}, 'total_monitors': {'type': 'number', 'description': 'Monitors on the account.'}, 'active_monitors': {'type': 'number', 'description': "Monitors in 'active' status."}, 'webhooks_sent_today': {'type': 'number', 'description': 'Webhooks sent today.'}, 'webhooks_sent_this_month': {'type': 'number', 'description': 'Webhooks sent this month.'}}, 'description': "Rollup counts for the organization's monitors.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['person', 'products'], 'properties': {'person': {'type': 'object', 'properties': {'school': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied school name; school_relationship is needed for a typed positive path.'}, 'worship': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied place of worship.'}, 'employer': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Person-supplied employer name; use employer_org_ids after authoritative resolution.'}, 'home_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Home ZIP; never inferred from another role.'}, 'work_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Worksite ZIP, separate from home and payroll.'}, 'home_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized home city.'}, 'work_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized worksite city.'}, 'home_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC home state.'}, 'occupation': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Person-supplied occupation.'}, 'work_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC worksite state.'}, 'home_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Home county.'}, 'payroll_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'Payroll-origin ZIP, separate from the worksite.'}, 'work_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Worksite county.'}, 'associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations the person already belongs to.'}, 'facility_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the applicant organization maintains a facility.'}, 'payroll_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized payroll-origin city.'}, 'property_zip': {'type': 'string', 'pattern': '^\\d{5}(?:-\\d{4})?$', 'description': 'ZIP where the person owns real property; never inferred from home.'}, 'facility_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized facility city.'}, 'payroll_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC payroll-origin state.'}, 'property_city': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Census-recognized city where the person owns real property.'}, 'applicant_kind': {'enum': ['person', 'trust', 'organization', 'partnership', 'corporation', 'other_legal_entity'], 'type': 'string', 'description': 'What the applicant is; absence means a natural person.'}, 'facility_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC facility state.'}, 'payroll_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'Payroll-origin county.'}, 'property_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'Valid 50-state/DC property state.'}, 'school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit school ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'facility_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the applicant organization maintains a facility.'}, 'family_relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relationship to the relative whose affiliations are supplied.'}, 'military_status': {'enum': ['active_duty', 'veteran', 'reservist', 'dod_civilian', 'military_family'], 'type': 'string', 'description': 'Person-supplied military affiliation.'}, 'property_county': {'type': 'string', 'maxLength': 200, 'minLength': 1, 'description': 'County where the person owns real property.'}, 'worship_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit worship-organization ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit employer ids returned by resolve_eligibility_entities; rates-api revalidates type and active-publication authority.', 'uniqueItems': True}, 'relative_schools': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Schools of the named relative, not the applicant.'}, 'relative_employers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Employers of the named relative, not the applicant.'}, 'association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Explicit association ids returned by resolve_eligibility_entities; rates-api revalidates them.', 'uniqueItems': True}, 'school_relationship': {'enum': ['student', 'alumni', 'employee'], 'type': 'string', 'description': 'How the person relates to the supplied school.'}, 'relative_memberships': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'relation', 'status'], 'properties': {'status': {'enum': ['current_member', 'deceased_member'], 'type': 'string', 'description': 'Confirmed membership status.'}, 'relation': {'type': 'string', 'maxLength': 60, 'minLength': 1, 'description': 'Relative relationship.'}, 'credit_union_id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'description': 'Confirmed relative memberships, each scoped to one exact institution.'}, 'relative_associations': {'type': 'array', 'items': {'type': 'string', 'maxLength': 500, 'minLength': 1}, 'maxItems': 20, 'description': 'Associations of the named relative, not the applicant.'}, 'military_service_state': {'type': 'string', 'pattern': '^(?:[Aa][Ll]|[Aa][Kk]|[Aa][Zz]|[Aa][Rr]|[Cc][Aa]|[Cc][Oo]|[Cc][Tt]|[Dd][Ee]|[Dd][Cc]|[Ff][Ll]|[Gg][Aa]|[Hh][Ii]|[Ii][Dd]|[Ii][Ll]|[Ii][Nn]|[Ii][Aa]|[Kk][Ss]|[Kk][Yy]|[Ll][Aa]|[Mm][Ee]|[Mm][Dd]|[Mm][Aa]|[Mm][Ii]|[Mm][Nn]|[Mm][Ss]|[Mm][Oo]|[Mm][Tt]|[Nn][Ee]|[Nn][Vv]|[Nn][Hh]|[Nn][Jj]|[Nn][Mm]|[Nn][Yy]|[Nn][Cc]|[Nn][Dd]|[Oo][Hh]|[Oo][Kk]|[Oo][Rr]|[Pp][Aa]|[Rr][Ii]|[Ss][Cc]|[Ss][Dd]|[Tt][Nn]|[Tt][Xx]|[Uu][Tt]|[Vv][Tt]|[Vv][Aa]|[Ww][Aa]|[Ww][Vv]|[Ww][Ii]|[Ww][Yy])$', 'description': 'State tied to a state-scoped military affiliation.'}, 'asserted_org_qualifiers': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200, 'minLength': 1}, 'maxItems': 20, 'description': 'Narrow conditions the person explicitly asserted; never infer them.'}, 'relative_school_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical school ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'relative_employer_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical employer ids belonging to the named relative, not the applicant.', 'uniqueItems': True}, 'willing_to_join_association': {'type': 'boolean', 'description': 'Whether documented joinable-association actions may be considered.'}, 'relative_association_org_ids': {'type': 'array', 'items': {'type': 'string', 'pattern': '^[a-z0-9]+(?:-[a-z0-9]+)*$', 'maxLength': 80, 'minLength': 1}, 'maxItems': 20, 'description': 'Canonical association ids belonging to the named relative, not the applicant.', 'uniqueItems': True}}, 'description': 'Explicit caller-supplied person facts. Unknown facts stay absent; do not infer them.', 'additionalProperties': False}, 'products': {'type': 'array', 'items': {'type': 'object', 'required': ['product_type'], 'properties': {'amount': {'type': 'number', 'description': 'Loan or credit amount in USD.', 'exclusiveMinimum': 0}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'Transaction intent when relevant.'}, 'balance': {'type': 'number', 'minimum': 0, 'description': 'Deposit balance in USD.'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': 'Product audience.'}, 'occupancy': {'enum': ['primary', 'secondary', 'investment'], 'type': 'string', 'description': 'Property occupancy.'}, 'term_months': {'type': 'integer', 'maximum': 600, 'minimum': 1, 'description': 'Requested term in months.'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan', 'credit_card', 'savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'Exact product family.'}, 'vehicle_condition': {'enum': ['new', 'used', 'certified_pre_owned', 'any'], 'type': 'string', 'description': 'Vehicle condition.'}}, 'description': 'Exact product request used for both eligibility-backed rate evaluation and ranking.', 'additionalProperties': False}, 'maxItems': 19, 'minItems': 1, 'description': 'One to nineteen unique explicit product selectors. Do not invent missing scenario facts.', 'uniqueItems': True}, 'total_limit': {'type': 'integer', 'maximum': 100, 'minimum': 1, 'description': 'Maximum detail rows across all selectors; must be at least the selector count. Default 50.'}, 'limit_per_product': {'type': 'integer', 'maximum': 10, 'minimum': 1, 'description': 'Maximum detail rows for each selector, subject to the total and plan caps. Default 5.'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'products': {'type': 'array', 'items': {'type': 'object', 'properties': {'counts': {'type': 'object', 'description': 'Exact pre-cap counts for each reachability bucket.', 'additionalProperties': True}, 'ranking': {'type': 'object', 'description': 'Explicit declaration that underwriting and approval were not evaluated.', 'additionalProperties': True}, 'request': {'type': 'object', 'description': 'Exact explicit product selector evaluated.', 'additionalProperties': True}, 'questions': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Product-aware questions that may clarify reachability.'}, 'unresolved': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Rows whose membership proof or product suitability remains unresolved; never denials.'}, 'completeness': {'type': 'object', 'description': 'Exact-count, cap, returned-detail, and truncation metadata for this selector.', 'additionalProperties': True}, 'ranking_basis': {'type': ['string', 'null'], 'description': 'Published-price ordering used for this product.'}, 'reachable_now': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Rows with proven current membership access, satisfied published constraints, and evidenced pricing.'}, 'no_published_price': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Graph-positive institutions with no matching fresh evidenced price; never an unavailability claim.'}, 'reachable_after_action': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Rows requiring a source-proven membership action before access.'}}, 'additionalProperties': True}, 'description': 'One result per selector in request order.'}, 'snapshot': {'type': 'object', 'description': 'Eligibility generation, rules clock, returned-price observation range, and generation time.', 'additionalProperties': True}, 'questions': {'type': 'object', 'description': 'Membership questions shared across selectors.', 'additionalProperties': True}, 'semantics': {'type': ['string', 'null'], 'description': 'Positive-evidence-only interpretation contract; unknown never means ineligible.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required separation of membership, suitability, published pricing, underwriting, and approval.'}, 'completeness': {'type': 'object', 'description': 'Fleet, selector, evaluation-strategy, cap, and truncation disclosure.', 'additionalProperties': True}, 'catalog_version': {'type': ['string', 'null'], 'description': 'Stable access-catalog response contract version.'}}, 'description': 'One-snapshot personal access catalog across explicit loan and deposit product selectors.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['products'], 'properties': {'products': {'type': 'array', 'items': {'type': 'object', 'required': ['credit_union_id', 'product_type', 'product_name'], 'properties': {'balance': {'type': 'number', 'minimum': 0, 'description': 'Optional balance used only to report fit with published bounds.'}, 'audience': {'enum': ['consumer', 'business'], 'type': 'string', 'description': 'Optional requested audience.'}, 'term_months': {'type': 'integer', 'maximum': 600, 'minimum': 1, 'description': 'Exact term when applicable.'}, 'product_name': {'type': 'string', 'maxLength': 500, 'minLength': 1, 'description': 'Verbatim stable product name.'}, 'product_type': {'enum': ['savings', 'cd', 'share_certificate', 'money_market', 'ira_cd', 'ira', 'share_savings'], 'type': 'string', 'description': 'Exact deposit product family.'}, 'credit_union_id': {'type': 'string', 'maxLength': 240, 'minLength': 1, 'description': 'Exact credit-union id.'}}, 'additionalProperties': False}, 'maxItems': 50, 'minItems': 1, 'description': 'Exact deposit product references; no fuzzy product matching is performed.'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'counts': {'type': 'object', 'description': 'Requested product and distinct institution counts.', 'additionalProperties': True}, 'envelopes': {'type': 'array', 'items': {'type': 'object', 'properties': {'input_index': {'type': ['number', 'null'], 'description': 'Zero-based position of the exact requested product.'}, 'product_ref': {'type': 'object', 'description': 'Exact product reference supplied by the caller.', 'additionalProperties': True}, 'product_rate': {'type': 'object', 'description': 'Current exact evidenced product row and explicit suitability facts, or an unavailable reason.', 'additionalProperties': True}, 'membership_access': {'type': 'object', 'description': 'Active-publication path kinds and documented actions; never a personal verdict.', 'additionalProperties': True}, 'stable_product_identity': {'type': ['string', 'null'], 'description': 'Stable composite identity for this exact product reference.'}}, 'additionalProperties': True}, 'description': 'One access envelope per input in stable order.'}, 'semantics': {'type': ['string', 'null'], 'description': 'Non-personal, positive-documented-paths-only contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required warning against interpreting access metadata as personal eligibility or approval.'}}, 'description': 'Non-personal published membership and product-rate access metadata for exact deposit products.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product_type', 'state'], 'properties': {'since': {'enum': ['1w', '2w', '4w'], 'type': 'string', 'description': 'How far back to compare against. Defaults to "1w".'}, 'state': {'type': 'string', 'description': 'US state code (2-letter, e.g., CA, TX). Required.'}, 'product_type': {'enum': ['auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'mortgage', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'now': {'type': 'object', 'properties': {'max': {'type': ['number', 'null'], 'description': 'Highest APR in percent currently published.'}, 'min': {'type': ['number', 'null'], 'description': 'Lowest APR in percent currently published — a single best deal, not a typical rate.'}, 'as_of': {'type': ['string', 'null'], 'description': 'Timestamp of the most recent rate in the current snapshot.'}, 'count': {'type': ['number', 'null'], 'description': 'Number of live offers behind the current snapshot.'}, 'median': {'type': ['number', 'null'], 'description': "Median APR in percent currently published; the right number for 'what rates are today'."}}, 'description': 'Current market snapshot for this product and state.', 'additionalProperties': True}, 'note': {'type': ['string', 'null'], 'description': 'Plain-English interpretation of the numbers above, already phrased for the user; quote it rather than re-deriving the comparison.'}, 'then': {'type': 'object', 'properties': {'max': {'type': ['number', 'null'], 'description': 'Highest APR in percent at the start of the window.'}, 'min': {'type': ['number', 'null'], 'description': 'Lowest APR in percent at the start of the window.'}, 'as_of': {'type': ['string', 'null'], 'description': 'Timestamp of the earlier snapshot.'}, 'count': {'type': ['number', 'null'], 'description': 'Number of offers behind the earlier snapshot. This is often far smaller than now.count because history is retention-bounded, so treat the comparison as indicative.'}, 'median': {'type': ['number', 'null'], 'description': 'Median APR in percent at the start of the window.'}}, 'description': 'Snapshot at the start of the window, for comparison against `now`.', 'additionalProperties': True}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'change': {'type': 'object', 'properties': {'direction': {'type': ['string', 'null'], 'description': "Direction of the median move: 'up', 'down', or 'flat'."}, 'min_delta': {'type': ['number', 'null'], 'description': 'Change in the lowest published APR, in percentage points. This can move very differently from the median.'}, 'median_delta_pct': {'type': ['number', 'null'], 'description': 'Change in median APR, in percentage points (0.023 = about 2 basis points). Negative means rates fell.'}}, 'description': 'Movement from `then` to `now`.', 'additionalProperties': True}, 'window': {'type': ['string', 'null'], 'description': "Lookback period used for the comparison, expressed as a short duration string such as '4w', '90d', or '180d'."}, 'data_source': {'type': ['string', 'null'], 'description': "Internal backing store that served this query ('clickhouse'); operational detail, not something to report to the user."}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product_type', 'state'], 'properties': {'state': {'type': 'string', 'description': 'US state code (2-letter, e.g., CA, TX). Required.'}, 'window': {'enum': ['30d', '60d', '90d', '180d', '365d'], 'type': 'string', 'description': 'Lookback window. Default "90d". Bounded by data retention.'}, 'interval': {'enum': ['day', 'week'], 'type': 'string', 'description': 'Bucket granularity per point. Default "week".'}, 'product_type': {'enum': ['auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'mortgage', 'heloc', 'personal_loan', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product. Required.'}, 'vehicle_condition': {'enum': ['new', 'used', 'cpo'], 'type': 'string', 'description': 'auto_loan only; selects the benchmark bucket. Default "new".'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Coverage caveat for this series, notably how many buckets are empty because history is retention-bounded. Do not describe empty buckets as rates falling to zero.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'series': {'type': 'array', 'items': {'type': 'object', 'properties': {'max': {'description': 'Highest APR in percent observed in this bucket. Null when the bucket has no observations.'}, 'min': {'description': 'Lowest APR in percent observed in this bucket. Null when no rates were captured in the bucket — a data gap, not a rate of zero.'}, 'date': {'type': ['string', 'null'], 'description': "Start date of this bucket (ISO date). For weekly intervals this is the week's first day."}, 'count': {'type': ['number', 'null'], 'description': 'Number of rate observations in this bucket. 0 means the bucket is empty and its statistics are null.'}, 'median': {'description': 'Median APR in percent for this bucket, the value to plot as the trend line. Null when the bucket has no observations.'}}, 'additionalProperties': True}, 'description': 'One bucket per interval across the window, oldest first. Buckets with no scrapes are present with null statistics.'}, 'window': {'type': ['string', 'null'], 'description': "Lookback period used for the comparison, expressed as a short duration string such as '4w', '90d', or '180d'."}, 'summary': {'type': 'object', 'properties': {'last': {'type': 'object', 'description': 'Most recent populated bucket, with its date and median APR in percent.'}, 'as_of': {'type': ['string', 'null'], 'description': 'Timestamp of the most recent underlying rate observation.'}, 'first': {'type': 'object', 'description': 'Earliest populated bucket, with its date and median APR in percent.'}, 'points': {'type': ['number', 'null'], 'description': 'Number of populated buckets the summary is based on; a handful of points is a weak trend.'}, 'direction': {'type': ['string', 'null'], 'description': "Direction of the move across the window: 'up', 'down', or 'flat'."}, 'median_delta_pct': {'type': ['number', 'null'], 'description': 'Change in median APR from first to last populated bucket, in percentage points (0.215 = 21.5 basis points). Negative means rates fell.'}}, 'description': 'Start-to-end comparison across the populated portion of the series.', 'additionalProperties': True}, 'interval': {'type': ['string', 'null'], 'description': "Bucket size the series is aggregated into, e.g. 'week', 'day', or 'month'. Each entry in `series` covers one of these."}, 'data_source': {'type': ['string', 'null'], 'description': "Internal backing store that served this query ('clickhouse'); operational detail, not something to report to the user."}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Scenario id'}}}
Ausgabeschema
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Scenario id.'}, 'error': {'type': ['string', 'null'], 'description': 'Present when the scenario was not found.'}, 'input': {'type': ['object', 'null'], 'description': 'The decision inputs that produced the snapshot.', 'additionalProperties': True}, 'createdAt': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'clientName': {'type': 'string', 'description': 'Client label.'}, 'resultSnapshot': {'description': 'The decision result captured at save time; ranked offers live at actions[0].offers[].'}}, 'description': 'One saved client scenario.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'limit': {'type': ['number', 'null'], 'description': "Monthly request allowance for the org's tier."}, 'remaining': {'type': ['number', 'null'], 'description': 'Requests left this month. Null on an unlimited plan.'}, 'reset_date': {'type': ['string', 'null'], 'description': 'When the monthly counter resets.'}, 'requests_today': {'type': 'number', 'description': 'Requests since midnight.'}, 'total_requests': {'type': 'number', 'description': "All-time request count across the org's keys."}, 'requests_this_month': {'type': 'number', 'description': 'Requests since the start of the current month — the number metered against the limit.'}}, 'description': 'API request usage and plan limit for the organization behind the API key.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of items in the array above. There is no pagination on this route — this is the complete set for the org, not a page.'}, 'cohorts': {'type': 'array', 'items': {'type': 'object', 'description': 'A saved cohort: a named set of borrower records the org can re-scan for savings.', 'additionalProperties': True}, 'description': 'The cohorts visible to the API key making the call. Empty when the org has none; the MCP layer wraps the upstream array so the result is always an object.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'zip': {'type': 'string', 'pattern': '^[0-9]{5}$', 'description': 'Optional: Find the closest credit unions by NCUA-reported branch location. Distances are ZIP-centroid straight-line estimates. When supplied, ZIP discovery takes precedence over state listing.'}, 'state': {'type': 'string', 'description': 'Optional: Filter to a specific state (2-letter code). If not provided, returns all states.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'Lower-cased two-letter state code the listing is scoped to.'}, 'summary': {'type': ['string', 'null'], 'description': 'One-sentence plain-English summary of this result, safe to quote directly to the user.'}, 'state_name': {'type': ['string', 'null'], 'description': "Full state name, e.g. 'California'."}, 'with_rates': {'type': ['number', 'null'], 'description': 'How many of those credit unions currently have published rate data — always smaller than total_credit_unions.'}, 'credit_unions': {'type': 'array', 'items': {'type': 'object', 'properties': {'url': {'type': ['string', 'null'], 'description': "The credit union's own website."}, 'city': {'type': ['string', 'null'], 'description': 'Headquarters city, lower-cased as stored.'}, 'name': {'type': ['string', 'null'], 'description': "Credit union name as displayed, usually without the words 'Credit Union'."}, 'slug': {'type': ['string', 'null'], 'description': 'URL-safe identifier used in rateapi.dev links and as the `slug` argument to get_credit_union.'}, 'members': {'type': ['number', 'null'], 'description': 'Member count from the NCUA quarterly call report. Null when no NCUA profile is linked.'}, 'has_rates': {'type': ['boolean', 'null'], 'description': 'True when this credit union has published rates on file; false means it is known but nothing is currently quotable.'}, 'last_verified': {'type': ['string', 'null'], 'description': 'UTC timestamp when rates were last successfully scraped. Null means never successfully scraped.'}, 'product_count': {'type': ['number', 'null'], 'description': 'Number of distinct rate products currently on file. 0 when has_rates is false.'}, 'location_count': {'type': ['number', 'null'], 'description': 'Number of NCUA-reported branch locations. 0 can mean genuinely branchless or simply not reported.'}}, 'additionalProperties': True}, 'description': 'The credit unions in this state, alphabetical by name.'}, 'total_credit_unions': {'type': ['number', 'null'], 'description': 'Number of credit unions known in this state, including those with no published rates.'}, 'verified_last_7_days': {'type': ['number', 'null'], 'description': 'How many have had their rates re-scraped and confirmed in the past 7 days; the rest may be staler.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'limit': {'type': 'number', 'description': 'Max rows (default 20, max 100)'}, 'offset': {'type': 'number', 'description': 'Pagination offset'}, 'request_id': {'type': 'string', 'description': 'Optional: look up a specific decision by its request_id'}}}
Ausgabeschema
{'type': 'object', 'properties': {'logs': {'type': 'array', 'items': {'type': 'object', 'properties': {'id': {'type': 'number', 'description': 'Audit row id.'}, 'timestamp': {'type': 'string', 'description': 'When the decision was made.'}, 'api_key_id': {'type': 'string', 'description': 'Key that made the call.'}, 'request_id': {'type': 'string', 'description': 'Caller-supplied request id — the handle for recalling one decision.'}, 'status_code': {'type': 'number', 'description': 'HTTP status the decision call returned.'}}, 'additionalProperties': True}, 'description': 'Audit rows, newest first.'}, 'total': {'type': 'number', 'description': 'Total matching rows across all pages.'}, 'has_more': {'type': 'boolean', 'description': 'True when further pages exist.'}}, 'description': "Audit rows for past /v1/decisions calls made by this organization's keys.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of items in the array above. There is no pagination on this route — this is the complete set for the org, not a page.'}, 'digests': {'type': 'array', 'items': {'type': 'object', 'description': 'A scheduled email digest for a cohort, with its cadence and last run time.', 'additionalProperties': True}, 'description': 'The digests visible to the API key making the call. Empty when the org has none; the MCP layer wraps the upstream array so the result is always an object.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of items in the array above. There is no pagination on this route — this is the complete set for the org, not a page.'}, 'campaigns': {'type': 'array', 'items': {'type': 'object', 'description': 'A branded email campaign, with its products, recipients and send state.', 'additionalProperties': True}, 'description': 'The campaigns visible to the API key making the call. Empty when the org has none; the MCP layer wraps the upstream array so the result is always an object.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'limit': {'type': 'number', 'description': 'Maximum number of monitors to return (1-100). Defaults to 20.'}, 'offset': {'type': 'number', 'description': 'Number of monitors to skip for pagination. Defaults to 0.'}, 'status': {'enum': ['active', 'paused', 'disabled'], 'type': 'string', 'description': 'Filter monitors by status.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'summary': {'type': 'string', 'description': 'Human-readable count of total, active, and paused monitors.'}, 'monitors': {'type': 'array', 'items': {'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Monitor id.'}, 'name': {'type': 'string', 'description': 'Monitor label.'}, 'status': {'type': 'string', 'description': "'active' or 'paused'."}, 'created_at': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'webhook_url': {'type': ['string', 'null'], 'description': 'Delivery URL.'}, 'cooldown_hours': {'type': ['number', 'null'], 'description': 'Minimum hours between triggers.'}, 'conditions_count': {'type': 'number', 'description': 'How many trigger conditions the monitor has.'}, 'last_triggered_at': {'type': ['string', 'null'], 'description': 'ISO-8601 timestamp of the last trigger, null if never.'}}, 'additionalProperties': True}, 'description': 'The monitors on this page (a condensed view — call get_monitor for full conditions).'}, 'pagination': {'type': 'object', 'properties': {'limit': {'type': 'number', 'description': 'Page size used.'}, 'total': {'type': 'number', 'description': 'Total monitors on the account.'}, 'offset': {'type': 'number', 'description': 'Zero-based offset of this page.'}, 'has_more': {'type': 'boolean', 'description': 'True when further pages exist.'}}, 'description': 'Page position.', 'additionalProperties': True}}, 'description': "A page of the account's rate monitors, with counts.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['email'], 'properties': {'email': {'type': 'string', 'description': 'The email whose alerts to list. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': 'number', 'description': 'Number of alerts returned.'}, 'alerts': {'type': 'array', 'items': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'Legacy scalar state — first entry of `states`.'}, 'intent': {'type': ['string', 'null'], 'description': "Borrower intent, e.g. 'purchase' or 'refinance'."}, 'states': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Full list of watched state codes.'}, 'status': {'type': 'string', 'description': "'pending', 'active', 'unsubscribed', or 'bounced'."}, 'target': {'type': 'object', 'properties': {'field': {'type': ['string', 'null'], 'description': 'Watched field.'}, 'value': {'type': ['number', 'null'], 'description': 'Threshold value.'}, 'operator': {'type': ['string', 'null'], 'description': 'Comparison operator.'}}, 'description': 'The threshold that fires the alert.', 'additionalProperties': True}, 'alert_id': {'type': 'string', 'description': 'Alert id.'}, 'created_at': {'type': ['string', 'number', 'null'], 'description': 'When the alert was created.'}, 'product_type': {'type': ['string', 'null'], 'description': 'Product the alert watches.'}, 'region_preset': {'type': ['string', 'null'], 'description': 'Region preset key, or null.'}, 'last_notified_at': {'type': ['string', 'number', 'null'], 'description': 'When the borrower was last emailed, null if never.'}}, 'additionalProperties': True}, 'description': "The borrower's alerts, newest first."}}, 'description': "A borrower's rate alerts, looked up by email. Unsubscribed alerts are excluded.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'sort': {'enum': ['apr_asc', 'apr_desc', 'rate_asc', 'rate_desc', 'updated_desc'], 'type': 'string', 'description': 'Default apr_asc'}, 'limit': {'type': 'number', 'description': '1-500, default 50'}, 'state': {'type': 'string', 'description': '2-letter US state code; omit for all states'}, 'lender': {'type': 'string', 'description': 'Filter by credit-union name (substring, case-insensitive)'}, 'offset': {'type': 'number', 'description': 'Pagination offset, default 0'}, 'max_apr': {'type': 'number'}, 'min_apr': {'type': 'number'}, 'audience': {'enum': ['business', 'consumer'], 'type': 'string', 'description': "WHO the product is for, orthogonal to product type: 'business' returns business-audience products across every category (DSCR mortgages, business deposits, SBA loans); 'consumer' excludes them."}, 'term_months': {'type': 'number'}, 'loan_program': {'type': 'string'}, 'product_type': {'enum': ['mortgage', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string'}}}
Ausgabeschema
{'type': 'object', 'properties': {'as_of': {'type': ['string', 'null'], 'description': 'UTC timestamp of the newest rate in this result set; the whole page is at least this stale.'}, 'rates': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': "Annual percentage rate in percent, including lender fees. NULL when the lender published no APR — the API deliberately does not substitute the note rate, so never present `rate` as an APR. Some legacy rows still carry an APR equal to the note rate; those heal on that credit union's next scrape."}, 'rate': {'type': ['number', 'null'], 'description': 'Note rate in percent (6.125 = 6.125%), excluding fees. On an ARM this is only the initial rate.'}, 'as_of': {'type': ['string', 'null'], 'description': 'UTC timestamp when this individual rate was last scraped from the lender.'}, 'state': {'type': ['string', 'null'], 'description': 'Two-letter state code of the lender.'}, 'lender': {'type': ['string', 'null'], 'description': 'Full name of the credit union publishing this rate.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for this rate, where 1 point = 1% of the loan amount.'}, 'rate_phase': {'type': ['string', 'null'], 'description': "Which phase of the rate this row describes: 'standard' for the ordinary rate, versus an introductory or teaser phase on ARMs and promotional products."}, 'eligibility': {'type': 'object', 'description': "Membership-eligibility snapshot for this lender, including status, charter type, and confidence; 'unknown' status means it could not be evaluated for this user."}, 'product_key': {'type': ['string', 'null'], 'description': 'Internal pipe-delimited product fingerprint used for deduplication; never show it to the user.'}, 'rateapi_url': {'type': ['string', 'null'], 'description': 'Public rateapi.dev profile page for this lender.'}, 'term_months': {'description': 'Term in months for this product. Null when the lender did not publish a term, common for ARMs and lines of credit.'}, 'display_name': {'type': ['string', 'null'], 'description': 'Normalized, human-readable product name for comparison across lenders.'}, 'loan_program': {'type': ['string', 'null'], 'description': "Underwriting program, e.g. 'conventional', 'va', 'fha', 'jumbo'."}, 'loan_purpose': {'type': ['string', 'null'], 'description': "Purpose the rate applies to, e.g. 'purchase' or 'refinance'. Null means the lender did not distinguish."}, 'product_name': {'type': ['string', 'null'], 'description': "The lender's own wording for the product, e.g. 'Home Purchases/Refinances 7 & 1 Year ARM'."}, 'product_type': {'type': ['string', 'null'], 'description': "Normalized product category, e.g. '30-year-fixed', 'arm', '10-year-fixed'."}, 'vehicle_type': {'description': 'For vehicle loans, the vehicle class (car, RV, boat, motorcycle). Null on non-vehicle products; null on an auto loan means a car.'}, 'vehicle_condition': {'description': 'For auto loans, whether the rate applies to a new or used vehicle. Null for non-auto products.'}}, 'additionalProperties': True}, 'description': 'The matching rate rows for this page, in the order given by filters.sort.'}, 'filters': {'type': 'object', 'properties': {'sort': {'type': ['string', 'null'], 'description': "Ordering applied to the rows, e.g. 'apr_asc' (cheapest APR first)."}, 'state': {'type': ['string', 'null'], 'description': 'Two-letter state filter applied. Null means nationwide.'}, 'lender': {'description': 'Lender name filter applied. Null means all lenders.'}, 'max_apr': {'description': 'Upper APR bound applied, in percent. Null means no ceiling.'}, 'min_apr': {'description': 'Lower APR bound applied, in percent. Null means no floor.'}, 'audience': {'description': 'Borrower-audience filter, e.g. first-time buyer programs. Null means unrestricted.'}, 'occupancy': {'description': 'Occupancy filter such as primary residence or investment property. Null means unrestricted.'}, 'term_months': {'description': 'Term filter in months. Null means all terms were included, so rows may mix 15- and 30-year products.'}, 'loan_program': {'description': "Loan program filter such as 'conventional' or 'va'. Null means all programs."}, 'product_type': {'type': ['string', 'null'], 'description': "Product category filter applied, e.g. 'mortgage'. Null means all categories."}}, 'description': 'The filters that were applied to produce these rows; null members were not constrained.', 'additionalProperties': True}, 'pagination': {'type': 'object', 'properties': {'limit': {'type': ['number', 'null'], 'description': 'Maximum rows requested for this page.'}, 'total': {'type': ['number', 'null'], 'description': 'Total rows matching the filters across all pages — usually far larger than `returned`. Use this when telling the user how many offers exist.'}, 'offset': {'type': ['number', 'null'], 'description': 'Number of rows skipped before this page.'}, 'has_more': {'type': ['boolean', 'null'], 'description': 'True when further pages of matching rows remain beyond this one.'}, 'returned': {'type': ['number', 'null'], 'description': 'Rows actually included in this response.'}}, 'description': 'Where this page sits within the full result set.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of items in the array above. There is no pagination on this route — this is the complete set for the org, not a page.'}, 'scenarios': {'type': 'array', 'items': {'type': 'object', 'description': 'A saved scenario: a stored decision input plus the result snapshot captured when it was saved.', 'additionalProperties': True}, 'description': 'The scenarios visible to the API key making the call. Empty when the org has none; the MCP layer wraps the upstream array so the result is always an object.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', 'properties': {'count': {'type': ['number', 'null'], 'description': 'Number of items in the array above. There is no pagination on this route — this is the complete set for the org, not a page.'}, 'shares': {'type': 'array', 'items': {'type': 'object', 'description': 'A share link issued for a scenario, with its view count and revocation state.', 'additionalProperties': True}, 'description': 'The shares visible to the API key making the call. Empty when the org has none; the MCP layer wraps the upstream array so the result is always an object.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'limit': {'type': 'integer', 'default': 50, 'maximum': 100, 'minimum': 1}, 'offset': {'type': 'integer', 'default': 0, 'minimum': 0}, 'status': {'enum': ['delivered', 'failed', 'pending'], 'type': 'string', 'description': 'Filter by delivery outcome.'}, 'monitor_id': {'type': 'string', 'description': 'Filter to one monitor.'}, 'redeliver_id': {'type': 'integer', 'description': 'If set, replay the delivery with this audit-log id instead of listing (maps to action:redeliver, delivery_id).'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'content': {'type': 'array', 'items': {'type': 'object', 'properties': {'text': {'type': 'string', 'description': 'The summary line.'}, 'type': {'type': 'string', 'description': "Content block type, always 'text' here."}}, 'additionalProperties': True}, 'description': 'MCP content blocks carrying a one-line human summary of the deliveries or the redelivery.'}, 'disclosures': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Scoping and replay-semantics caveats.'}, 'next_actions': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Suggested follow-up tool names.'}, 'structuredContent': {'type': 'object', 'properties': {'error': {'type': ['string', 'null'], 'description': 'Failure reason for the replay, null on success.'}, 'limit': {'type': 'number', 'description': 'Page size used. List mode only.'}, 'offset': {'type': 'number', 'description': 'Zero-based page offset. List mode only.'}, 'summary': {'type': 'object', 'properties': {'total': {'type': 'number', 'description': 'Matching deliveries.'}, 'failed': {'type': 'number', 'description': 'Failed deliveries.'}, 'pending': {'type': 'number', 'description': 'Not yet attempted or unresolved.'}, 'delivered': {'type': 'number', 'description': 'Successful deliveries.'}}, 'description': 'Counts across the same filter as the rows. List mode only.', 'additionalProperties': True}, 'deliveries': {'type': 'array', 'items': {'type': 'object', 'properties': {'id': {'type': 'number', 'description': 'Delivery row id — pass as redeliver_id to replay it.'}, 'status': {'type': 'string', 'description': "Derived status: 'delivered', 'failed', or 'pending'."}, 'event_id': {'type': 'string', 'description': 'Id of the triggering event.'}, 'timestamp': {'type': 'string', 'description': 'ISO-8601 time of the delivery attempt.'}, 'event_type': {'type': 'string', 'description': 'Event type carried in the payload.'}, 'monitor_id': {'type': 'string', 'description': 'Monitor that produced the delivery.'}, 'webhook_url': {'type': 'string', 'description': 'Destination URL.'}, 'trigger_type': {'type': 'string', 'description': 'What caused the fire (e.g. a rate change or a simulation).'}, 'is_simulation': {'type': 'boolean', 'description': 'True when the delivery came from a test/simulate call.'}, 'delivery_error': {'type': ['string', 'null'], 'description': 'Failure reason, null on success.'}, 'response_time_ms': {'type': ['number', 'null'], 'description': 'Endpoint response time in milliseconds.'}, 'delivery_status_code': {'type': ['number', 'null'], 'description': 'HTTP status from the endpoint, null when no response.'}}, 'additionalProperties': True}, 'description': 'Audit rows, newest last. List mode only.'}, 'new_status': {'type': 'string', 'description': 'Status of the replay attempt. Redelivery mode only.'}, 'delivery_id': {'type': 'number', 'description': 'The delivery row that was replayed. Redelivery mode only.'}, 'redelivered': {'type': 'boolean', 'description': 'True when a stored payload was replayed. Redelivery mode only.'}}, 'description': 'The raw /v1/webhook-deliveries payload. In list mode: deliveries, summary, limit, offset. In redelivery mode: redelivered, delivery_id, new_status, delivery_status_code, response_time_ms, error.', 'additionalProperties': True}}, 'description': 'Webhook delivery audit rows, or the outcome of a redelivery when redeliver_id was supplied. The handler wraps the API response in a self-orchestrating envelope, so the raw payload lives under structuredContent.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['income_annual', 'dti', 'term_months'], 'properties': {'dti': {'type': 'number', 'description': 'Target debt-to-income ratio as a decimal, e.g. 0.36'}, 'rate': {'type': 'number', 'description': 'Optional annual interest rate, e.g. 6.5. If omitted, best market rate is used.'}, 'state': {'type': 'string', 'description': 'US state code (used to look up a market rate when rate is omitted)'}, 'term_months': {'type': 'number', 'description': 'Loan term in months (e.g. 360)'}, 'product_type': {'type': 'string', 'description': 'Product for the market-rate lookup, default mortgage'}, 'income_annual': {'type': 'number', 'description': 'Gross annual income in dollars'}, 'existing_monthly_debt': {'type': 'number', 'description': 'Optional existing monthly debt payments to subtract'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Required caveat that this uses income and DTI only; lenders also weigh credit, down payment, and reserves.'}, 'rate_used': {'type': ['string', 'null'], 'description': 'Interest rate, in percent, used for every calculation in this result. Check rate_source to see whether it came from the caller or from live market data.'}, 'assumptions': {'type': 'object', 'properties': {'target_dti': {'type': ['number', 'null'], 'description': 'Debt-to-income ratio targeted, as a decimal (0.43 = 43%).'}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months used to convert the payment into a principal.'}, 'existing_monthly_debt': {'type': ['number', 'null'], 'description': 'Existing monthly debt payments in dollars deducted from the DTI budget.'}}, 'description': 'The inputs the calculation rests on; state them alongside the number.', 'additionalProperties': True}, 'rate_source': {'type': ['string', 'null'], 'description': "Where rate_used came from: 'provided' means the caller supplied it, 'market' means it was resolved from the best live published rate for this state and product."}, 'max_loan_amount': {'type': ['string', 'null'], 'description': 'Largest loan principal in dollars that payment supports at the rate and term used. This is a loan amount, not a home price.'}, 'max_monthly_payment': {'type': ['string', 'null'], 'description': 'Largest monthly payment in dollars the income supports at the target DTI, after subtracting existing debts.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['loan_amount', 'term_months', 'base_rate', 'options'], 'properties': {'state': {'type': 'string', 'description': 'Optional 2-letter state (validated only if supplied).'}, 'options': {'type': 'array', 'items': {'type': 'object', 'required': ['points', 'rate'], 'properties': {'rate': {'type': 'number', 'description': 'Resulting interest rate at that point spend, percent.'}, 'points': {'type': 'number', 'description': 'Discount points as % of loan (positive) or lender credit (negative); 1 = 1% of loan.'}}}, 'maxItems': 25, 'minItems': 1, 'description': 'Points/lender-credit tradeoff menu to evaluate.'}, 'base_rate': {'type': 'number', 'description': 'The no-points (par) interest rate, percent, e.g. 6.75.'}, 'hold_months': {'type': 'number', 'description': 'Expected time-in-loan horizon for lifetime savings; defaults to term_months.'}, 'loan_amount': {'type': 'number', 'description': 'Loan principal in dollars (>0).'}, 'term_months': {'type': 'number', 'default': 360, 'description': 'Loan term in months, e.g. 360.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'reason': {'type': ['string', 'null'], 'description': "Why no buydown option was recommended, present only in that case — e.g. 'No option produces positive net savings over the hold horizon; paying par (no points) is best.'"}, 'optimal': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-sentence justification of the winning option, safe to quote.'}, 'rate': {'type': ['string', 'null'], 'description': 'Rate as a percent string in the winning option.'}, 'points': {'type': ['number', 'null'], 'description': 'Points bought in the winning option.'}, 'point_cost': {'type': ['string', 'null'], 'description': 'Upfront cost in dollars of the winning option.'}, 'break_even_months': {'type': ['number', 'null'], 'description': "Months to recover the winning option's point cost."}, 'savings_over_hold': {'type': ['string', 'null'], 'description': 'Net dollars the winning option saves over the assumed holding period.'}}, 'description': 'The option that maximizes net savings over the assumed holding period.', 'additionalProperties': True}, 'options': {'type': 'array', 'items': {'type': 'object', 'properties': {'rate': {'type': ['string', 'null'], 'description': 'Note rate as a percent string after this buydown.'}, 'points': {'type': ['number', 'null'], 'description': 'Points bought, where 1 point = 1% of the loan amount. Negative values are lender credits that raise the rate in exchange for cash at closing.'}, 'point_cost': {'type': ['string', 'null'], 'description': 'Upfront cost in dollars for these points, as a formatted string.'}, 'monthly_payment': {'type': ['string', 'null'], 'description': "Monthly principal-and-interest payment in dollars at this option's rate."}, 'monthly_savings': {'type': ['string', 'null'], 'description': 'Dollars per month saved versus the base rate; $0 on the baseline option.'}, 'break_even_months': {'type': ['number', 'null'], 'description': 'Months for the monthly savings to repay the point cost. 0 on the baseline option, since nothing was spent.'}, 'lifetime_interest': {'type': ['string', 'null'], 'description': 'Total interest in dollars over the full term at this rate, ignoring the hold period.'}, 'savings_over_hold': {'type': ['string', 'null'], 'description': 'Net dollars saved over hold_months after paying for the points; this is the figure to compare across options.'}}, 'additionalProperties': True}, 'description': 'Each points/rate combination modeled, including negative points (lender credits) where supplied.'}, 'base_rate': {'type': ['string', 'null'], 'description': 'The no-points starting rate as a percent string, the baseline every option is measured against.'}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'hold_months': {'type': ['number', 'null'], 'description': "How long the borrower is assumed to keep the loan. Buying points only wins if this exceeds the option's break-even."}, 'loan_amount': {'type': ['string', 'null'], 'description': 'Loan amount in dollars as a formatted string; point costs are a percentage of this.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months (360 = 30 years, 180 = 15 years, 60 = 5 years).'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'recommendation': {'type': ['string', 'null'], 'description': "The action implied by the analysis, e.g. 'buy_points', 'no_points', or 'take_credit'."}, 'assumed_defaults': {'type': 'object', 'properties': {'hold_months': {'type': ['number', 'null'], 'description': 'Holding period in months assumed because the caller did not supply one.'}}, 'description': 'Inputs filled in because the caller did not supply them, notably the holding period that decides the winner.', 'additionalProperties': True}, 'base_monthly_payment': {'type': ['string', 'null'], 'description': 'Monthly principal-and-interest payment in dollars at the base rate.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': [], 'properties': {'rate': {'type': 'number', 'description': 'Annual rate %, e.g. 6.5. Omit -> best market rate for state.'}, 'state': {'type': 'string', 'description': '2-letter code for market-rate lookup. Default CA.'}, 'pmi_rate': {'type': 'number', 'description': 'Annual PMI as % of loan balance. Default 0.5.'}, 'home_price': {'type': 'number', 'description': 'Purchase/appraised price. Required unless loan_amount given.'}, 'loan_amount': {'type': 'number', 'description': 'Optional explicit loan; overrides home_price - down_payment.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months. Default 360.'}, 'credit_score': {'type': 'number', 'description': 'Optional, for market-rate lookup.'}, 'down_payment': {'type': 'number', 'description': 'Cash down, dollars. Default 0.'}, 'extra_monthly_payment': {'type': 'number', 'description': 'Optional extra principal/month to model faster cancel. Default 0.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'pmi_drop': {'type': 'object', 'properties': {'ltv_basis': {'type': ['string', 'null'], 'description': "What LTV is measured against: 'original_value' means the purchase price, so appreciation does not accelerate the drop unless the borrower pays for a new appraisal."}, 'auto_terminate_78': {'type': 'object', 'description': 'When the balance reaches 78% LTV and the servicer must drop PMI automatically. Later, and more expensive, than requesting at 80%.'}, 'request_cancel_80': {'type': 'object', 'description': 'When the balance reaches 80% LTV — the borrower must actively request cancellation at this point; it does not happen on its own.'}}, 'description': 'The two dates PMI can come off: the earlier one the borrower must request, the later one is automatic.', 'additionalProperties': True}, 'rate_used': {'type': ['string', 'null'], 'description': 'Interest rate, in percent, used for every calculation in this result. Check rate_source to see whether it came from the caller or from live market data.'}, 'home_price': {'type': ['string', 'null'], 'description': 'Purchase price in dollars, as a formatted string.'}, 'monthly_pi': {'type': ['string', 'null'], 'description': 'Monthly principal-and-interest payment in dollars, excluding PMI.'}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'loan_amount': {'type': ['string', 'null'], 'description': 'Amount borrowed in dollars.'}, 'pmi_applies': {'type': ['boolean', 'null'], 'description': 'True when PMI is required at origination; false means the rest of this projection is moot.'}, 'rate_source': {'type': ['string', 'null'], 'description': "Where rate_used came from: 'provided' means the caller supplied it, 'market' means it was resolved from the best live published rate for this state and product."}, 'down_payment': {'type': ['string', 'null'], 'description': 'Cash in dollars put down at closing.'}, 'extra_needed': {'type': 'array', 'items': {'type': 'object', 'properties': {'extra_monthly': {'type': ['string', 'null'], 'description': 'Extra principal in dollars per month required to hit that target — often far beyond what a borrower can sustain.'}, 'reach_80_in_months': {'type': ['number', 'null'], 'description': 'Target number of months to reach 80% LTV.'}}, 'additionalProperties': True}, 'description': 'How much extra principal per month would be required to hit 80% LTV by various target dates.'}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'starting_ltv': {'type': ['string', 'null'], 'description': 'Loan-to-value at origination as a percent string. PMI applies above 80%.'}, 'total_pmi_paid': {'type': ['string', 'null'], 'description': 'Total PMI in dollars paid before it drops off, on the scheduled payments alone.'}, 'assumed_defaults': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'State code assumed for market-rate lookups because the caller did not supply one.'}, 'pmi_rate': {'type': ['string', 'null'], 'description': 'PMI rate assumed, as a percent string. Note this field carries a formatting quirk: it renders the annual PMI rate as a whole-number percent, so read it as the annual PMI rate and prefer monthly_pmi_initial for the actual dollar cost.'}, 'ltv_basis': {'type': ['string', 'null'], 'description': "LTV basis assumed, e.g. 'original_value' (purchase price) rather than a current appraisal."}, 'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months assumed because the caller did not supply one.'}}, 'description': 'Inputs the caller did not supply that were filled in with defaults. State these explicitly to the user, since they drive the numbers.', 'additionalProperties': True}, 'with_extra_payment': {'type': 'object', 'properties': {'pmi_saved': {'type': ['string', 'null'], 'description': 'PMI dollars avoided by paying down faster.'}, 'months_saved': {'type': ['number', 'null'], 'description': 'Months earlier PMI drops off thanks to the extra payments.'}, 'extra_monthly': {'type': ['string', 'null'], 'description': 'Extra principal in dollars paid each month in this scenario.'}, 'new_drop_date': {'type': ['string', 'null'], 'description': 'Calendar year-month when PMI now drops off.'}, 'new_drop_month': {'type': ['number', 'null'], 'description': 'Payment number when PMI now drops off, counting from the first payment.'}}, 'description': "How the caller's extra monthly principal payment accelerates PMI removal.", 'additionalProperties': True}, 'monthly_pmi_initial': {'type': ['string', 'null'], 'description': 'Monthly PMI premium in dollars at the start, before the balance amortizes down.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['product_type', 'state', 'rate'], 'properties': {'apr': {'type': 'number', 'description': 'The quoted APR as a percentage. Optional — falls back to rate if omitted.'}, 'zip': {'type': 'string', 'pattern': '^[0-9]{5}$', 'description': 'Borrower ZIP code. Optional; sharpens membership eligibility and enables include_nearby_offers.'}, 'fees': {'type': 'number', 'description': 'Quoted fees in dollars. Optional, used only for the note.'}, 'rate': {'type': 'number', 'description': 'The quoted interest rate as a percentage (e.g., 4.25). Required.'}, 'state': {'type': 'string', 'description': 'US state code (2-letter, e.g., CA, TX). Required.'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars. Optional — also sharpens better-offer payment math.'}, 'max_offers': {'type': 'number', 'description': 'How many better offers to return (1-5, default 3). Only applies with include_better_offers.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months. For MORTGAGES this selects which market the quote is scored against: pass 180 for a 15-year and 360 for a 30-year. 15-year rates run structurally lower, so omitting it on a 15-year quote compares it to 30-year offers and makes an ordinary rate look market-leading. Defaults to 30-year. Also sharpens better-offer payment math for every product.'}, 'credit_score': {'type': 'number', 'description': "Borrower's credit score (300-850). Optional; improves better-offer matching."}, 'product_type': {'enum': ['auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'mortgage', 'mortgage_arm', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product the quote is for. Pick `mortgage_arm` — NOT `mortgage` — whenever the user names an adjustable-rate mortgage: "ARM", "adjustable", or a slash pair like "5/1", "5/5", "7/1", "10/1". ARM intro rates run structurally BELOW fixed rates, so scoring an ARM against the fixed market makes an ordinary quote look market-leading, which is the exact error this tool exists to prevent. All initial fixed periods share one ARM market. Use `mortgage` for fixed-rate mortgages and set term_months to pick 15- vs 30-year.'}, 'include_better_offers': {'type': 'boolean', 'description': 'Set TRUE for negotiation questions. Adds `better_offers`: named lenders currently beating the quote, each with the APR gap in basis points, estimated monthly savings, and `can_you_join` (yes / likely / unknown) so you only cite alternatives the borrower can realistically obtain. This is what turns a percentile into something the user can act on — prefer it whenever the user asks whether their rate is fair or what to do about it.'}, 'include_nearby_offers': {'type': 'boolean', 'description': 'Set true with zip to return product-matched rates from credit unions ranked by the closest NCUA-reported branch. Results include approximate straight-line miles, branch details, and the basis-point difference versus the quote.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': "Ready-to-quote sentence explaining the verdict in the borrower's terms."}, 'quote': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': 'Quoted APR in percent, including fees; this is the number scored against the market.'}, 'rate': {'type': ['number', 'null'], 'description': 'Quoted note rate in percent, excluding fees.'}}, 'description': 'The rate the borrower was quoted, echoed back as supplied.', 'additionalProperties': True}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'market': {'type': 'object', 'properties': {'max': {'type': ['number', 'null'], 'description': 'Highest APR, in percent, among the live offers in this segment.'}, 'min': {'type': ['number', 'null'], 'description': 'Lowest APR, in percent, among the live offers in this market segment — the single best published deal, not a typical one.'}, 'as_of': {'type': ['string', 'null'], 'description': 'UTC timestamp of the newest rate in the market comparison set.'}, 'count': {'type': ['number', 'null'], 'description': 'Number of live published offers the min/median/max were computed from. Small counts make the median unreliable.'}, 'median': {'type': ['number', 'null'], 'description': "Median APR, in percent, across the live offers in this segment; the fairest single number to describe 'the market'."}}, 'description': 'Live market distribution the quote was scored against.', 'additionalProperties': True}, 'share_url': {'type': ['string', 'null'], 'description': 'Link to this same check on rateapi.dev that the borrower can send to a lender or broker; it re-runs against live rates when opened, so it never goes stale.'}, 'percentile': {'type': ['number', 'null'], 'description': 'Where the quote sits in the live market distribution, 0-100, lower being cheaper. 100 means every tracked offer is cheaper than this quote.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}, 'better_offers': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': 'APR of this offer in percent, including fees where published.'}, 'rate': {'type': ['number', 'null'], 'description': 'Note rate of this offer in percent, excluding fees.'}, 'state': {'type': ['string', 'null'], 'description': 'Two-letter state code of the lender.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for this rate, where 1 point = 1% of the loan amount.'}, 'eligibility': {'type': 'object', 'description': 'Membership-eligibility snapshot for this lender, including status, charter type, and confidence.'}, 'rateapi_url': {'type': ['string', 'null'], 'description': 'Public rateapi.dev profile page for this credit union.'}, 'can_you_join': {'type': ['string', 'null'], 'description': "Whether the borrower appears able to join this credit union: 'unknown' means membership could not be evaluated, not that they are excluded."}, 'display_name': {'type': ['string', 'null'], 'description': "Normalized product name for comparison against the borrower's quote."}, 'last_updated': {'type': ['string', 'null'], 'description': 'UTC timestamp when this offer was last scraped from the lender.'}, 'product_name': {'type': ['string', 'null'], 'description': "The lender's own wording for the product."}, 'apr_delta_bps': {'type': ['number', 'null'], 'description': 'How much cheaper this offer is than the quote, in basis points (105 = 1.05 percentage points better).'}, 'credit_union_id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE' of the lender."}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Estimated principal-and-interest payment in dollars at this rate for the assumed amount and term.'}, 'credit_union_url': {'type': ['string', 'null'], 'description': "The credit union's own website."}, 'credit_union_name': {'type': ['string', 'null'], 'description': 'Credit union publishing this better offer.'}, 'estimated_total_savings': {'type': ['number', 'null'], 'description': 'Dollars saved over the full assumed term versus the quoted rate — a whole-term figure, not annual.'}, 'estimated_monthly_savings': {'type': ['number', 'null'], 'description': 'Dollars per month saved versus the quoted rate, at the assumed loan amount and term.'}}, 'additionalProperties': True}, 'description': 'Statewide published offers that beat the quote, best first. Empty means nothing tracked beats it.'}, 'nearby_offers': {'type': 'array', 'items': {'type': 'object', 'properties': {'apr': {'type': ['number', 'null'], 'description': 'APR in percent, including fees where published.'}, 'rate': {'type': ['number', 'null'], 'description': 'Note rate in percent, excluding fees.'}, 'branch': {'type': 'object', 'description': 'The nearest branch (name and street address) the distance was measured to.'}, 'points': {'type': ['number', 'null'], 'description': 'Discount points required for this rate, where 1 point = 1% of the loan amount.'}, 'proximity': {'type': ['string', 'null'], 'description': "How the lender qualified as nearby: 'same_zip' or 'distance'."}, 'comparison': {'type': ['string', 'null'], 'description': "Whether this nearby offer is 'lower', 'higher', or the same as the borrower's quote."}, 'rateapi_url': {'type': ['string', 'null'], 'description': 'Public rateapi.dev profile page for this credit union.'}, 'display_name': {'type': ['string', 'null'], 'description': 'Normalized product name for comparison across lenders.'}, 'last_updated': {'type': ['string', 'null'], 'description': 'UTC timestamp when this offer was last scraped.'}, 'product_name': {'type': ['string', 'null'], 'description': "The lender's own wording for the product; check it, since a jumbo or program-restricted product may not fit the borrower."}, 'apr_delta_bps': {'type': ['number', 'null'], 'description': "Difference from the borrower's quoted APR in basis points; read `comparison` for the direction."}, 'distance_miles': {'type': ['number', 'null'], 'description': 'Straight-line miles from the ZIP centroid to the nearest branch, not driving distance. Null when no branch geocode is available.'}, 'credit_union_id': {'type': ['string', 'null'], 'description': "Internal composite identifier 'name|city|STATE' of the lender."}, 'distance_method': {'type': ['string', 'null'], 'description': "Precision of the distance: 'branch_coordinate' (exact branch geocode) or 'zip_centroid' (coarser)."}, 'credit_union_name': {'type': ['string', 'null'], 'description': 'Credit union publishing this nearby offer.'}}, 'additionalProperties': True}, 'description': 'Product-matched offers from credit unions with branches near the supplied ZIP, closest first. Included only when the caller asked for nearby offers.'}, 'product_floor': {'type': ['number', 'null'], 'description': 'Lowest rate in percent considered plausible for this product; quotes under it trip below_product_floor.'}, 'classification': {'type': ['string', 'null'], 'description': "Verdict on the quote: 'market_leading', 'plausible', 'suspicious_low', 'overpriced', or 'unknown' when there is too little data to judge."}, 'compared_against': {'type': ['string', 'null'], 'description': "The market segment the quote was matched to, e.g. 'mortgage_30yr'. If this is not the borrower's actual product, the verdict does not apply."}, 'better_offers_meta': {'type': 'object', 'properties': {'assumptions': {'type': 'object', 'description': 'Loan amount, term in months, and intent used for the payment math, plus `assumed` — true when these were defaulted rather than supplied by the caller.'}}, 'description': 'The assumptions used to compute the savings figures on the better offers.', 'additionalProperties': True}, 'nearby_offers_meta': {'type': 'object', 'properties': {'precision': {'type': ['string', 'null'], 'description': "Precision of the distance estimates, e.g. 'ZIP-centroid straight-line estimate'."}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required caveat that distances are straight-line estimates from ZIP centers and NCUA-reported branch locations.'}, 'nearby_credit_union_count': {'type': ['number', 'null'], 'description': 'How many credit unions were found near the ZIP before filtering to those publishing this product.'}}, 'description': 'Context and caveats for the nearby-offer list.', 'additionalProperties': True}, 'below_product_floor': {'type': ['boolean', 'null'], 'description': 'True when the quote is implausibly low for this product, suggesting a teaser, a promotional tier, or a misread number rather than a real offer.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'product_type', 'balance', 'term_months', 'current_rate'], 'properties': {'state': {'type': 'string', 'description': 'US state code'}, 'balance': {'type': 'number', 'description': 'Current loan balance in dollars'}, 'term_months': {'type': 'number', 'description': 'Remaining or new term in months'}, 'credit_score': {'type': 'number', 'description': 'Optional borrower credit score'}, 'current_rate': {'type': 'number', 'description': "Borrower's current interest rate, e.g. 7.25"}, 'product_type': {'type': 'string', 'description': 'mortgage | auto | heloc | personal_loan | student_loan'}, 'closing_costs': {'type': 'number', 'description': 'Lender fees / closing costs in dollars (default 0)'}}}
Ausgabeschema
{'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'reason': {'type': ['string', 'null'], 'description': "Why refinancing is not worth it, present only when `refinance_worth_it` is false — e.g. 'No qualifying market offer beats the current rate.' Its absence means a viable refinance was found."}, 'best_lender': {'type': ['string', 'null'], 'description': 'Credit union publishing that best market rate.'}, 'disclosures': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Caveats and assumptions that must accompany any answer built from this result; surface them rather than dropping them.'}, 'current_rate': {'type': ['string', 'null'], 'description': "The borrower's existing rate as a percent string."}, 'next_actions': {'type': 'array', 'items': {'type': 'object', 'properties': {'why': {'type': ['string', 'null'], 'description': 'One-line reason this follow-up tool would be useful given the current result.'}, 'tool': {'type': ['string', 'null'], 'description': 'Name of the follow-up MCP tool to call next.'}}, 'additionalProperties': True}, 'description': 'Suggested follow-up tools that would deepen this answer; offer them as next steps, not as results.'}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}, 'closing_costs': {'type': ['string', 'null'], 'description': 'Assumed cost in dollars to close the refinance, as a formatted string.'}, 'monthly_savings': {'type': ['string', 'null'], 'description': 'Reduction in the monthly payment in dollars; the difference between the two payments above.'}, 'assumed_defaults': {'type': 'object', 'properties': {'term_months': {'type': ['number', 'null'], 'description': 'Loan term in months assumed because the caller did not supply one.'}, 'closing_costs': {'type': ['number', 'null'], 'description': 'Closing costs in dollars assumed because the caller did not supply them.'}}, 'description': 'Inputs filled in because the caller did not supply them; the break-even is only as good as these.', 'additionalProperties': True}, 'best_market_rate': {'type': ['string', 'null'], 'description': 'Best live published rate available for this product and state, as a percent string.'}, 'lifetime_savings': {'type': ['string', 'null'], 'description': 'Total interest saved in dollars over the full term, before subtracting closing costs.'}, 'break_even_months': {'type': ['number', 'null'], 'description': 'Months of savings needed to repay the closing costs. Refinancing only pays off if the borrower keeps the loan longer than this.'}, 'refinance_worth_it': {'type': ['boolean', 'null'], 'description': 'True when the refinance clears its costs on the assumptions shown; it does not account for how long the borrower actually plans to stay.'}, 'new_monthly_payment': {'type': ['string', 'null'], 'description': 'Principal-and-interest payment in dollars after refinancing at the best market rate.'}, 'net_lifetime_savings': {'type': ['string', 'null'], 'description': 'Lifetime savings after subtracting closing costs — the honest headline number.'}, 'current_monthly_payment': {'type': ['string', 'null'], 'description': 'Principal-and-interest payment in dollars on the existing loan, as a formatted string.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id', 'recipient_id'], 'properties': {'id': {'type': 'string', 'description': 'Campaign id. Required.'}, 'recipient_id': {'type': 'string', 'description': 'Recipient id. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'success': {'type': 'boolean', 'description': 'True when the request completed.'}}, 'description': 'Removal acknowledgement. The route replies 204 with no body, which the client renders as a bare success flag. It is idempotent — an unknown recipient id still succeeds.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['inputs'], 'properties': {'inputs': {'type': 'array', 'items': {'type': 'object', 'required': ['value', 'entity_type'], 'properties': {'value': {'type': 'string', 'maxLength': 120, 'minLength': 2, 'description': 'Organization name as supplied by the user.'}, 'entity_type': {'enum': ['employer', 'association', 'school', 'worship'], 'type': 'string', 'description': 'Asserted exact organization type.'}}, 'additionalProperties': False}, 'maxItems': 50, 'minItems': 1, 'description': 'Typed values to resolve in stable input order.'}, 'candidate_limit': {'type': 'integer', 'default': 5, 'maximum': 10, 'minimum': 1, 'description': 'Maximum exact matches or prefix suggestions returned per input.'}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'results': {'type': 'array', 'items': {'type': 'object', 'properties': {'input': {'type': 'object', 'description': 'Original typed value plus its normalized representation.', 'additionalProperties': True}, 'entity': {'type': 'object', 'description': 'Authoritative entity only when exactly one normalized exact match exists with confidence of at least 0.8.', 'additionalProperties': True}, 'status': {'type': ['string', 'null'], 'description': 'resolved, ambiguous, or unresolved.'}, 'candidates': {'type': 'array', 'items': {'type': 'object', 'additionalProperties': True}, 'description': 'Exact ambiguity choices or non-authoritative prefix suggestions.'}, 'input_index': {'type': ['number', 'null'], 'description': 'Zero-based position of the corresponding input.'}, 'candidates_truncated': {'type': ['boolean', 'null'], 'description': 'Whether more candidates existed for this input.'}}, 'additionalProperties': True}, 'description': 'One resolution result per input in the same order.'}, 'semantics': {'type': ['string', 'null'], 'description': 'Machine-readable organization-resolution-not-eligibility contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required warning that resolution does not prove eligibility.'}, 'resolution_method': {'type': ['string', 'null'], 'description': 'Authority rule: one normalized-exact match with confidence of at least 0.8.'}, 'prefix_candidates_are_suggestions': {'type': ['boolean', 'null'], 'description': 'True: prefix results must never be silently promoted to facts.'}}, 'description': 'Stable-order exact normalized canonical organization resolution.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['token'], 'properties': {'token': {'type': 'string', 'description': 'The share token to revoke. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'success': {'type': 'boolean', 'description': 'True when the share was revoked.'}}, 'description': 'Revocation acknowledgement. The route replies 204 with no body, which the client renders as a bare success flag.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['name', 'members'], 'properties': {'name': {'type': 'string', 'description': 'Cohort name, e.g. "Q2 refi prospects". Required.'}, 'members': {'type': 'array', 'items': {'type': 'object', 'required': ['label', 'scenario'], 'properties': {'label': {'type': 'string', 'description': 'Member label, e.g. "Smith — $400k purchase".'}, 'scenario': {'type': 'object', 'description': 'A financing scenario: { product_type, state, intent, amount, term_months, credit_score?, current_offer?:{rate,apr,amount,term_months} }.'}}}, 'description': 'List of cohort members (max ~50).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Cohort id — pass to scan_portfolio, get_cohort, schedule_digest.'}, 'name': {'type': 'string', 'description': 'Cohort label.'}, 'members': {'type': 'array', 'items': {'type': 'object', 'properties': {'label': {'type': 'string', 'description': "Member label, e.g. the client's name."}, 'scenario': {'type': 'object', 'description': 'The decision inputs for this member.', 'additionalProperties': True}}, 'additionalProperties': True}, 'description': 'The cohort members as supplied.'}, 'lastScan': {'type': ['object', 'null'], 'description': 'Previous scan snapshot. Null on a newly created cohort.', 'additionalProperties': True}, 'createdAt': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'updatedAt': {'type': ['string', 'null'], 'description': 'ISO-8601 last-modified timestamp.'}}, 'description': 'The saved cohort (book of business), as stored. Capped at 50 members.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['client_name', 'input', 'result_snapshot'], 'properties': {'input': {'type': 'object', 'description': 'The scenario inputs (product, amount, state, term, etc.)'}, 'client_name': {'type': 'string', 'description': 'Client/scenario label, e.g. "Smith — $400k purchase, CA"'}, 'result_snapshot': {'description': 'The comparison result to store (object from get_financing_decision/compare_products)'}}}
Ausgabeschema
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Scenario id — pass to get_scenario, generate_share_link, or generate_client_report.'}, 'input': {'type': ['object', 'null'], 'description': 'The decision inputs that produced the snapshot (product, amount, state, term).', 'additionalProperties': True}, 'createdAt': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}, 'clientName': {'type': 'string', 'description': 'Client label for the scenario.'}, 'resultSnapshot': {'description': 'The decision result captured at save time. Shape mirrors a /v1/decisions response.'}}, 'description': 'The saved client scenario, as stored.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Cohort id to scan. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'triage': {'type': 'array', 'items': {'type': 'object', 'properties': {'label': {'type': 'string', 'description': 'Member label.'}, 'best_apr': {'type': ['number', 'null'], 'description': 'Best APR percent.'}, 'best_lender': {'type': ['string', 'null'], 'description': 'Institution with the best offer.'}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly payment on the best offer.'}, 'savings_vs_current': {'type': ['number', 'null'], 'description': "Monthly saving against the member's stated current rate, when supplied."}}, 'additionalProperties': True}, 'description': "Every member's current best offer."}, 'changed': {'type': 'array', 'items': {'type': 'object', 'properties': {'to': {'type': 'object', 'description': 'Current best_lender and best_apr.', 'additionalProperties': True}, 'from': {'type': ['object', 'null'], 'description': 'Prior best_lender and best_apr. Absent for a new member.', 'additionalProperties': True}, 'label': {'type': 'string', 'description': 'Member label.'}, 'change': {'type': 'string', 'description': "'new', 'best_lender_changed', or 'apr_changed'."}, 'apr_delta': {'type': ['number', 'null'], 'description': 'Change in APR in percentage points.'}}, 'additionalProperties': True}, 'description': 'Members whose best offer moved since the previous scan.'}, 'scanned': {'type': 'number', 'description': 'Members evaluated (capped at 50).'}}, 'description': 'Live re-scan of every cohort member against the decision engine, diffed against the previous snapshot. The new snapshot is persisted.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['state', 'debts'], 'properties': {'debts': {'type': 'array', 'items': {'type': 'object', 'required': ['product_type', 'balance', 'current_rate', 'term_months'], 'properties': {'balance': {'type': 'number', 'description': 'Outstanding balance in dollars.'}, 'term_months': {'type': 'number', 'description': 'Remaining term in months.'}, 'current_rate': {'type': 'number', 'description': 'Current interest rate as a percentage (e.g., 7.9).'}, 'product_type': {'enum': ['auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'mortgage', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of the existing debt.'}}}, 'description': 'List of existing debts to evaluate for refinancing.'}, 'state': {'type': 'string', 'description': 'US state code (2-letter, e.g., TX). Required.'}, 'credit_score': {'type': 'number', 'description': "Borrower's credit score (300-850). Recommended for accurate matching."}}}
Ausgabeschema
{'type': 'object', 'properties': {'stack': {'type': 'array', 'items': {'type': 'object', 'properties': {'rank': {'type': ['number', 'null'], 'description': 'Priority of this debt for refinancing, 1 = largest opportunity.'}, 'balance': {'type': ['number', 'null'], 'description': 'Outstanding balance in dollars on this debt.'}, 'worth_it': {'type': ['boolean', 'null'], 'description': 'True when the saving is large enough to be worth acting on; it does not account for closing costs specific to the user.'}, 'best_offer': {'type': 'object', 'description': 'Best live published replacement offer, with lender, APR and rate in percent, points, and monthly payment in dollars.'}, 'current_rate': {'type': ['number', 'null'], 'description': 'Rate in percent the user currently pays on this debt.'}, 'product_type': {'type': ['string', 'null'], 'description': "Category of the existing debt, e.g. 'mortgage', 'auto_loan'."}, 'monthly_savings': {'type': ['number', 'null'], 'description': 'Dollars per month saved by moving to the best offer at the same balance and remaining term.'}, 'lifetime_savings': {'type': ['number', 'null'], 'description': 'Total dollars saved over the remaining term, before any refinancing or closing costs.'}, 'current_monthly_payment': {'type': ['number', 'null'], 'description': 'What the user pays each month in dollars on this debt today.'}}, 'additionalProperties': True}, 'description': "The user's debts ordered by refinancing opportunity, biggest saving first."}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'totals': {'type': 'object', 'properties': {'total_monthly_savings': {'type': ['number', 'null'], 'description': 'Sum of the monthly savings in dollars across all debts worth refinancing.'}, 'total_lifetime_savings': {'type': ['number', 'null'], 'description': 'Sum of the lifetime savings in dollars across all debts, dominated by the longest-term debt.'}, 'debts_worth_refinancing': {'type': ['number', 'null'], 'description': 'How many of the submitted debts cleared the worth-it bar.'}}, 'description': 'Combined opportunity across every debt in the stack.', 'additionalProperties': True}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['cohort_id', 'email'], 'properties': {'email': {'type': 'string', 'description': 'Where to send the digest.'}, 'cadence': {'type': 'string', 'description': 'weekly (default) or daily.'}, 'cohort_id': {'type': 'string', 'description': 'The cohort to scan on a schedule (from list_cohorts).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Digest id — pass to delete_digest.'}, 'email': {'type': 'string', 'description': 'Recipient address.'}, 'cadence': {'type': 'string', 'description': "'daily' or 'weekly'. Anything other than 'daily' is stored as 'weekly'."}, 'enabled': {'type': 'boolean', 'description': 'True on creation.'}, 'cohort_id': {'type': 'string', 'description': 'Cohort the digest scans.'}, 'created_at': {'type': ['string', 'null'], 'description': 'ISO-8601 creation timestamp.'}}, 'description': 'The scheduled digest that was created — a standing instruction to scan a cohort on a cadence and email the result.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['query'], 'properties': {'limit': {'type': 'number', 'description': 'Maximum pages to return (1-12). Defaults to 5.'}, 'query': {'type': 'string', 'description': 'What you want to know about the API, in plain words (e.g. "oauth", "how fresh are rates", "429 error").'}}}
Ausgabeschema
{'type': 'object', 'properties': {'note': {'type': ['string', 'null'], 'description': 'Guidance on what to do with these results.'}, 'count': {'type': ['number', 'null'], 'description': 'Number of pages returned.'}, 'query': {'type': ['string', 'null'], 'description': 'The query as received.'}, 'results': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'url': {'type': ['string', 'null'], 'description': 'Canonical published URL to cite.'}, 'slug': {'type': ['string', 'null'], 'description': 'Identifier to pass to get_doc.'}, 'score': {'type': ['number', 'null'], 'description': 'Relevance score; comparable within one result set only.'}, 'title': {'type': ['string', 'null'], 'description': 'Page title.'}, 'excerpt': {'type': ['string', 'null'], 'description': 'The first matching paragraph of the page.'}, 'summary': {'type': ['string', 'null'], 'description': 'One-line description of the page.'}}, 'additionalProperties': True}, 'description': 'Matching documentation pages, best match first.'}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': [], 'properties': {'limit': {'type': 'integer', 'default': 10, 'maximum': 10, 'minimum': 1, 'description': 'Maximum results; the response discloses truncation.'}, 'query': {'type': 'string', 'maxLength': 120, 'minLength': 2, 'description': 'Optional organization name or prefix, 2-120 characters. Omit to browse by active-publication connectivity.'}, 'types': {'type': 'array', 'items': {'enum': ['employer', 'association', 'school', 'worship'], 'type': 'string'}, 'maxItems': 4, 'minItems': 1, 'description': 'Exact public organization types to search. Omit for all four types.', 'uniqueItems': True}}, 'additionalProperties': False}
Ausgabeschema
{'type': 'object', 'properties': {'query': {'type': ['string', 'null'], 'description': 'Trimmed search text supplied by the caller.'}, 'types': {'type': 'array', 'items': {'type': ['string', 'null']}, 'description': 'Exact public entity types included in the search.'}, 'results': {'type': 'array', 'items': {'type': 'object', 'properties': {'org_id': {'type': ['string', 'null'], 'description': 'Stable canonical organization identifier; identical to entity_id.'}, 'entity_id': {'type': ['string', 'null'], 'description': 'Stable canonical entity identifier.'}, 'entity_type': {'type': ['string', 'null'], 'description': 'Exact public organization type.'}, 'match_method': {'type': ['string', 'null'], 'description': 'normalized_exact, normalized_prefix, or canonical_id for query-less browse.'}, 'matched_alias': {'type': ['string', 'null'], 'description': 'Stored alias that produced this match.'}, 'canonical_name': {'type': ['string', 'null'], 'description': 'Canonical public organization name.'}, 'match_confidence': {'type': ['number', 'null'], 'description': 'Alias and method confidence from 0 to 1; not eligibility confidence.'}, 'active_rule_count': {'type': ['number', 'null'], 'description': 'Current active-publication positive rules referencing this entity.'}, 'last_confirmed_at': {'type': ['string', 'null'], 'description': 'Latest derivable publication-bound confirmation timestamp, or null.'}, 'active_institution_count': {'type': ['number', 'null'], 'description': 'Active institutions whose publications positively reference this entity.'}}, 'additionalProperties': True}, 'description': 'Deterministically ranked canonical entity matches; these do not imply personal eligibility.'}, 'semantics': {'type': ['string', 'null'], 'description': 'Machine-readable organization-discovery-not-eligibility contract.'}, 'disclosure': {'type': ['string', 'null'], 'description': 'Required warning that organization discovery does not prove eligibility.'}, 'result_mode': {'type': ['string', 'null'], 'description': 'search for text-ranked results or most_connected for query-less graph-connectivity browse; neither is an eligibility verdict.'}, 'result_limit': {'type': ['number', 'null'], 'description': 'Requested result cap.'}, 'query_truncated': {'type': ['boolean', 'null'], 'description': 'Whether the accepted query text was truncated; currently always false because oversized input is rejected.'}, 'normalized_query': {'type': ['string', 'null'], 'description': 'Canonical normalized text used for indexed exact and prefix matching.'}, 'results_truncated': {'type': ['boolean', 'null'], 'description': 'True when more authorized matches existed than were returned.'}}, 'description': 'Bounded canonical organization discovery backed only by positive conditions in active publications.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Campaign id. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'sent': {'type': 'number', 'description': 'Emails handed to the provider.'}, 'failed': {'type': 'number', 'description': 'Recipients the provider rejected.'}, 'run_id': {'type': ['string', 'number', 'null'], 'description': 'Id of the campaign run, for correlating with send history.'}, 'suppressed': {'type': 'number', 'description': 'Recipients skipped because they had unsubscribed or were otherwise suppressed.'}}, 'description': "Result of an immediate full send to the campaign's recipients, using the same path as the scheduled cron. Only an 'active' campaign can be sent.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Campaign id. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'ok': {'type': 'boolean', 'description': 'True when the test email was accepted by the email provider.'}, 'message': {'type': 'string', 'description': 'Confirmation naming the address the test was sent to.'}}, 'description': "Result of a single test send. The email goes to the organization OWNER's address, not to campaign recipients, and is capped at 3 per day per address.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'properties': {'intro_text': {'type': 'string', 'description': 'Default intro paragraph for campaign emails.'}, 'brand_color': {'type': 'string', 'description': 'Accent color as a #hex string (e.g. #00b368).'}, 'display_name': {'type': 'string', 'description': 'The lender/brand name shown as the email sender and advertiser.'}, 'reply_to_email': {'type': 'string', 'description': 'Optional Reply-To address for campaign emails.'}, 'business_address': {'type': 'string', 'description': 'Physical mailing address of the advertiser (CAN-SPAM).'}, 'logo_background_color': {'type': 'string', 'description': 'Solid backdrop behind the logo in the email header, as a 6-digit #hex (e.g. #0d1b2a). Useful when the logo is white. Omit or null for the white default.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'branding': {'type': ['object', 'null'], 'properties': {'logo_url': {'type': ['string', 'null'], 'description': 'Public logo URL.'}, 'intro_text': {'type': ['string', 'null'], 'description': 'Default intro paragraph for campaign emails.'}, 'brand_color': {'type': ['string', 'null'], 'description': 'Accent color as a #hex string.'}, 'display_name': {'type': ['string', 'null'], 'description': 'From-name and CAN-SPAM advertiser identity. Required before a campaign can be activated.'}, 'logo_email_url': {'type': ['string', 'null'], 'description': 'Email-optimized logo variant.'}, 'reply_to_email': {'type': ['string', 'null'], 'description': 'Optional Reply-To address.'}, 'organization_id': {'type': 'string', 'description': 'Owning organization.'}, 'business_address': {'type': ['string', 'null'], 'description': 'CAN-SPAM physical address. Required before a campaign can be activated or sent.'}, 'logo_background_color': {'type': ['string', 'null'], 'description': 'Logo backdrop as a 6-digit #hex string.'}}, 'description': 'The stored branding row.', 'additionalProperties': True}}, 'description': "The organization's email branding after the update, wrapped in a `branding` envelope.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['scenario', 'sweep'], 'properties': {'sweep': {'type': 'object', 'required': ['field', 'from', 'to', 'step'], 'properties': {'to': {'type': 'number', 'description': 'End value (inclusive).'}, 'from': {'type': 'number', 'description': 'Start value (inclusive).'}, 'step': {'type': 'number', 'description': 'Increment between values.'}, 'field': {'enum': ['credit_score', 'down_payment_percent', 'rate_shift_bps'], 'type': 'string', 'description': 'Which input to vary across the grid.'}}, 'description': 'The input to sweep and its range.'}, 'scenario': {'type': 'object', 'required': ['product_type', 'state', 'intent', 'amount'], 'properties': {'state': {'type': 'string', 'description': 'US state code (2-letter).'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars.'}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'The loan intent.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months.'}, 'credit_score': {'type': 'number', 'description': 'Baseline credit score (used unless swept).'}, 'product_type': {'enum': ['mortgage', 'mortgage_arm', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'personal_loan', 'heloc', 'credit_card', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of financing product.'}, 'down_payment_percent': {'type': 'number', 'description': 'Baseline down payment percent (used unless swept).'}}, 'description': 'The fixed financing scenario.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'grid': {'type': 'array', 'items': {'type': 'object', 'properties': {'value': {'type': ['number', 'null'], 'description': "The swept input's value for this row, e.g. a credit score of 700."}, 'best_apr': {'type': ['number', 'null'], 'description': 'Best published APR in percent at this swept value, taken as published without any score adjustment.'}, 'best_lender': {'type': ['string', 'null'], 'description': 'Best lender at this swept value. It often does not change, because published credit-union rates are rarely tiered by score.'}, 'monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly payment in dollars at best_apr.'}, 'estimated_tier_apr': {'type': ['number', 'null'], 'description': 'APR in percent after applying a modeled credit-tier adjustment — an estimate of what this borrower would actually be offered, not a published rate.'}, 'estimated_tier_monthly_payment': {'type': ['number', 'null'], 'description': 'Monthly payment in dollars at the tier-adjusted APR; this is the realistic figure to quote a borrower at this credit score.'}}, 'additionalProperties': True}, 'description': 'One row per swept value, showing how the outcome changes.'}, 'state': {'type': ['string', 'null'], 'description': "Two-letter US state code the result is scoped to (e.g. 'CA'). Null means the result was not filtered by state."}, 'flip_points': {'type': 'array', 'description': 'Values of the swept input where the winning lender or recommended action changes. Empty means the outcome is stable across the whole sweep.'}, 'sweep_field': {'type': ['string', 'null'], 'description': "The input that was varied across the grid, e.g. 'credit_score'."}, 'product_type': {'type': ['string', 'null'], 'description': "Loan or deposit category this result covers, e.g. 'mortgage', 'auto_loan', 'heloc', 'savings'."}}, 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['monitor_id', 'rate_change'], 'properties': {'monitor_id': {'type': 'string', 'description': 'The unique identifier of the monitor to simulate. Required.'}, 'rate_change': {'type': 'object', 'required': ['state', 'product_type', 'previous_rate', 'new_rate'], 'properties': {'state': {'type': 'string', 'description': 'US state code where the rate changed. Required.'}, 'new_rate': {'type': 'number', 'description': 'The new rate value. Required.'}, 'product_type': {'type': 'string', 'description': 'The product type that changed (e.g., "30yr_fixed"). Required.'}, 'previous_rate': {'type': 'number', 'description': 'The previous rate value. Required.'}}, 'description': 'The simulated rate change event. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'error': {'type': ['string', 'null'], 'description': "Present and set to 'not_found' when the monitor id does not exist."}, 'summary': {'type': 'string', 'description': 'Plain-language verdict on whether the monitor would fire, or a not-found message.'}, 'evaluation': {'type': 'object', 'properties': {'conditions_met': {'type': ['boolean', 'array', 'null'], 'description': 'Whether the trigger conditions were satisfied.'}, 'conditions_summary': {'type': ['string', 'array', 'null'], 'description': 'Per-condition explanation of the evaluation.'}}, 'description': 'Why the monitor did or did not fire.', 'additionalProperties': True}, 'rate_change': {'type': 'object', 'properties': {'state': {'type': ['string', 'null'], 'description': 'Two-letter state code.'}, 'new_rate': {'type': ['string', 'null'], 'description': 'New rate, formatted as a percent string.'}, 'change_pct': {'type': ['string', 'null'], 'description': "Signed change, formatted as a percent string such as '+0.25%'."}, 'product_type': {'type': ['string', 'null'], 'description': 'Product type of the simulated change.'}, 'previous_rate': {'type': ['string', 'null'], 'description': "Prior rate, formatted as a percent string such as '6.5%'."}}, 'description': 'The simulated change, echoed back with rates pre-formatted as percent strings.', 'additionalProperties': True}, 'would_trigger': {'type': 'boolean', 'description': "Whether the monitor's conditions are satisfied by the supplied change."}}, 'description': 'Dry-run evaluation of a monitor against a hypothetical rate change. No webhook is sent and the cooldown is ignored. On a missing id the tool returns a not-found shape instead of throwing.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['email', 'product_type', 'intent', 'target'], 'properties': {'email': {'type': 'string', 'description': 'Consumer email address to send the alert to. Required.'}, 'state': {'type': 'string', 'description': 'Legacy single US state code (2-letter, e.g., CA, TX, NY). Prefer states or region for multi-state alerts.'}, 'amount': {'type': 'number', 'description': 'Loan amount in dollars. Optional.'}, 'intent': {'enum': ['purchase', 'refinance', 'cash_out', 'balance_transfer', 'new_credit'], 'type': 'string', 'description': 'The loan intent. Required.'}, 'region': {'enum': ['east_coast', 'west_coast', 'midwest', 'south', 'northeast', 'southeast', 'southwest', 'mountain_west', 'new_england', 'mid_atlantic', 'pacific_northwest'], 'type': 'string', 'description': 'Named region preset (e.g. east_coast); expands server-side to its member states.'}, 'states': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 25, 'description': '2-letter US state codes (up to 25) — best rates are ranked ACROSS all of them, not per state.'}, 'target': {'type': 'object', 'required': ['field', 'operator', 'value'], 'properties': {'field': {'enum': ['rate', 'apr', 'monthly_payment'], 'type': 'string', 'description': 'The field to watch.'}, 'value': {'type': 'number', 'description': 'The threshold value to compare against.'}, 'operator': {'enum': ['lte', 'gte'], 'type': 'string', 'description': 'Comparison operator (lte=at or below, gte=at or above).'}}, 'description': 'The condition that triggers the alert. Required.'}, 'term_months': {'type': 'number', 'description': 'Loan term in months (12-480). Optional.'}, 'credit_score': {'type': 'number', 'description': 'Credit score (300-850). Optional.'}, 'product_type': {'enum': ['mortgage', 'auto_loan', 'rv', 'boat', 'motorcycle', 'powersports', 'heloc', 'personal_loan', 'student_loan', 'equipment_loan'], 'type': 'string', 'description': 'Type of loan product. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'email': {'type': 'string', 'description': 'Subscriber address.'}, 'state': {'type': ['string', 'null'], 'description': 'Legacy scalar state — the first entry of `states`.'}, 'states': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Full list of watched state codes. Regions are expanded to a fixed snapshot at subscribe time.'}, 'status': {'type': 'string', 'description': "Typically 'pending_confirmation'."}, 'target': {'type': 'object', 'properties': {'field': {'type': ['string', 'null'], 'description': "Field watched, e.g. 'rate', 'apr', or 'monthly_payment'."}, 'value': {'type': ['number', 'null'], 'description': 'Threshold value.'}, 'operator': {'type': ['string', 'null'], 'description': "Comparison operator, e.g. 'lte' or 'gte'."}}, 'description': 'The threshold that fires the alert.', 'additionalProperties': True}, 'message': {'type': 'string', 'description': "Human-readable next step ('Check your inbox to confirm')."}, 'alert_id': {'type': 'string', 'description': 'Id of the created alert.'}, 'disclosures': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Consent and CAN-SPAM disclosures for the subscription.'}, 'next_actions': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Suggested follow-up tool names.'}, 'region_preset': {'type': ['string', 'null'], 'description': 'Region preset key when one was used, else null.'}, 'assumed_defaults': {'type': 'object', 'properties': {'amount': {'type': ['number', 'null'], 'description': 'Loan amount used when evaluating the threshold.'}, 'term_months': {'type': ['number', 'null'], 'description': 'Term in months.'}}, 'description': 'Loan assumptions recorded with the alert; null where the caller supplied none.', 'additionalProperties': True}}, 'description': "Result of a double-opt-in rate-alert subscription. The alert is created in 'pending' status and only becomes active once the borrower clicks the confirmation email.", 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['token'], 'properties': {'token': {'type': 'string', 'description': 'The unsubscribe token from the email. Required.'}}}
Ausgabeschema
{'type': 'object', 'properties': {'status': {'type': 'string', 'description': "'unsubscribed' on success."}, 'alert_id': {'type': 'string', 'description': 'The alert that was unsubscribed.'}}, 'description': 'Result of a one-click unsubscribe. Replaying a token on an already-unsubscribed alert is treated as not-found and surfaces as an error rather than this shape.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'description': 'Campaign id. Required.'}, 'name': {'type': 'string'}, 'region': {'enum': ['east_coast', 'west_coast', 'midwest', 'south', 'northeast', 'southeast', 'southwest', 'mountain_west', 'new_england', 'mid_atlantic', 'pacific_northwest'], 'type': 'string', 'description': 'Named region preset (e.g. east_coast); expands server-side to its member states.'}, 'status': {'enum': ['active', 'paused'], 'type': 'string'}, 'cadence': {'enum': ['daily', 'weekly', 'monthly'], 'type': 'string'}, 'products': {'type': 'array', 'items': {'type': 'object'}, 'description': 'Full replacement product set (1-5, no duplicates); same shapes as create_email_campaign.'}, 'state_code': {'type': 'string', 'description': 'Legacy single 2-letter US state code. Prefer state_codes or region.'}, 'state_codes': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 25, 'description': '2-letter US state codes (up to 25) — best rates are ranked ACROSS all of them, not per state.'}, 'intro_text_override': {'type': 'string'}}}
Ausgabeschema
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Campaign id.'}, 'name': {'type': 'string', 'description': 'Campaign label.'}, 'status': {'type': ['string', 'null'], 'description': "'draft', 'active', or 'paused'."}, 'cadence': {'type': ['string', 'null'], 'description': "'daily', 'weekly', or 'monthly'."}, 'products': {'type': ['array', 'null'], 'description': 'Parsed list of products the email covers.'}, 'created_at': {'type': ['number', 'null'], 'description': 'Epoch-ms creation time.'}, 'state_code': {'type': ['string', 'null'], 'description': 'Legacy scalar state — first entry of state_codes.'}, 'updated_at': {'type': ['number', 'null'], 'description': 'Epoch-ms last-modified time.'}, 'last_run_at': {'type': ['number', 'null'], 'description': 'Epoch-ms of the last send.'}, 'state_codes': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Full list of covered state codes.'}, 'product_type': {'type': ['string', 'null'], 'description': 'Primary product type.'}, 'region_preset': {'type': ['string', 'null'], 'description': 'Region preset key, or null.'}, 'organization_id': {'type': 'string', 'description': 'Owning organization.'}, 'product_category': {'type': ['string', 'null'], 'description': 'Product family.'}, 'intro_text_override': {'type': ['string', 'null'], 'description': 'Per-campaign intro override.'}}, 'description': 'The campaign after the patch. Activating a campaign requires a display name and business address on the org branding.', 'additionalProperties': True}
Eingabeschema
{'type': 'object', 'required': ['monitor_id'], 'properties': {'name': {'type': 'string', 'description': 'New name for the monitor.'}, 'status': {'enum': ['active', 'paused', 'disabled'], 'type': 'string', 'description': 'New status for the monitor.'}, 'conditions': {'type': 'array', 'items': {'type': 'object', 'required': ['field', 'operator', 'value'], 'properties': {'field': {'enum': ['rate', 'apr', 'monthly_payment'], 'type': 'string'}, 'value': {'type': 'number'}, 'operator': {'enum': ['lt', 'lte', 'gt', 'gte', 'eq', 'change_pct'], 'type': 'string'}}}, 'description': 'New array of conditions.'}, 'monitor_id': {'type': 'string', 'description': 'The unique identifier of the monitor to update. Required.'}, 'webhook_url': {'type': 'string', 'description': 'New webhook URL.'}, 'cooldown_hours': {'type': 'number', 'description': 'New cooldown period in hours (1-168).'}}}
Ausgabeschema
{'type': 'object', 'properties': {'error': {'type': ['string', 'null'], 'description': "Present and set to 'not_found' when the monitor id does not exist."}, 'monitor': {'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Monitor id.'}, 'name': {'type': 'string', 'description': 'Monitor label.'}, 'status': {'type': 'string', 'description': "'active' or 'paused'."}, 'conditions': {'type': ['array', 'null'], 'description': 'Trigger conditions after the update.'}, 'updated_at': {'type': ['string', 'null'], 'description': 'ISO-8601 last-modified timestamp.'}, 'webhook_url': {'type': ['string', 'null'], 'description': 'Delivery URL.'}, 'cooldown_hours': {'type': ['number', 'null'], 'description': 'Minimum hours between triggers.'}}, 'description': 'The monitor after the update. Absent when not found.', 'additionalProperties': True}, 'summary': {'type': 'string', 'description': 'Confirmation naming the monitor and which fields changed, or a not-found message.'}}, 'description': 'Result of patching a monitor. On a missing id the tool returns a not-found shape instead of throwing.', 'additionalProperties': True}
Letzte Tool-Änderungen
Ähnliche MCP-Server
Superlógica Condomínios
Connects to a condominium ERP for billing, collections, agreements, expenses, bank movements, statements, files, communications, …
DFX Real Estate Intelligence
Provides US commercial real estate, parcel, debt maturity, bank CRE exposure, private capital, investor, ownership, occupancy, an…
Rafid Intelligence Network
Analyzes Oman properties using rental comparables, yields, costs, and payback metrics, and supports Oman company search, profilin…
Housing Intel
Analyzes housing markets, affordability, mortgage rates, rental yields, property data, employment, metro demand, and investment s…
OpenLMNP
Manages French LMNP furnished-rental accounting, including income, expenses, depreciation, loans, VAT, fiscal calculations, FEC f…
Antevo Wealth
Aggregates household wealth data across investments, liabilities, credit facilities, real assets, markets, risk, exposure, and fi…
DataPorium
Provides market and company data covering stocks, ETFs, crypto, forex, commodities, economic indicators, housing, property listin…
Cambio Uruguay
Provides Uruguayan exchange-rate data, rental and used-car searches, product pricing, market comparisons, and neighborhood inform…