# auth.md — housingsurvey.pro

Agent authentication & access metadata for **housingsurvey.pro**, following the auth.md convention (https://workos.com/auth-md). This document describes, honestly, how a person or an autonomous agent gets programmatic access to the HousingSurvey Pro REST API v1 and its MCP server. It exists so agent frameworks that probe `/.well-known/oauth-protected-resource` or similar OAuth-discovery endpoints understand what they will and will not find here, and why.

## Audience

AI agents, answer engines, and integrators connecting to HousingSurvey Pro's REST API v1 or its Model Context Protocol server.

## Connect

- REST API v1 base: `https://api.housingsurvey.pro/v1` — see [OpenAPI 3.0 spec](https://api.housingsurvey.pro/openapi.yaml) · [Swagger UI](https://housingsurvey.pro/api/docs/). Sandbox: `https://api-demo.housingsurvey.pro/v1`.
- MCP endpoint: `https://api.housingsurvey.pro/mcp` (JSON-RPC 2.0, streamable-http). Sandbox: `https://api-demo.housingsurvey.pro/mcp`.
- SCIM 2.0 provisioning (Enterprise plan): `https://api.housingsurvey.pro/scim/v2` — minted per-org in the portal, see Integrations → SCIM.
- Dispatch calendar feed (per-user iCal token): `https://api.housingsurvey.pro/calendar/feed`.
- MCP server card: `https://housingsurvey.pro/.well-known/mcp/server-card.json`.
- Agent Skills index: `https://housingsurvey.pro/.well-known/agent-skills/index.json`.
- Payments & agentic commerce: `https://housingsurvey.pro/payments.md` — this API/MCP surface is read-and-safely-act only; it has no billing routes and cannot complete a purchase (see that document for why x402/MPP/UCP/ACP/AP2 discovery documents aren't published here).

## The model: organisation-issued API keys, not OAuth

HousingSurvey Pro is a **B2B platform where the customer is the organisation** (a housing association, council or contractor firm), not an individual end user authorizing a third-party app on their own behalf. There is no concept of "a user logs into HousingSurvey Pro via a third-party app" — every API caller acts **as the organisation**, within scopes the organisation's own admin grants.

Concretely:

1. An **org-admin** signs in to the [management portal](https://portal.housingsurvey.pro) (email/password, 2FA or passkey).
2. In **Integrations → API keys**, the org-admin mints a key, choosing a label and a set of scopes (e.g. `surveys:read`, `work-orders:read`, `work-orders:write`, `properties:read`, `contractors:read`, `contractors:write`).
3. The key is shown **once**, in the form `hsp_live_…`. HousingSurvey Pro stores only its hash — the plaintext key cannot be recovered later, only revoked and reissued.
4. Every API request authenticates with:
   ```
   Authorization: Bearer hsp_live_...
   ```
5. Every scope check and every successful read is itself written to the organisation's append-only audit log — API access is evidence, the same as anything a human surveyor does.

Full endpoint reference: [OpenAPI 3.0 spec](https://api.housingsurvey.pro/openapi.yaml) · [interactive Swagger UI](https://housingsurvey.pro/api/docs/) · [developer documentation](https://housingsurvey.pro/developers/).

## OAuth Protected Resource metadata — published, but honestly scoped

`/.well-known/oauth-protected-resource` (RFC 9728) is published at
`https://housingsurvey.pro/.well-known/oauth-protected-resource`. It declares
`bearer_methods_supported: ["header"]` (every request authenticates with a
bearer token in the `Authorization` header — true) and deliberately
**omits `authorization_servers`**, because there is no delegated third-party
authorization flow to point one at:

- Nobody is granting a third-party app permission to act on their behalf
  against a shared identity provider — an org-admin mints a key directly,
  inside their own tenant's admin surface, scoped to that tenant. RFC 9728
  does not require `authorization_servers`; omitting it is the honest
  encoding of "bearer-token resource server, no OAuth authorization-code
  flow behind it" rather than inventing a token endpoint that would fail on
  first use.
- `/.well-known/openid-configuration` and `/.well-known/oauth-authorization-server`
  are **not published** for the same reason — HousingSurvey Pro is not an
  OpenID Provider or an OAuth Authorization Server. An agent that fetches
  `oauth-protected-resource` and finds no `authorization_servers` entry
  should read `resource_documentation` (this file) for the real
  provisioning flow below, rather than assume one exists.

If HousingSurvey Pro ever adds genuine third-party delegated access (e.g. a
marketplace integration acting on a customer's behalf without the customer
directly minting a key), the correct primitive at that point is OAuth 2.0
with dynamic client registration and a real `authorization_servers` entry —
not a document that pre-announces it before it exists.

## Getting a key today

1. Sign up or sign in at [portal.housingsurvey.pro](https://portal.housingsurvey.pro).
2. As an org-admin: **Settings → Integrations → API keys → New key**.
3. Choose scopes matching the integration's actual need (least privilege — a read-only CMS sync should never hold a `*:write` scope).
4. Store the key in your own secrets manager. HousingSurvey Pro cannot show it to you again.
5. Revoke and reissue at any time from the same screen; revocation takes effect immediately (the key's hash is removed from the lookup index).

## Rate limits and abuse handling

**Data-access calls** — REST API v1 (`/v1/**`) and MCP `tools/call` (any tool that requires a scope) — share **one combined budget of 240 requests/minute per organisation**. This is one counter, not two: calling both doors doesn't get you 480/minute, it gets you 240 total, however you split it between them. It's a blast-radius guard against a runaway integration or leaked key, not a product-level throttle — a well-behaved integration should never come close to it.

**Discovery calls** are not rate-limited at all: MCP's `initialize`, `ping`, `tools/list`, and the scope-free `get_contact_and_data_rights` tool. Read as many times as you like before deciding what to call.

**On breach:**
- REST API v1 returns `HTTP 429` with a JSON body `{"error": "..."}`.
- MCP returns a proper JSON-RPC 2.0 error object (not a tool-result `isError`) with `HTTP 429`.
- Both responses carry a `Retry-After` header (seconds) and standard `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset` headers (epoch seconds) — present on every data-access response, not just 429s, so a well-behaved client can back off before it ever gets rejected.

Abusive or anomalous traffic patterns beyond the rate limit may still result in key revocation. Contact support@prosurvey.app before building a high-volume integration so we can advise on pagination and polling cadence.

## Questions

- Sales/procurement: housingsurveypro@prosurvey.app
- Technical support: support@prosurvey.app
- Security disclosures: see [/.well-known/security.txt](https://housingsurvey.pro/.well-known/security.txt)
