# CLI API reference

Integrate with the scoped VentilatePro CLI API: bearer authentication, endpoint discovery, pagination, idempotency, error handling, and MCP boundaries.

Canonical: https://ventilatepro.com/exam/cli/api/

Documentation version: VentilatePro CLI 0.8.4

## Discover the contract before building an integration

The CLI HTTP API and remote MCP are different interfaces. Use a personal CLI bearer token with `/api/cli/`. Use an MCP client with OAuth or a personal CLI bearer token with `/mcp`; that endpoint exchanges MCP protocol messages rather than accepting REST resource paths.

Start with `GET /api/cli/auth/me/`, then `GET /api/cli/schemas/` and the relevant resource list. Build requests from the returned schema and records. Keep trailing slashes on CLI API routes. Send JSON bodies with `Content-Type: application/json` where the endpoint expects JSON; uploads use their documented file contract.

Paginated lists normally return `{"count": 0, "limit": 20, "offset": 0, "results": []}`. This example is an empty page, not a live response. Consume all pages for a complete audit, preserve filters, and tolerate additional response fields. Consult the specific endpoint for detail and job-result shapes.

A scope is one authorization check; it does not replace membership, object permissions, or field validation. CLI `--yes` and MCP `confirm` are interface-level controls and are not universal HTTP headers or a guarantee that every direct REST write has the same review flow. Integrators must preserve review and approval requirements themselves.

Apply finite timeouts. For a failed write, distinguish rejection from an unknown outcome before retrying. Use `Idempotency-Key` only on supported endpoints and preserve it for the same logical operation. Never infer that a proxy endpoint is safe or supported merely because its path resembles an internal web-app route. See [scripting and pagination](https://ventilatepro.com/exam/cli/commands/#scripting-contract) and [error recovery](https://ventilatepro.com/exam/cli/troubleshooting/#recovery-reference).

## Authentication model

- Authenticate with `Authorization: Bearer <token>`.
- Idempotent create workflows such as notes and meeting recording use an `Idempotency-Key`.
- Token creation and revocation happen in the web UI account settings area.
- Scopes and project permissions are enforced for every direct or proxied request.

## Endpoints

| Method | Path | Purpose |
| --- | --- | --- |
| GET | `/api/cli/auth/me/` | Validate the token and return the current user. |
| GET | `/api/cli/schemas/` | Discover machine-readable schema metadata available to the current token. |
| GET | `/api/cli/projects/` | List accessible projects for the current user. |
| GET / POST | `/api/cli/room-equipment/` | List or create room equipment through the parent room's project access. |
| GET | `/api/cli/room-equipment/summary/?project=<id>` | Return only rooms with modeled equipment and calculated W/ft². |
| GET / PATCH / DELETE | `/api/cli/room-equipment/<id>/` | Inspect, update, or delete one equipment record. |
| GET | `/api/cli/proxy/projects/<id>/revit-imports/pending/` | Read the pending staged Revit import and its computed diff. |
| POST | `/api/cli/proxy/revit-imports/<id>/commit/` | Commit a validated pending import through an `imports:write` token. |
| GET / POST | `/api/cli/projects/<id>/categorization/<operation>/` | Review, preview, and apply guarded room categorization decisions. |
| POST | `/api/cli/notes/` | Create a note (any kind: note, meeting, call, site\_visit, agent\_session). |
| GET | `/api/cli/notes/?project=<id>&limit=<n>&offset=<n>&type=<type>&source=<source>&tag=<tag>&q=<text>` | List normalized notes with pagination, filters, and search. |
| GET | `/api/cli/notes/<note_ref>/?project=<id>` | Fetch one normalized note by typed reference. |
| ANY APPROVED | `/api/cli/proxy/<approved-path>` | Reach approved HVAC, notes, and AI routes through CLI scopes and server permissions. |

## Room equipment contract

- Every equipment record belongs to one room and inherits project access from that room.
- Heat may be entered with `heat_gain_value` plus `heat_gain_unit`: `W`, `KW`, or `BTU_H`.
- Responses include canonical watts, total quantity heat, room W/ft², environmental limits, plumbing/fuel flags, and hydronic requirements.
- Each item adds heat gain × quantity × `usage_factor` to its own room's heating and cooling loads, split by `latent_fraction`, on `schedule_id` (default `always_on_design`). Set `include_in_load_calc` to false to leave it out. Reads report the result under `load_calculation`.

## MCP proxy guardrails

- Supported targets are restricted to approved HVAC, notes, and Gemini route prefixes.
- Scope checks are derived from both HTTP method and target path.
- Broad, destructive, import, export, apply, and run tools require `confirm=true` client-side.
- The destination endpoint still performs normal serializer, validation, project-membership, and permission checks.

## Revit import contract

- Review returns room and zone changes, conflicts, import options, metadata, and a token for the exact staged revision.
- The first-class CLI and MCP confirmation commands accept no replacement payload; they commit only the reviewed session.
- A changed payload, options object, diff, status, or update timestamp invalidates the review token.
- Generic MCP request/workflow tools reject commit and discard paths so the review-token guard cannot be bypassed.
- The server repeats access, pending-status, payload-validation, and diff checks at commit time.

## Create request

```text
{
  "project": 1,
  "title": "Field Note",
  "body": "Captured from terminal.",
  "tags": ["cli", "field-note"],
  "captured_at": "2026-03-10T10:00:00-07:00"
}
```

## Normalized note response

```text
{
  "note_ref": "note:42",
  "type": "note",
  "kind": "note",
  "project_id": 1,
  "title": "Field Note",
  "body": "Captured from terminal.",
  "tags": ["cli", "field-note"],
  "source": "cli",
  "captured_at": "2026-03-10T10:00:00-07:00",
  "created_at": "2026-03-10T10:00:01-07:00",
  "updated_at": "2026-03-10T10:00:01-07:00",
  "metadata": {}
}
```

## List query parameters

| Parameter | Behavior |
| --- | --- |
| `project` | Required. Restricts reads to one project scope. |
| `limit` / `offset` | Pagination for the normalized note feed. |
| `type` | `note` or `decision`. Use `kind` to narrow notes. |
| `source` | Filter by note origin such as `cli` or `web`. |
| `tag` | Repeat the parameter or let the CLI send a comma-split tag set. |
| `q` | Free-text search over note ref, title, body, tags, and metadata strings. |

## Operational notes

- `POST /api/cli/notes/` creates notes; decisions go through the decisions endpoints.
- Idempotent retries return the original create result when the same `Idempotency-Key` is reused.
- Queueable client behavior is reserved for network failures and server 5xx responses.
- 4xx auth and validation failures must be fixed by the caller before retrying.
