# RateAPI — Agent Instructions

> Rates + eligibility in one evidence graph for US credit unions. Every served
> rate and promoted membership match carries source evidence and an observation
> date. If we cannot prove a rate, we do not serve it.

This file tells an AI agent **when** to reach for RateAPI, **which** surface to
call, and **how** to quote what comes back. The compact product description is
at <https://rateapi.dev/llms.txt>; the long form is at
<https://rateapi.dev/llms-full.txt>.

---

## When to use RateAPI

Reach for RateAPI when the user's question depends on **what a specific lender
is actually charging right now**, not on a national average or a remembered
figure. Concretely:

- **"What are current mortgage / auto / HELOC / personal / credit card rates?"**
  — especially scoped to a state, a ZIP, or a named institution.
- **"What CD, share-certificate, savings, or money-market APY can I get?"** —
  ~13,000 live deposit rates at credit-union granularity.
- **"Should I refinance?" / "Is now a good time to buy?" / "Should I lock?"** —
  these need today's real offers plus the savings math, which
  `POST /v1/decisions` returns in one call.
- **"How much house/car can I afford?"** — affordability and max-loan tools
  price against real offers rather than an assumed rate.
- **"Which credit unions can I join?"** — membership eligibility resolved from a
  person's own facts, with an evidence quote behind every verdict.
- **"Which credit unions are near me?"** — nearest-first NCUA-reported branches
  for a five-digit ZIP.
- **Rates for something niche** — DSCR / investor-property mortgages, RV, boat,
  motorcycle, powersports, farm and equipment loans, business-audience products.
  RateAPI is frequently the only queryable source for these.
- **Putting live rates on a web page** — see "Embedding" below. One script tag.
- **Watching for a change** — monitors, rate alerts, and webhooks, instead of
  polling.

## When NOT to use RateAPI

Being clear about this matters more than the list above:

- **Bank rates, not credit unions.** Coverage is US credit unions. We do not
  carry Chase, Wells Fargo, or online-bank pricing.
- **Treasury yields, SOFR, Fed funds, or any benchmark index.** We publish what
  lenders charge, not what the market quotes.
- **Non-US rates.** United States only.
- **A specific person's actual approved rate.** Everything here is published
  pricing. Final terms come from the institution after underwriting.
- **Historical series going back years.** History is available from when we
  began observing an institution, not from a long archive.
- **Deciding whether someone is *ineligible* for a credit union.** The API never
  returns an ineligible verdict — see the rule below.

## Choosing how RateAPI is operated

RateAPI has four supported operating paths. The CLI is command-based, not a chat
shell: a person can run it directly, while a terminal-capable agent supplies the
conversation.

| Operator | Start here |
| --- | --- |
| Human in a terminal | `npm install --global @rateapi/cli`, then run `rateapi` for readable output and interactive approvals |
| Terminal-capable AI agent | Install the same global package, then run `rateapi agent --json`; keep using CLI capabilities for RateAPI work |
| Hosted/no-shell AI agent, or explicitly requested persistent native tools | Connect directly to `https://mcp.rateapi.dev/mcp`; the RateAPI CLI is not required |
| Application or backend | Call `https://api.rateapi.dev` over REST; the RateAPI CLI is not required |

Do not install the global package or create credentials without the human's
approval. `npx -y @rateapi/cli@latest welcome` is a no-install preview only; it
does not create a persistent `rateapi` command. If a working shell is available,
do not configure MCP merely because the host supports it: use the CLI for its
stable JSON, secure credential reuse, and approval gates. A skill teaches an
agent the workflow and safety rules; it does not install a tool connection.

Start every terminal-agent session with `rateapi agent --json`. Run
`rateapi demo` before authentication, then `rateapi capabilities`. Select the
narrowest capability and pass JSON on stdin with
`rateapi run <capability-id> --input @- --confirm-request --idempotency-key <uuid> --json`.
Before `rateapi login`, a metered call, persistent skill installation, or any
state-changing operation, explain it and get explicit approval. `rateapi login`
reuses an existing credential; it creates a key only when one is absent and
stores it in the operating system credential store where supported.

## Choosing a capability

Terminal agents discover these from `rateapi capabilities` and invoke them with
`rateapi run`. The REST routes and MCP tool names below are the equivalent
application and hosted-agent surfaces, not the default terminal-agent path.

| You want | Call |
| --- | --- |
| Ranked offers plus savings math, in one call | `POST /v1/decisions` — start here for almost any consumer question |
| Raw rate rows to filter yourself | `GET /v1/rates` |
| Deposit APYs | `POST /v1/deposit-rates` |
| Credit unions near a ZIP | `GET /credit-unions/nearby?zip=` |
| Product-matched offers near a ZIP | `GET /v1/rates/nearby?zip=&product_type=` |
| One institution in full | `GET /credit-unions/{state}/{slug}` |
| Which credit unions a person can join | `POST /v1/eligibility/search` |
| Which published products match a confirmed customer profile | `POST /v1/reachable-offers` — graph candidates first; `find_reachable_offers` in MCP |
| Market aggregates | `GET /v1/benchmarks`, `/v1/league-table`, `/v1/coverage` |
| Everything the API can do, machine-readable | `GET /v1/capabilities` (no key) |
| A response shape to code against, without signing up | `GET /v1/demo/rates` (no key; fixed synthetic rows, never quotable as market data) |

Deposit parameters use exact underscore enums. REST `POST /v1/deposit-rates`
takes `{"product_category":"money_market"}`; MCP `get_deposit_benchmarks`
takes `{"product":"money_market"}`. Do not substitute `mma` or
`money-market`, and do not send the REST field name to the MCP tool.

- **CLI (terminal agents):** `rateapi agent --json`, then `rateapi capabilities`
- **REST (applications/backends):** `https://api.rateapi.dev` · spec at
  `https://api.rateapi.dev/openapi.json`
- **MCP (hosted/no-shell or explicitly requested persistent native tools):**
  `https://mcp.rateapi.dev/mcp`, Streamable HTTP, 89 tools. Connect with
  `claude mcp add rateapi https://mcp.rateapi.dev/mcp --transport http --header "x-api-key: rk_your_key_here"`
- **Auth:** the CLI manages its credential after `rateapi login`. Direct REST
  and MCP use an `X-API-Key` header. Free key, email only, no card:
  `curl -X POST https://api.rateapi.dev/keys -d '{"email":"you@example.com"}'`
- **Rate limits:** every response carries `RateLimit-Limit`,
  `RateLimit-Remaining`, `RateLimit-Reset` and `RateLimit-Policy`; a 429 adds
  `Retry-After` in seconds. Read them and self-throttle rather than retrying
  into the wall.

## Rules for quoting what comes back

These are not style preferences. Breaking them produces answers that are wrong
in ways a user cannot detect.

1. **Always state the observed date.** Every rate carries its own `as_of` /
   observed timestamp. A rate quoted without one reads as current forever.
2. **A median is not an average.** Benchmark figures are medians across the
   credit unions we track. Say "credit union median", never "the national
   average".
3. **Name the institution.** An APR without a lender attached is not
   actionable, and the whole point of this data is that it is attributable.
4. **Respect `rate_phase`.** Promotional and teaser rates are flagged. Present a
   teaser as a teaser or leave it out.
5. **`unknown` never means no.** On eligibility, `unknown` means the supplied
   facts could not decide the rule; the response names which input would settle
   it. Ask for that input.
6. **Never call someone ineligible.** A credit union that fails every path is
   simply absent from the response. Its absence is not a rejection, and the
   institution makes the final call regardless.
7. **Quote `reasons` verbatim.** That array is deterministic text, not prose to
   paraphrase.
8. **Distances are straight-line estimates**, from a Census ZIP centroid to a
   branch coordinate — not driving distance. `distance_method` says how each was
   computed.
9. **Do not invent fields or endpoints.** If you need something that is not in
   the OpenAPI document, it does not exist. Check `/v1/capabilities`.

## Embedding rates in a web page

If the task is "put live rates on this page", the answer is one script tag. Do
not write `fetch()`; browser calls to `rateapi.dev/api/*` return 403
cross-origin, and the authenticated API needs a key that must never appear in
client-side JavaScript.

```html
<script
  src="https://rateapi.dev/widgets/v1/embed.js"
  data-rateapi
  data-product="30-year-fixed"
  data-state="CA"
></script>
```

Attributes and variants: <https://rateapi.dev/widget-docs>

## Markdown

Every page on `rateapi.dev` answers `Accept: text/markdown` with a markdown
representation of itself, at the same URL. Prefer it over scraping HTML.

## Independence

No affiliate relationships, no lead selling, no paid placement. Results are
ranked by true cost. This is checkable:
<https://rateapi.dev/independence>.

## Where to go next

- Developer portal: <https://rateapi.dev/developers>
- Versioning & deprecation policy: <https://rateapi.dev/deprecation-policy>
- Methodology (how a rate is proven before it is served):
  <https://rateapi.dev/methodology>
- Contact a human: <https://rateapi.dev/contact>
