**Language / Язык:** [English](api-surface.md) | [Русский](ru/api-surface.md) # API surface ## Request path 1. Middleware assigns or forwards a request ID (`REQUEST_ID_HEADER`). 2. FastAPI routes the request to the vSphere REST router (`/api`, `/rest`), the SOAP router (`/sdk`), or (if `ENABLE_PVE_STUB=true`) the optional legacy stub. 3. `/api/session` (or `/rest/com/vmware/cis/session`, or SOAP `Login`) resolves a principal and issues a `vmware-api-session-id`. 4. `require_read` / `require_privilege(...)` dependencies check the session's roles before revealing or mutating resources. 5. A deep handler (core inventory/lifecycle/tagging/content/appliance logic) or the DB-backed stub surface executes against PostgreSQL-backed state. 6. Long operations (power, clone, relocate, snapshot, OVF deploy) create a durable CIS task and return `{ "task": "task-…" }`. ## Two REST surfaces on one registry - **Core (deep) handlers** — ~104 verb+path combinations across [`app/vsphere/rest/router.py`](../app/vsphere/rest/router.py), `vm_ext.py`, `inventory_ext.py`, `platform_rest.py`, `tagging_rest.py`, `content_rest.py`, `appliance_ext.py`, `nfc_rest.py`, `tasks.py`. These read and mutate the seeded inventory/tagging/content/appliance tables directly. - **DB-backed stub surface** — [`app/vsphere/rest/stub_surface.py`](../app/vsphere/rest/stub_surface.py) answers the remaining Broadcom Automation API operations index routes (registered from `universe.json`) against `vsphere_api_state`. GET returns live inventory-derived payloads when possible, otherwise seeded rows; PUT/PATCH persist into `vsphere_api_state`; POST appends collection rows; DELETE removes them. No `"stub": true` marker is returned — probes see real seeded payloads. Both surfaces share one route table; core handlers take priority over stub entries registered for the same verb+path. ## Legacy `/rest` [`app/vsphere/rest/legacy.py`](../app/vsphere/rest/legacy.py) wraps vm/host/datastore/network/datacenter/cluster/power/appliance reads (and VM power) in `{ "value": … }` envelopes for older `com.vmware.vcenter.*` clients. ## Errors ([`app/vsphere/errors.py`](../app/vsphere/errors.py)) | Status | `error_type` | Typical cause | |---|---|---| | 400 | `invalid_argument` / `already_exists` | Malformed body, duplicate name | | 401 | `unauthenticated` | Missing/invalid/expired session | | 403 | `unauthorized` | Session lacks the required privilege | | 404 | `not_found` | Unknown MOID/path parameter | | 409 | (handler-specific) | Illegal power-state transition, lock conflict | | 501 | `error` | Only reachable via the optional legacy stub's undeclared-method fallback | All error bodies follow the vSphere Automation shape: `{ "error_type": "...", "messages": [{ "default_message": "...", "id": "...", "args": [] }] }`. ## Tasks Async work (power, clone, snapshot, relocate, OVF deploy, guest customize) returns a task id. Poll: ```text GET /api/cis/tasks/{task} ``` Task rows commit in `vsphere_tasks`; `progress` is `100` once `status` is `SUCCEEDED`/`FAILED`. HTTP 200/201 on the mutation request means "accepted", not "VM already in final state". See [Tasks](domains/tasks.md). ## Exploration - Interactive FastAPI docs: `/docs` - Web UI method inspector: `/` → catalog → method - UI helper APIs: `/ui/api/catalog`, `/ui/api/method`, `/ui/api/compatibility` - Coverage registry: [`app/vsphere/rest/coverage.py`](../app/vsphere/rest/coverage.py) - Path-floor / catalog matrix: [`app/vsphere/contracts/matrix.py`](../app/vsphere/contracts/matrix.py) ## Compatibility endpoints | Path | Format | |---|---| | `/ui/api/compatibility?major=N` | JSON | See [Compatibility](compatibility.md) and [API coverage](api-coverage.md) for the full Broadcom-universe-vs-implemented breakdown.