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

Decorators

Supported NestJS and Swagger decorators

The generator covers the most common NestJS + Swagger decorators. Schemas come from TypeScript types (not @ApiProperty); security schemes are defined in config and decorators add per-operation requirements.

Quick truth table: we read routing + HTTP method decorators, Swagger operation metadata (tags, operation, consumes/produces, ApiResponse), parameter descriptions from @ApiParam/@ApiQuery, and method-level exclusion decorators. We ignore property-level Swagger decorators and response shortcuts.

For a concise overview, see the Support Matrix.

Routing Decorators

Controller

@Controller('users')
export class UsersController {
  // All routes prefixed with /users
}

Controller versioning (@Controller({ path: 'users', version: '1' })) is not currently supported. We only read the string path.

HTTP Method Decorators

Standard HTTP method decorators are supported:

@Controller('users')
export class UsersController {
  @Get()
  findAll() {}

  @Get(':id')
  findOne(@Param('id') id: string) {}

  @Post()
  create(@Body() dto: CreateUserDto) {}

  @Put(':id')
  replace(@Param('id') id: string, @Body() dto: UpdateUserDto) {}

  @Patch(':id')
  update(@Param('id') id: string, @Body() dto: PatchUserDto) {}

  @Delete(':id')
  remove(@Param('id') id: string) {}
}

@Options() and @Head() are also supported. @All() is mapped to an all operation, which is not a standard OpenAPI method - prefer explicit verbs if you need strict validation.

Parameter Decorators

@Get(':id')
findOne(
  @Param('id') id: string,                    // Path parameter
  @Query('include') include?: string,         // Query parameter
  @Headers('authorization') auth: string,     // Header parameter
) {}

@Post()
create(
  @Body() dto: CreateUserDto,                 // Request body
) {}

Response Status

@Post()
@HttpCode(201)
create(@Body() dto: CreateUserDto) {}

@Delete(':id')
@HttpCode(204)
remove(@Param('id') id: string) {}

Swagger Decorators

@ApiTags

Assigns tags to controller endpoints:

@ApiTags('users')
@Controller('users')
export class UsersController {
  // All endpoints tagged with 'users'
}

// Multiple tags
@ApiTags('users', 'admin')
@Controller('admin/users')
export class AdminUsersController {}

@ApiOperation

Describes an operation:

@Get()
@ApiOperation({
  summary: 'List all users',
  description: 'Returns a paginated list of users',
  operationId: 'listUsers',
  deprecated: false,
})
findAll() {}
PropertyOpenAPI Field
summarysummary
descriptiondescription
operationIdoperationId
deprecateddeprecated

@ApiParam

Documents path parameters:

@Get(':id')
@ApiParam({
  name: 'id',
  description: 'User ID',
  type: String,
  required: true,
  example: '123e4567-e89b-12d3-a456-426614174000',
})
findOne(@Param('id') id: string) {}

@ApiQuery

Documents query parameters:

@Get()
@ApiQuery({
  name: 'page',
  description: 'Page number',
  type: Number,
  required: false,
  example: 1,
})
@ApiQuery({
  name: 'limit',
  description: 'Items per page',
  type: Number,
  required: false,
  example: 10,
})
findAll(
  @Query('page') page?: number,
  @Query('limit') limit?: number,
) {}

Query DTOs

When using @Query() without an explicit parameter name, DTO class properties are expanded into individual query parameters by default:

// DTO definition
class PaginationDto {
  page?: number;
  limit?: number;
}

// Controller
@Get()
findAll(@Query() pagination: PaginationDto) {}

// Generated OpenAPI parameters:
// - page (query, optional)
// - limit (query, optional)

This is a common OpenAPI style and works better with code generators. If you prefer to keep the DTO as a single schema reference, set query.style: "ref" in your config. See the Configuration Guide for details.

Explicitly named query params like @Query('filter') filter: FilterDto always use a schema reference, regardless of the query.style setting.

@ApiBody

Documents the request body:

@Post()
@ApiBody({
  description: 'User creation data',
  type: CreateUserDto,
  required: true,
})
create(@Body() dto: CreateUserDto) {}

@ApiResponse

Documents responses. The status property is required and we read description, type, and array forms (type: [UserDto]). Shortcut helpers like @ApiOkResponse are not read; use @ApiResponse directly.

@Get(':id')
@ApiResponse({
  status: 200,
  description: 'User found',
  type: UserDto,
})
@ApiResponse({
  status: 404,
  description: 'User not found',
})
findOne(@Param('id') id: string) {}

The status property is required for @ApiResponse. Responses without a status are ignored.

Response Shortcuts

Response shortcut decorators (@ApiOkResponse, @ApiCreatedResponse, etc.) are not currently supported. Use @ApiResponse with an explicit status property instead.

// Instead of @ApiOkResponse({ description: 'Success', type: UserDto })
// Use:
@ApiResponse({ status: 200, description: 'Success', type: UserDto })

// Instead of @ApiCreatedResponse({ description: 'Created', type: UserDto })
// Use:
@ApiResponse({ status: 201, description: 'Created', type: UserDto })

// Instead of @ApiNotFoundResponse({ description: 'Not found' })
// Use:
@ApiResponse({ status: 404, description: 'Not found' })

@ApiConsumes and @ApiProduces

Specify content types:

@Post('upload')
@ApiConsumes('multipart/form-data')
uploadFile(@Body() dto: FileUploadDto) {}

@Get('report')
@ApiProduces('application/pdf')
getReport() {}

@ApiExcludeEndpoint

Exclude endpoints from the generated spec:

@Get('health')
@ApiExcludeEndpoint()
healthCheck() {}

This is controlled by the excludeDecorators option:

// openapi.config.ts
options: {
  excludeDecorators: ['ApiExcludeEndpoint'],
}

excludeDecorators matches method decorators only. To exclude an entire controller, apply a decorator to each method or use a path filter.

DTO Schema Generation

Schemas are generated from TypeScript types, not @nestjs/swagger decorators. The library uses ts-json-schema-generator to analyze your DTO classes and interfaces.

How Schemas Work

The library generates JSON Schema definitions by analyzing TypeScript source files:

// TypeScript types are converted to JSON Schema
export class CreateUserDto {
  email: string; // → { "type": "string" }
  age?: number; // → { "type": "number" } (optional)
  roles: string[]; // → { "type": "array", "items": { "type": "string" } }
}

Adding Descriptions with JSDoc

Use JSDoc comments to add descriptions to your schemas:

export class CreateUserDto {
  /** User email address */
  email: string;

  /**
   * User age in years
   * @minimum 0
   * @maximum 150
   */
  age?: number;
}

class-validator Integration

If you enable extractValidation: true, the library extracts constraints from class-validator decorators:

export class CreateUserDto {
  @IsEmail()
  email: string; // → { "type": "string", "format": "email" }

  @Min(0)
  @Max(150)
  age?: number; // → { "type": "number", "minimum": 0, "maximum": 150 }

  @MinLength(1)
  @MaxLength(100)
  name: string; // → { "type": "string", "minLength": 1, "maxLength": 100 }
}

See the Validation Guide for details.

Unsupported DTO Decorators

The following @nestjs/swagger property decorators are not supported:

  • @ApiProperty() - Use TypeScript types and JSDoc instead
  • @ApiPropertyOptional() - Use optional properties (?) instead
  • @ApiHideProperty() - Not supported

Type Inference

The library infers types from TypeScript when possible:

@Controller('users')
export class UsersController {
  // Return type inferred from method signature
  @Get()
  findAll(): Promise<UserDto[]> {
    return this.service.findAll();
  }

  // Parameter types inferred from decorators
  @Get(':id')
  findOne(@Param('id') id: string): Promise<UserDto> {
    return this.service.findOne(id);
  }
}

For best results, always specify explicit return types on controller methods and use typed DTOs for request bodies.

Security Decorators

Security decorators are fully supported at both controller and method level:

@Controller('users')
@ApiBearerAuth() // Applied to all methods
export class UsersController {
  @Get()
  findAll() {} // Inherits @ApiBearerAuth

  @Get(':id')
  @ApiOAuth2(['read:users']) // Method-level override
  findOne(@Param('id') id: string) {}

  @Delete(':id')
  @ApiBearerAuth('jwt')
  @ApiSecurity('admin-key') // Multiple schemes (AND logic)
  remove(@Param('id') id: string) {}
}

Supported Security Decorators

DecoratorDefault NameNotes
@ApiBearerAuth(name?)'bearer'HTTP Bearer (JWT)
@ApiBasicAuth(name?)'basic'HTTP Basic auth
@ApiOAuth2(scopes[], name?)'oauth2'OAuth2 with scopes
@ApiSecurity(name, scopes?)-Generic security scheme
@ApiCookieAuth(name?)'cookie'Cookie-based auth

Behavior

  • Controller-level: Applies to all methods in the controller
  • Method-level: Overrides controller-level security
  • Multiple decorators: AND logic (all schemes required)
  • Merge with config: Global security from config is merged into per-operation requirements; if both are present, all schemes are required

Security schemes must still be defined in config. Decorators reference scheme names defined in openapi.security.schemes.

See the Security Guide for complete configuration options.

Unsupported Decorators

The following @nestjs/swagger decorators are not currently supported:

Response Shortcuts

  • @ApiOkResponse() - Use @ApiResponse({ status: 200, ... })
  • @ApiCreatedResponse() - Use @ApiResponse({ status: 201, ... })
  • @ApiAcceptedResponse() - Use @ApiResponse({ status: 202, ... })
  • @ApiNoContentResponse() - Use @ApiResponse({ status: 204, ... })
  • @ApiBadRequestResponse() - Use @ApiResponse({ status: 400, ... })
  • @ApiUnauthorizedResponse() - Use @ApiResponse({ status: 401, ... })
  • @ApiForbiddenResponse() - Use @ApiResponse({ status: 403, ... })
  • @ApiNotFoundResponse() - Use @ApiResponse({ status: 404, ... })
  • @ApiConflictResponse() - Use @ApiResponse({ status: 409, ... })
  • @ApiInternalServerErrorResponse() - Use @ApiResponse({ status: 500, ... })

Property Decorators

  • @ApiProperty() - Use TypeScript types and JSDoc
  • @ApiPropertyOptional() - Use optional properties (?)
  • @ApiHideProperty() - Not supported

Other

  • @ApiExtension() - Custom extensions
  • Controller versioning - @Controller({ path, version }) object syntax

Next Steps

On this page