Skip to main content
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

Step-by-step setup

1

Enable the feature

Add the openapi feature to your nestrs dependency, or add nestrs-openapi directly if you need the standalone router.
2

Call enable_openapi() before listen

Chain enable_openapi() on the NestApplication returned by NestFactory::create. This registers GET /openapi.json and GET /docs on the same router as your API.
Your API is now self-documenting. Open http://localhost:3000/docs in a browser to see the Swagger UI.
3

Annotate routes with #[openapi]

Enrich individual handlers with a custom summary, tag, or response codes. Handlers without annotations get sensible defaults.

Customize with OpenApiOptions

When you need to set the API title, version, server URLs, or security schemes, replace enable_openapi() with enable_openapi_with_options(OpenApiOptions { ... }).
All fields on 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 under components.schemas. The #[openapi(responses = ...)] attribute on handlers sets status codes and descriptions but not content or $ref links.
If you want schemas derived from Rust types, add utoipa with its ToSchema and IntoParams derives, build a small utoipa::OpenApi fragment, serialize it to serde_json::Value, and merge it into OpenApiOptions.components. One OpenAPI document is served from nestrs; utoipa supplies the schema fragments.

Global security scheme

Declare a security scheme under components.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.
Routes with #[roles("admin")] get "security": [{ "bearerAuth": [] }] in the generated document. Routes without #[roles] are left unchanged.
infer_route_security_from_roles is a heuristic that reads metadata, not runtime guard types. Custom guards that do not set roles metadata will not trigger the security hint unless you also add #[roles(...)] or #[set_metadata("roles", "...")] on those handlers.

Standalone router

If you manage your own Axum router rather than using NestApplication, import openapi_router from nestrs-openapi directly and merge the returned Router into your app.
Set api_prefix so the documented paths in openapi.json match the actual URLs your application serves.

Troubleshooting