OpenApiModule
NestJS module for serving OpenAPI specifications at runtime
A NestJS dynamic module for serving generated OpenAPI specifications at runtime. Optionally serves Swagger UI for interactive documentation.
Import
import { OpenApiModule } from 'nestjs-openapi';forRoot()
Configure and register the module.
Signature
class OpenApiModule {
static forRoot(options: OpenApiModuleOptions): DynamicModule;
static setup(
path: string,
app: OpenApiHttpApplication,
documentSource: OpenApiDocumentSource,
options?: OpenApiSetupOptions,
): void;
}Parameters
| API | Description |
|---|---|
OpenApiModule.forRoot(options) | Register OpenAPI routes from module-level static config |
OpenApiModule.setup(path, app, document, options) | Register OpenAPI routes during bootstrap |
OpenApiModuleOptions
interface OpenApiModuleOptions {
/**
* Path to the generated OpenAPI JSON file.
* Can be absolute or relative to process.cwd().
* @required
*/
readonly specFile: string;
/**
* Additional spec files to try when specFile is missing.
*/
readonly fallbackSpecFiles?: readonly string[];
/**
* Whether the module is enabled.
* When false, no routes are registered.
* @default true
*/
readonly enabled?: boolean;
/**
* Path where the OpenAPI JSON will be served.
* @default "/openapi.json"
*/
readonly jsonPath?: string;
/**
* Swagger UI configuration.
* - `true` - Enable with defaults (path: '/api-docs', title from spec)
* - `false` or omitted - Disable Swagger UI
* - `object` - Enable with custom configuration
* @default false
*/
readonly swagger?: boolean | SwaggerOptions;
}
interface SwaggerOptions {
/**
* Path where Swagger UI will be served.
* @default "/api-docs"
*/
readonly path?: string;
/**
* Custom title for the Swagger UI page.
* Uses spec's info.title if not provided.
*/
readonly title?: string;
}
interface OpenApiDocumentFileSource {
/**
* Path to the generated OpenAPI JSON file.
*/
readonly specFile: string;
/**
* Additional spec files to try when specFile is missing.
*/
readonly fallbackSpecFiles?: readonly string[];
}
type OpenApiDocumentSource =
| OpenApiSpec
| (() => OpenApiSpec)
| OpenApiDocumentFileSource;
interface OpenApiSetupOptions {
readonly enabled?: boolean;
readonly useGlobalPrefix?: boolean;
readonly jsonDocumentUrl?: string;
readonly ui?: boolean;
readonly raw?: boolean | readonly 'json'[];
readonly customSiteTitle?: string;
}Returns
DynamicModule - NestJS dynamic module configuration.
Example
Basic Usage
import { Module } from '@nestjs/common';
import { OpenApiModule } from 'nestjs-openapi';
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
}),
],
})
export class AppModule {}Serves the spec at GET /openapi.json.
With Swagger UI (Simple)
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
swagger: true,
}),
],
})
export class AppModule {}Creates two endpoints:
GET /openapi.json- Raw OpenAPI specificationGET /api-docs- Swagger UI interface
With Swagger UI (Custom)
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
swagger: {
path: '/docs',
title: 'My API Documentation',
},
}),
],
})
export class AppModule {}Environment-Based
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
enabled: process.env.NODE_ENV !== 'production',
swagger: process.env.SWAGGER_UI === 'true',
}),
],
})
export class AppModule {}Custom Paths
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
jsonPath: '/api/v1/openapi.json',
swagger: {
path: '/api/v1/docs',
title: 'My API v1 Documentation',
},
}),
],
})
export class AppModule {}Bootstrap-Time Configuration
Use OpenApiModule.setup() when route config comes from providers that are only available after the Nest app is created:
import { NestFactory } from '@nestjs/core';
import { OpenApiModule } from 'nestjs-openapi';
import { AppModule } from './app.module.js';
import { ConfigService } from './config.service.js';
const app = await NestFactory.create(AppModule);
const config = app.get(ConfigService);
app.setGlobalPrefix(config.baseUrl);
OpenApiModule.setup(
'/docs',
app,
{
specFile: 'apps/api/src/openapi/openapi.generated.json',
fallbackSpecFiles: ['dist/apps/api/src/openapi/openapi.generated.json'],
},
{
enabled: config.swaggerUi,
useGlobalPrefix: true,
jsonDocumentUrl: '/openapi/platform',
customSiteTitle: 'Platform API',
},
);useGlobalPrefix matches @nestjs/swagger: it prefixes the docs and JSON routes with the value passed to app.setGlobalPrefix().
Injection Tokens
The module exports two injection tokens for accessing the spec and options in your services.
OPENAPI_SPEC
Inject the loaded OpenAPI specification:
import { Injectable, Inject } from '@nestjs/common';
import { OPENAPI_SPEC } from 'nestjs-openapi';
import type { OpenApiSpec } from 'nestjs-openapi';
@Injectable()
export class ApiInfoService {
constructor(@Inject(OPENAPI_SPEC) private readonly spec: OpenApiSpec) {}
getVersion(): string {
return this.spec.info.version;
}
getEndpoints(): string[] {
return Object.keys(this.spec.paths);
}
getOperationCount(): number {
return Object.values(this.spec.paths).flatMap((methods) =>
Object.keys(methods),
).length;
}
}OPENAPI_MODULE_OPTIONS
Inject the resolved module options:
import { Injectable, Inject } from '@nestjs/common';
import { OPENAPI_MODULE_OPTIONS } from 'nestjs-openapi';
import type { ResolvedOpenApiModuleOptions } from 'nestjs-openapi';
@Injectable()
export class DocsService {
constructor(
@Inject(OPENAPI_MODULE_OPTIONS)
private readonly options: ResolvedOpenApiModuleOptions,
) {}
getDocsUrl(): string {
return this.options.swagger.enabled
? this.options.swagger.path
: this.options.jsonPath;
}
}Helper Functions
loadSpecFile()
Load an OpenAPI spec file from disk:
import { loadSpecFile } from 'nestjs-openapi';
const spec = loadSpecFile('openapi.json', {
fallbackSpecFiles: ['dist/openapi.json'],
});
console.log(spec.info.title);Throws an error if the file is not found.
generateSwaggerUiHtml()
Generate the Swagger UI HTML page:
import { generateSwaggerUiHtml } from 'nestjs-openapi';
const html = generateSwaggerUiHtml('My API', '/openapi.json');
// Returns full HTML page with Swagger UIresolveOptions()
Resolve options with defaults:
import { resolveOptions } from 'nestjs-openapi';
const options = resolveOptions({
specFile: 'openapi.json',
});
console.log(options.jsonPath); // '/openapi.json'
console.log(options.enabled); // true
console.log(options.swagger.enabled); // falseResolvedOpenApiModuleOptions
The resolved options interface with all defaults applied:
interface ResolvedOpenApiModuleOptions {
readonly specFile: string;
readonly fallbackSpecFiles: readonly string[];
readonly enabled: boolean;
readonly jsonPath: string;
readonly swagger: {
readonly enabled: boolean;
readonly path: string;
readonly title: string;
};
}Error Handling
If the spec file is not found when the module initializes:
Error: OpenAPI spec file not found: openapi.json.
Make sure to run 'nestjs-openapi generate' first.Ensure you run nestjs-openapi generate before starting your application.
Disabled Module
When enabled: false, the module returns an empty configuration:
OpenApiModule.forRoot({
specFile: 'openapi.json',
enabled: false, // No routes registered
});This is useful for conditionally disabling OpenAPI in production:
enabled: process.env.NODE_ENV !== 'production';See Also
- Serving Guide - Detailed serving configuration
- Swagger UI Recipe - Advanced Swagger UI options
- generate() - Generate the spec to serve