Wire surface

The API's contract is split across two standards-based, generated artifacts, so the documentation never drifts from the code:

  • HTTP RPC (submit, query, cancel, delete, schema, build list, logs) is described by an OpenAPI 3.1 spec generated from the FastAPI app. Browse it as Swagger UI, or build the spec with nix build ./api#packages.x86_64-linux.openapi, or the interactive Swagger UI bundle with nix build ./api#packages.x86_64-linux.swagger-ui and open result/index.html.
  • Centrifugo pub/sub events (build progress, deployment-state changes) are described by an AsyncAPI 3.0 spec generated from the pydantic event models. Browse the rendered AsyncAPI docs, or build the spec with nix build ./api#packages.x86_64-linux.asyncapi-spec, or the rendered docs with nix build ./api#packages.x86_64-linux.asyncapi-docs.

CI validates both specs (api-openapi-validate, api-asyncapi-validate).

The OpenAPI spec names a real host

The OpenAPI spec carries a servers block, so Swagger UI offers a host dropdown rather than resolving calls relative to whichever static host is serving the page. The published bundle lists the production deployment and a local api-http-stack on http://127.0.0.1:8088. The production api/ allows the Swagger host as a CORS origin for exactly this, and for nothing else: it is deliberately not on the allowlist of origins api/ may call back to check authorization. A running instance overrides servers with its own domain, so /openapi.json fetched from a deployment always advertises that deployment.

Each deployment serves its own documentation pages

A hosting provider set-up serves the Swagger UI and the rendered AsyncAPI spec on names of their own on the api node, by default swagger.<apex> and asyncapi.<apex> (the swaggerDomain and asyncapiDomain options of the api component). The overview page links both. These pages document the API that the node runs. The only server of their OpenAPI spec is the domain of the node, and the origin of the Swagger UI page is in the CORS allowlist of that api/, so Try it out sends its requests to that deployment.

The name of the Centrifugo is a property of the deployment, not of api/. When the node runs Centrifugo on a public name (the eventsDomain that a front-end gives the api component), the host server variable of its AsyncAPI page has that name as its default. Otherwise, and in the asyncapi-spec and asyncapi-docs packages, the variable is the bare {host} placeholder. A build of nix/asyncapi.nix with eventsHost fills it in.

To send authorized requests from the Swagger UI, see Sending authorized requests from the Swagger UI.