Docs are a work in progress - contributions welcome
Logonestjs-openapi
API Reference

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

APIDescription
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 specification
  • GET /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 UI

resolveOptions()

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); // false

ResolvedOpenApiModuleOptions

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

On this page