OpenAPI and docs
Use this page to write OpenAPI documents and to add the contract to the one your framework serves. Every key is in the Config reference.
Write OpenAPI documents
Section titled “Write OpenAPI documents”seampact generate writes one document per api, openapi/<api>.yaml by default. Choose another place, and add servers:
openapi: notes: path: docs/notes.openapi.yaml servers: - { url: "https://api.example.com", description: Production }openapi: none writes no document.
Which server serves docs
Section titled “Which server serves docs”nativeDocs keeps your framework’s own Swagger in line with the contract. Servers with no nativeDocs serve the generated OpenAPI document from a file or a route you add yourself.
| Server | nativeDocs |
Where the setup is |
|---|---|---|
| NestJS | yes | NestJS |
| Fastify | yes | Fastify |
| Spring Boot | yes (springdoc) | Spring Boot |
| FastAPI | yes | FastAPI |
| Django Ninja | yes | Django Ninja |
| Django REST Framework | no | Django REST Framework |
| Express, Hono, AdonisJS, Laravel, Symfony | no | Serve openapi/<api>.yaml yourself |
The docs routes are routes outside the contract: allow-list them with frameworkRoutes (the boot check). The examples for NestJS and Fastify follow.
Serve Swagger on Fastify
Section titled “Serve Swagger on Fastify”nativeDocs also puts the contract’s routes in @fastify/swagger. The setup, with the generated contractSwaggerTransformObject, is in Fastify.
Serve Swagger on NestJS
Section titled “Serve Swagger on NestJS”nativeDocs makes the generated routes visible to @nestjs/swagger.
npm install @nestjs/swagger@12.0.2Add it to the server target, then run seampact generate (commands per stack).
artefacts: nativeDocs: trueIn src/main.ts, add the imports and, before app.listen, these lines.
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";import * as NotesNest from "./__generated__/server/notes/index.js";
const config = new DocumentBuilder().setTitle("Notes").setVersion("1").build();const document = NotesNest.createContractDocument(app, config);
SwaggerModule.setup("docs", app, document);createContractDocument adds the contract schemas to the document, writes OpenAPI 3.1.0 and leaves out NestJS’s controller tags. It stops the app on a clash, with a message that says what to rename.
You see the Swagger page at localhost:3000/docs.
The boot check reads only the routes under the api’s paths. When the api serves routes at the root (no prefix and no mount), it reads Swagger’s routes too and stops the app with framework routes are outside the contract and not allow-listed. Then list them under frameworkRoutes of the server target:
frameworkRoutes: - { path: "/docs", reason: "Swagger UI." } - { path: "/docs/**", reason: "Swagger UI files." } - { path: "/docs-json", reason: "Swagger document." } - { path: "/docs-yaml", reason: "Swagger document." }Serve the contract in FastAPI’s docs
Section titled “Serve the contract in FastAPI’s docs”nativeDocs puts the contract’s routes in FastAPI’s own /openapi.json and /docs.
use: pypi:seampact-fastapi artefacts: nativeDocs: trueRun seampact generate. It writes native_docs.json beside the code, and bind_<api>() adds it to app.openapi().
- It needs the compiler, which writes the document. Install
seampact-ir[compiler]or the compiler binary: see install the compiler. - Name the document with
documenton the entry when the api declares several. One of them must hold every operation the entry generates (nativeDocs.document.ambiguous,artefacts.nativeDocs.operation-missing: see Generate errors). frameworkDocs: offremoves FastAPI’s own/openapi.json,/docsand/redoc.
Django Ninja takes nativeDocs the same way: bind_<api>() adds the routes to the document Ninja builds, at /openapi.json and /docs. frameworkDocs: off is refused there: build the api with NinjaAPI(docs_url=None, openapi_url=None) instead. See Django Ninja.
Django REST Framework has no nativeDocs. See FastAPI.
- Next: Monorepo, or Check it in CI.
- Every OpenAPI key: Config reference.