Docs are a work in progress - contributions welcome
Logonestjs-openapi
Guides

Serving

Serve the OpenAPI spec at runtime with OpenApiModule

While nestjs-openapi generates specs statically, you can serve the generated specification at runtime using the included OpenApiModule.

Basic Usage

import { Module } from '@nestjs/common';
import { OpenApiModule } from 'nestjs-openapi';

@Module({
  imports: [
    OpenApiModule.forRoot({
      specFile: 'openapi.json',
    }),
  ],
})
export class AppModule {}

This serves the OpenAPI spec at GET /openapi.json.

Configuration Options

OpenApiModule.forRoot({
  // Path to the generated OpenAPI JSON file (required)
  specFile: 'openapi.json',

  // Enable/disable the module (default: true)
  enabled: process.env.NODE_ENV !== 'production',

  // Path to serve the JSON spec (default: '/openapi.json')
  jsonPath: '/openapi.json',

  // Enable Swagger UI (default: false)
  swagger: true,
  // Or with custom options:
  swagger: {
    path: '/api-docs',
    title: 'My API Documentation',
  },
});

Options Reference

OptionTypeDefaultDescription
specFilestring-Path to the generated OpenAPI JSON file (required)
enabledbooleantrueWhether the module is enabled
jsonPathstring'/openapi.json'Path to serve the JSON spec
swaggerboolean | SwaggerOptionsfalseSwagger UI configuration

SwaggerOptions

OptionTypeDefaultDescription
pathstring'/api-docs'Path for Swagger UI
titlestringspec.info.titleCustom title for Swagger UI page

With Swagger UI

Serve interactive documentation with Swagger UI:

// Simple: enable with defaults
@Module({
  imports: [
    OpenApiModule.forRoot({
      specFile: 'openapi.json',
      swagger: true,
    }),
  ],
})
export class AppModule {}

// Custom: configure path and title
@Module({
  imports: [
    OpenApiModule.forRoot({
      specFile: 'openapi.json',
      swagger: {
        path: '/docs',
        title: 'My API Docs',
      },
    }),
  ],
})
export class AppModule {}

This creates two endpoints:

  • GET /openapi.json - Raw OpenAPI spec
  • GET /docs - Swagger UI interface

Swagger UI is loaded from unpkg.com CDN. No additional packages are required.

Environment-Based Configuration

Disable in production or enable based on environment:

@Module({
  imports: [
    OpenApiModule.forRoot({
      specFile: 'openapi.json',
      enabled: process.env.NODE_ENV !== 'production',
      swagger: process.env.SWAGGER_UI === 'true',
    }),
  ],
})
export class AppModule {}

When enabled is false, no routes are registered and the module is essentially a no-op.

Custom Paths

Configure custom paths for both endpoints:

@Module({
  imports: [
    OpenApiModule.forRoot({
      specFile: 'openapi.json',
      jsonPath: '/api/v1/openapi.json',
      swagger: {
        path: '/api/v1/docs',
      },
    }),
  ],
})
export class AppModule {}

File Path Resolution

The specFile is resolved relative to the current working directory (process.cwd()):

// Relative path (recommended)
specFile: 'openapi.json';

// Relative path with directory
specFile: 'src/openapi/spec.json';

// Absolute path
specFile: '/var/app/openapi.json';

The spec file must exist when the NestJS application starts. Run nestjs-openapi generate before starting your app.

Error Handling

If the spec file is not found, a helpful error is thrown:

OpenAPI spec file not found: openapi.json.
Make sure to run 'nestjs-openapi generate' first.

Injecting the Spec

You can inject the loaded spec in your services:

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) {}

  getApiVersion(): string {
    return this.spec.info.version;
  }

  getOperationCount(): number {
    return Object.values(this.spec.paths).flatMap((methods) =>
      Object.keys(methods),
    ).length;
  }
}

Available injection tokens:

  • OPENAPI_SPEC - The loaded OpenAPI specification object
  • OPENAPI_MODULE_OPTIONS - The resolved module options

Complete Example

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { OpenApiModule } from 'nestjs-openapi';

@Module({
  imports: [
    ConfigModule.forRoot(),
    OpenApiModule.forRoot({
      specFile: 'openapi.json',
      enabled: process.env.NODE_ENV !== 'production',
      jsonPath: '/api/openapi.json',
      swagger: {
        path: '/api/docs',
        title: 'My API - Interactive Documentation',
      },
    }),
  ],
})
export class AppModule {}

Workflow

The recommended workflow is:

  1. Generate the spec during build/CI:

    npm run build
    npx nestjs-openapi generate -c openapi.config.ts
  2. Commit the generated spec (optional but recommended)

  3. Serve at runtime:

    OpenApiModule.forRoot({
      specFile: 'openapi.json',
      swagger: true,
    });

Why generate at build time instead of runtime?

  • App starts faster
  • Spec works even if source files change
  • All instances serve the same spec

Alternative: Static File Serving

If you prefer not to use OpenApiModule, you can serve the spec as a static file:

import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';

@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..'),
      serveRoot: '/api',
      serveStaticOptions: {
        index: false,
      },
    }),
  ],
})
export class AppModule {}

Then access at /api/openapi.json.

Next Steps

On this page