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 and error recovery.
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 CLI note as `GeneralInfo`. |
| 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_valueplusheat_gain_unit:W,KW, orBTU_H. - Responses include canonical watts, total quantity heat, room W/ft², environmental limits, plumbing/fuel flags, and hydronic requirements.
- Equipment heat remains informational and is not added to room cooling-load calculations.
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=trueclient-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
{
"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
{
"note_ref": "general-info:42",
"type": "general-info",
"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 | One of general-info, design-minute, or decision. |
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 only CLI-backedGeneralInforecords.- Idempotent retries return the original create result when the same
Idempotency-Keyis 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.