<!-- Generated by postman/integrator_context.py — do not edit by hand. Run: python scripts/generate_integrator_context.py -->

# RELD API — integration context for AI assistants

> **Generated at:** 2026-05-28T17:18:47Z  
> **Jurisdictions with Postman examples:** 50 (50 states + PR)  
> **Hosted copy:** [https://www.realestatelicensedatabase.com/docs/RELD_API_CONTEXT.md](https://www.realestatelicensedatabase.com/docs/RELD_API_CONTEXT.md)

Paste this file into Cursor, Claude, ChatGPT, or Copilot when building against the
**Real Estate License Database (RELD)** API.

---

## 1. Source of truth (read this first)

1. **This file (`RELD_API_CONTEXT.md`)** — integration guide for coding agents: auth rules, canonical vs legacy endpoints, workflows, and pitfalls.
2. **`openapi.json`** — source of truth for exact parameters, request bodies, and response shapes. Fetch from production when implementing.
3. **Postman collection** — runnable examples; not the API contract.
4. **Marketing site copy** — orientation only; never treat website examples as the contract.

Do **not** invent endpoints, fields, request bodies, or response shapes.

OpenAPI (schemas): [https://app.realestatelicensedatabase.com/openapi.json](https://app.realestatelicensedatabase.com/openapi.json)

---

## 2. Product summary

RELD is a REST API over normalized U.S. real estate **licensee** records from official
state and territory sources. Typical uses:

- Agent/broker **license verification** at onboarding
- **Search** by name, brokerage, city, status, license type
- **Batch verify** up to 100 licenses per request
- **Supervision / affiliation** lookups where the source publishes relationships (CA-rich)

Production base URL: `https://app.realestatelicensedatabase.com`

---

## 3. Canonical licensee API

Use the **`/api/v1/licensees` endpoint family** as the canonical API for licensee search, verification, batch verification, affiliations, supervisors, and affiliates.

- **`GET /api/v1/licensees`** is the preferred search endpoint (requires `state`).
- **`GET /api/v1/licensees/search`** is legacy / backward-compatible only — omit `name`, `brokerage`, and `license_type` filters. New integrations should not use it unless a downstream system already depends on separate `first_name` / `last_name` parameters.
- Prefer **`GET /api/v1/licensees/{state}/{license_number}/supervisors`** over the legacy singular **`/supervisor`** path.
- **`GET /api/v1/licensees/changes`** is a reserved stub — do not build sync jobs on it yet.

**Start here for new integrations:**

| Method | Path | Purpose |
|--------|------|---------|
| GET | `/api/v1/coverage` | Public coverage metadata (no API key) |
| GET | `/api/v1/licensees` | Search licensees |
| GET | `/api/v1/licensees/verify` | Verify one license |
| POST | `/api/v1/licensees/batch` | Batch verify (≤100) |
| GET | `/api/v1/licensees/{state}/{license_number}/supervisors` | Current supervisors |


---

## 4. Quick start

1. Sign up at `https://app.realestatelicensedatabase.com/dashboard/signup`
2. Create an API key at `https://app.realestatelicensedatabase.com/dashboard/api-keys` (raw key shown **once**)
3. Send `Authorization: Bearer <raw_key>` on authenticated calls (not `X-API-Key`)
4. Smoke-test:

Run in order when validating a new integration:

1. `GET https://app.realestatelicensedatabase.com/health` — no auth
2. `GET https://app.realestatelicensedatabase.com/api/v1/account` — `Authorization: Bearer <key>`
3. `GET https://app.realestatelicensedatabase.com/api/v1/licensees?state=TX&name=Smith&page=1&per_page=25` — `Authorization: Bearer <key>`
4. `GET https://app.realestatelicensedatabase.com/api/v1/licensees/verify?state=TX&license_number=9001878` — `Authorization: Bearer <key>`

---

## 5. Authentication and metering

- **Bearer only:** `Authorization: Bearer rel_…` (or your key prefix)
- **Public (no Bearer):** `/health`, `/api/v1/coverage`, `/openapi.json`, `/docs`
- **Unmetered** (Bearer required but does not count toward monthly usage): `/api/v1/account/usage`, `/api/v1/coverage`, `/api/v1/sources/coverage`
- All other `/api/v1/*` routes require a valid key and count toward plan limits

### Error responses

**401** example:

```json
{
  "detail": "Missing API key"
}
```

**402** example:

```json
{
  "detail": "Subscription required",
  "subscription_status": "past_due"
}
```

**429** example:

```json
{
  "detail": "Monthly API usage limit exceeded",
  "limit": 10000,
  "current_usage": 10001,
  "year_month": "2026-05"
}
```

**503** example:

```json
{
  "detail": "Database connection pool exhausted. Please retry shortly."
}
```

**404** — `{detail: "Licensee not found"}` on canonical lookup misses.

**422** — validation errors (e.g. `GET /api/v1/licensees` without required `state`).

---

## 6. Endpoint map (curated)

| Method | Path | Auth | Params | Notes |
|--------|------|------|--------|-------|
| GET | `/health` | public | — | Liveness: `{status, commit}`. No auth. |
| GET | `/api/v1/coverage` | public | — | Per-state record counts and freshness. No auth. |
| GET | `/api/v1/account` | bearer | — | Verify API key; returns `{id, name, is_active}`. |
| GET | `/api/v1/account/usage` | bearer (unmetered) | — | Monthly request totals by `year_month`. |
| GET | `/api/v1/licensees` | bearer | state (required), name, first_name, last_name, business_name, status, license_type, brokerage, city, page, per_page | Primary search. `{data: [licensee...], meta: {total, page, per_page}}`. per_page max 100. |
| GET | `/api/v1/licensees/search` | bearer | state, first_name, last_name, … | **Legacy** — backward-compatible only; prefer `GET /api/v1/licensees`. |
| GET | `/api/v1/licensees/verify` | bearer | state, license_number | Always 200: `{verified, licensee}`. Prefer over 404 for verification UX. |
| POST | `/api/v1/licensees/batch` | bearer | body: `{licenses: [{state, license_number}]}` (1–100 items) | Batch verify; `{data: [{state, license_number, verified, licensee}]}` in input order. |
| GET | `/api/v1/licensees/{state}/{license_number}` | bearer | path: state, license_number | Exact lookup. 404 if not found. `{data: licensee}`. |
| GET | `/api/v1/licensees/{state}/{license_number}/affiliations` | bearer | include_inactive, as_of, affiliate_role, relationship_type | Supervisor history. CA-rich; other states often `data: []`. |
| GET | `/api/v1/licensees/{state}/{license_number}/supervisors` | bearer | affiliate_role, relationship_type (optional) | All open supervisors (recommended). Empty list, not 404, when none. |
| GET | `/api/v1/licensees/{state}/{license_number}/supervisor` | bearer | — | **Legacy** — single supervisor; prefer `GET .../supervisors`. |
| GET | `/api/v1/licensees/{state}/{license_number}/affiliates` | bearer | page, per_page, filters | Roster of licensees supervised by this broker. |
| GET | `/api/v1/licensees/changes` | bearer | — | **Reserved stub** — empty `data`; not for production sync. |
| GET | `/api/v1/licenses/search` | bearer | state, license_number, first_name, last_name, … | Legacy flat license rows; no affiliation fields. |
| GET | `/api/v1/licenses/{state}/{license_number}` | bearer | path | Legacy lookup; `{data: null}` when missing (not 404). |
| GET | `/api/v1/licenses/license-type-counts` | bearer | state (optional) | Population breakdown by license type per state. |
| GET | `/api/v1/license-credentials/{credential_id}/hierarchy` | bearer | path: credential UUID from search `id` | Supervision chain for normalized graph. |
| GET | `/api/v1/states` | bearer | — | Active jurisdictions `[{abbreviation, name, is_active}]`. |
| GET | `/api/v1/sources` | bearer | — | Ingestion source status per state. |
| GET | `/api/v1/sources/coverage` | bearer (unmetered) | — | Legacy coverage shape `{states: [{state, status}]}`. |
| GET | `/api/v1/readiness` | bearer | — | Authenticated health: DB + data sanity checks. |
| POST | `/api/v1/api-keys` | bearer | body: `{label?}` | Create key; raw `key` returned once. |
| GET | `/api/v1/api-keys` | bearer | — | List keys (prefix only, not secret). |
| DELETE | `/api/v1/api-keys/{key_id}` | bearer | path: key_id | Revoke a key. |

For exhaustive path/query schemas, use OpenAPI. Per-state runnable examples live in the
Postman collection folder **5. States**.

### Canonical vs legacy

### Licensee family vs legacy `/licenses` routes

| Topic | Prefer (`/api/v1/licensees` family) | Legacy (`/api/v1/licenses`) |
|-------|--------------------------------------|-----------------------------|
| Search | `GET /api/v1/licensees` | `GET /api/v1/licenses/search` (flat rows) |
| Lookup miss | 404 on `/licensees/{state}/{n}` | `{data: null}` on `/licenses/{state}/{n}` |
| Verify | `GET /api/v1/licensees/verify` | No dedicated verify |
| Fields | `supervising_brokerages`, `current_affiliate_roles`, `last_verified` | Not included |

| Endpoint | Status | Guidance |
|----------|--------|----------|
| `GET /api/v1/licensees/search` | Legacy | Backward-compatible only; use `GET /api/v1/licensees` for new code |
| `GET /api/v1/licensees/{state}/{license_number}/supervisor` | Legacy | Single supervisor; prefer `/supervisors` |
| `GET /api/v1/licensees/changes` | Reserved stub | Empty `data` today — not for production sync |


### Search and verify (detail)

Canonical state-agnostic endpoints. Pass a 2-letter `state` and the API routes to the right per-state adapter under the hood. These are the endpoints integrators should call from production code; the per-state examples in folder 5 are for exploration only.

### Affiliations

Broker → salesperson supervision and affiliation history. California is the only jurisdiction with rich data today (DRE publishes a bipartite licensee/affiliation feed). Other states return an empty list rather than 404, so a frontend can render "no affiliations on file" uniformly.

**Two flavors of "current supervisor":**
- `/supervisor` (singular) — legacy view, returns the single most recent open relationship. Use for backward compat only.
- `/supervisors` (plural) — recommended. Returns *all* currently open supervisor relationships, important for CA broker-associates who can be supervised by multiple responsible brokers simultaneously.

### Coverage metadata

Programmatic coverage metadata. Use these when surfacing "what data do you have?" in your own UI. The `Coverage (programmatic)` endpoint is intentionally unauthenticated so it can be used in marketing pages.

---

## 7. Public licensee object

Each search/verify/lookup row uses this shape:

| Field | Type / notes |
|-------|----------------|
| `id` | UUID string for the license credential (use with hierarchy endpoint). |
| `full_name` | Display name; business_name if set, else first + last. |
| `license_number` | State-issued license number (natural key with state). |
| `license_type` | Normalized type, title-cased (e.g. Broker, Salesperson). |
| `status` | Normalized status, title-cased (e.g. Active, Inactive). |
| `state` | Two-letter jurisdiction code. |
| `expiration_date` | ISO date (YYYY-MM-DD) or null. |
| `brokerage` | Primary supervising brokerage name, or null. |
| `supervising_brokerages` | List of current supervising brokerage names. |
| `current_affiliate_roles` | List of current affiliate role codes (CA-rich). |
| `last_verified` | ISO-8601 UTC timestamp when RELD last saw this row in source data. |
| `first_name` | Individual first name, or null for pure business licenses. |
| `last_name` | Individual last name, or null. |
| `business_name` | Registered business name, or null. |
| `city` | City when published by the source; null in many jurisdictions. |

---

## 8. Workflow recipes

### Onboard an agent (verify license)

```bash
curl -sS "https://app.realestatelicensedatabase.com/api/v1/licensees/verify?state=TX&license_number=9001878" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Expect `{"verified": true, "licensee": {...}}` or `verified: false` with `licensee: null`.

### Nightly batch verification (max 100 per request)

```bash
curl -sS -X POST "https://app.realestatelicensedatabase.com/api/v1/licensees/batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"licenses": [{"state": "TX", "license_number": "9001878"}, {"state": "CA", "license_number": "00006213"}]}'
```

### Search by name and brokerage

```bash
curl -sS "https://app.realestatelicensedatabase.com/api/v1/licensees?state=NY&name=johnson&brokerage=coldwell&status=active&page=1&per_page=25" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Affiliation check (CA example)

```bash
curl -sS "https://app.realestatelicensedatabase.com/api/v1/licensees/CA/00006213/supervisors" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Empty `data: []` is normal outside California; do not treat as an error.

---

## 9. Coverage and data expectations

- Live coverage: `GET https://app.realestatelicensedatabase.com/api/v1/coverage` (public)
- **50** jurisdictions have curated Postman examples; coverage metadata lists live vs planned
- **Affiliations:** California has rich supervisor/affiliate data; most states return `data: []`
- **`GET /api/v1/licensees/changes`:** reserved stub — do not build sync jobs against it yet
- City/address availability varies by state (see operator doc `docs/address-coverage.md` in the app repo)

---

## 10. Billing and account boundaries

- Self-serve **checkout** and **customer portal:** use the **dashboard** at
  `https://app.realestatelicensedatabase.com/dashboard/billing`, not as the primary integrator path
- `POST /api/v1/billing/checkout` and `POST /api/v1/billing/portal` exist but require an
  API key first; most customers manage billing in the browser UI
- API keys: dashboard UI or `POST /api/v1/api-keys` / `GET /api/v1/api-keys` / `DELETE /api/v1/api-keys/{id}`

---

## 11. Out of scope for customer integrations

Do **not** use these in production customer apps:

- `/dashboard/*` — HTML session UI (signup, billing, key management)
- `/api/v1/admin/*` — cookie `dashboard_session` + platform admin only
- `POST /webhooks/stripe` — Stripe billing webhooks, not data access

---

## 12. Authoritative references

| Resource | URL |
|----------|-----|
| Integration guide (this file) | https://www.realestatelicensedatabase.com/docs/RELD_API_CONTEXT.md |
| OpenAPI (schemas) | https://app.realestatelicensedatabase.com/openapi.json |
| Swagger UI | https://app.realestatelicensedatabase.com/docs |
| Postman collection | https://www.realestatelicensedatabase.com/postman/License_API.postman_collection.json |
| Developer hub | https://www.realestatelicensedatabase.com/developers/ |
| LLM discovery index | https://www.realestatelicensedatabase.com/llms.txt |
| Contact | https://www.realestatelicensedatabase.com/contact/ |
| Email | support@realestatelicensedatabase.com |

---

## 13. Suggested prompt for your AI tool

```
Integrate our application with the RELD API using RELD_API_CONTEXT.md (https://www.realestatelicensedatabase.com/docs/RELD_API_CONTEXT.md).
Use the /api/v1/licensees endpoint family as the canonical API (GET /api/v1/licensees for search).
Do not invent endpoints, fields, or response shapes. For exact schemas, use https://app.realestatelicensedatabase.com/openapi.json.
Auth: Authorization: Bearer <api_key>. Do not use legacy /licensees/search unless required.
```

---

*Postman for trying requests; this file for building with AI.*
