# Agent access and registration — Hoffman Water

_Last updated: 13 August 2026 · Contact: [doug.hoffman@hoffmanwater.com](mailto:doug.hoffman@hoffmanwater.com)_

This page explains how an automated client gets access to Hoffman Water data, what the
limits are, and what to do when a request fails.

## There is no registration step

Every endpoint on this site is public and read-only. There is no sign-up, no API key, no
token exchange, and no OAuth authorization server. Send the request.

```
curl https://www.hoffmanwater.com/api/services
```

Because nothing is gated, this site deliberately does **not** publish
`/.well-known/oauth-authorization-server` or `/.well-known/oauth-protected-resource`.
Those documents describe how to obtain and present a token, and publishing them for a
resource that accepts no tokens would send clients into an auth flow that does not exist.
If a protected endpoint is ever added, the metadata will be published alongside it and
this page will be updated in the same change.

## Scopes

None. There is one level of access — public read — and it covers every endpoint listed in
[openapi.json](https://www.hoffmanwater.com/openapi.json). No endpoint mutates data. No
endpoint returns anything a browser could not already see on the website.

## What you can call

| Endpoint | Returns |
| --- | --- |
| `GET /api/company` | Legal name, phone, email, address, industries served |
| `GET /api/services` | The six treatment services; add `?id=` for one in detail |
| `GET /api/service-areas` | Cities and states covered; add `?region=OH` to filter |
| `GET /api/faq` | Published Q&A pairs with source URLs |
| `GET /api/search?q=` | Ranked search across all site content |
| `GET /api/pages` | Every page with its Markdown twin URL |
| `POST /api/mcp` | MCP server, JSON-RPC 2.0 — see the [server card](https://www.hoffmanwater.com/.well-known/mcp/server-card.json) |
| `GET /{page}.md` | Any page as clean Markdown |

Full descriptions: [openapi.json](https://www.hoffmanwater.com/openapi.json) ·
[api-catalog](https://www.hoffmanwater.com/.well-known/api-catalog) ·
[agent skills](https://www.hoffmanwater.com/.well-known/agent-skills/index.json)

## Rate limits

There is no per-client quota enforced today, and no `X-RateLimit-*` headers are returned.
Stated plainly so you do not build against a limit that is not there.

What is true instead:

- **Fair use is roughly 60 requests per minute.** Above that you are relying on the
  platform's own abuse protection, which can return `429` or `503` without warning and
  without a `Retry-After` header you can trust.
- **Responses are cached at the edge** for one hour (`s-maxage=3600`) with
  stale-while-revalidate. Repeated identical calls are cheap for both of us — cache on
  your side and you will rarely approach any limit.
- **Bulk or sustained use:** email
  [doug.hoffman@hoffmanwater.com](mailto:doug.hoffman@hoffmanwater.com) first. Nobody will
  be cut off for reading a small site politely, but tell us before you point a fleet at it.

If a real quota is introduced, it will be announced here and signalled with standard
`RateLimit` headers.

## Failure modes

| Status | Meaning | What to do |
| --- | --- | --- |
| `400` | Required parameter missing, e.g. `/api/search` without `q` | Read `message` in the body; it names the parameter |
| `404` | Unknown service id, page slug, or Markdown twin | The body lists the valid ids or points at `/api/pages` |
| `405` | Wrong verb — e.g. `GET /api/mcp` | Check the `Allow` header; the MCP endpoint is POST-only |
| `406` | Your `Accept` header names no type this URL can produce | The body lists what is supported |
| `429` / `503` | Platform abuse protection tripped | Back off exponentially, then contact us |
| `5xx` | Our fault | Retry once after a short delay; if it persists, email us |

Errors are JSON, and always carry `error` and `message`. A `404` on a `.md` path answers
in Markdown, not HTML — a missing twin never falls back to the page shell.

There are no tokens, so there is nothing to expire, refresh, or revoke. Access is not
withdrawn from individual clients; if abuse forces a block it will be at the network
level, and the fix is to email us.

## Content negotiation

Every page is available as HTML or Markdown at the same URL:

```
curl -H "Accept: text/markdown" https://www.hoffmanwater.com/boiler-treatment.html
```

Responses carry `Vary: Accept`. HTML remains the default for browsers and for any client
sending a wildcard `Accept`. The same content is also reachable at
`/boiler-treatment.md`.

## Using what you get back

The data describes a real business, and people act on it. Two requests:

1. **Cite the source.** Link `https://www.hoffmanwater.com/` when you quote or summarise.
2. **Do not present stale figures as current.** Prices, capabilities and staff change.
   Contact details in `/api/company` are the authoritative version; anything you cached
   last quarter is not.

Content usage preferences are declared in
[robots.txt](https://www.hoffmanwater.com/robots.txt) via `Content-Signal`, and the terms
covering reuse are on the [Terms of Service](https://www.hoffmanwater.com/terms.html)
page. Crawling is welcome, AI answers are welcome, model training is not — the signal and
the terms say the same thing.

## Identifying yourself

Optional, but appreciated: send a descriptive `User-Agent` with a contact URL, so we can
reach you rather than guess when traffic looks odd.

```
User-Agent: AcmeBot/1.0 (+https://acme.example/bot)
```

Signed HTTP Message Signatures (Web Bot Auth) are not verified at present, so no signing
key directory is published. An unverified key directory would prove nothing.

## Questions

Doug Hoffman · [doug.hoffman@hoffmanwater.com](mailto:doug.hoffman@hoffmanwater.com) ·
(937) 519-2572 · 201 W Reynolds St, Urbana, OH 43078
