nestrs-openapi discovers all routes registered through #[routes] and impl_routes!, builds an OpenAPI 3.1 document, and serves it at GET /openapi.json. A Swagger UI page is available at GET /docs. You enable the whole thing with a single method call on NestApplication — no separate server, no build step.
What is generated automatically
| Area | Behavior |
|---|---|
| Paths and HTTP methods | Auto-discovered from the RouteRegistry |
operationId | Module path + handler function name |
summary | Humanized handler name; override with #[openapi(summary = "...")] |
tags | Inferred from the first path segment; override with #[openapi(tag = "...")] |
responses | Default 200 OK; extend with #[openapi(responses = ((404, "..."), ...))] |
| Request/response schemas | Not auto-generated — hand-author components.schemas or merge from utoipa |
Step-by-step setup
Enable the feature
Add the
openapi feature to your nestrs dependency, or add nestrs-openapi directly if you need the standalone router.Call enable_openapi() before listen
Chain Your API is now self-documenting. Open
enable_openapi() on the NestApplication returned by NestFactory::create. This registers GET /openapi.json and GET /docs on the same router as your API.http://localhost:3000/docs in a browser to see the Swagger UI.Customize with OpenApiOptions
When you need to set the API title, version, server URLs, or security schemes, replaceenable_openapi() with enable_openapi_with_options(OpenApiOptions { ... }).
OpenApiOptions have defaults — use ..Default::default() and override only what you need.
Add schemas to components
nestrs-openapi does not derive request/response schemas from Rust types. Provide them manually undercomponents.schemas. The #[openapi(responses = ...)] attribute on handlers sets status codes and descriptions but not content or $ref links.
Global security scheme
Declare a security scheme undercomponents.securitySchemes and reference it in the root security array to apply it to all operations in the Swagger UI.
Per-route security from #[roles]
When handlers use#[roles("admin")], the macro stores roles metadata in MetadataRegistry. Setting infer_route_security_from_roles: true tells nestrs-openapi to add a security array to those operations automatically, so Swagger UI shows a lock icon only on protected routes.
#[roles("admin")] get "security": [{ "bearerAuth": [] }] in the generated document. Routes without #[roles] are left unchanged.
Standalone router
If you manage your own Axum router rather than usingNestApplication, import openapi_router from nestrs-openapi directly and merge the returned Router into your app.
api_prefix so the documented paths in openapi.json match the actual URLs your application serves.
Troubleshooting
| Symptom | What to check |
|---|---|
/docs or /openapi.json returns 404 | Confirm features = ["openapi"] on nestrs and that enable_openapi() is called before listen. |
| Routes missing from the document | Handlers must use #[routes] or impl_routes! to register in RouteRegistry. |
| Schemas are empty | nestrs does not infer schemas from Rust types — populate OpenApiOptions.components manually or merge a utoipa fragment. |
| Security not shown per-route | Set infer_route_security_from_roles: true and roles_security_scheme; add #[roles(...)] to the handler. |
| Paths have wrong prefix | Set api_prefix on OpenApiOptions to match your set_global_prefix and controller version. |