The OpenAPI document and the Swagger UI that renders it.
Generated from the endpoint values, never written by hand. A checked-in spec is a second statement of the contract, and the two disagree the first time an error output is added — silently, because nothing compiles YAML. Here the document is a projection of the same Endpoints values the server routes on, so "the docs are wrong" is not a state this service can be in.
This replaced a hand-rolled walk of the Tapir endpoint ADT. That version could describe paths, methods, parameters and status codes, but it emitted permissive placeholders where the body schemas belong, because deriving a JSON Schema from Schema[T] is the hard half and tapir-openapi-docs is the thing that does it. The placeholder version documented everything except the part a client generator needs most.
Both JSON and YAML are served. They are the same document; code generators and curl | jq want the first, humans and git diff want the second, and rendering both from one model costs one line.
Swagger UI plus the two documents, as server endpoints on this service's own port.
Swagger UI plus the two documents, as server endpoints on this service's own port.
Mounted through the same Vert.x interpreter as the API rather than on a second listener: the UI's "Try it out" button issues a same-origin request, so there is no CORS configuration to get wrong and no second port to expose in compose. The trade is that the docs share the API's lifecycle — if the service is down, so are its docs, which for a document generated from the running build is the honest behaviour anyway.
The version of the API contract, which is not the build version.
The version of the API contract, which is not the build version.
ADR-adjacent decision worth stating: SERVICE_VERSION changes on every deploy, and putting it here would make every generated client look out of date after a patch release that changed nothing a client can see. This value moves when the contract moves.
Where the UI and the YAML document are mounted. /docs is the human entry point; the JSON rendering is served at the conventional root path by AdminRoutes.OpenApiPath, not from here.
Where the UI and the YAML document are mounted. /docs is the human entry point; the JSON rendering is served at the conventional root path by AdminRoutes.OpenApiPath, not from here.