Skip to content

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.

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.

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.

nativeDocs also puts the contract’s routes in @fastify/swagger. The setup, with the generated contractSwaggerTransformObject, is in Fastify.

nativeDocs makes the generated routes visible to @nestjs/swagger.

Terminal window
npm install @nestjs/swagger@12.0.2

Add it to the server target, then run seampact generate (commands per stack).

artefacts:
nativeDocs: true

In 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." }

nativeDocs puts the contract’s routes in FastAPI’s own /openapi.json and /docs.

use: pypi:seampact-fastapi
artefacts:
nativeDocs: true

Run 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 document on 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: off removes FastAPI’s own /openapi.json, /docs and /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.