OpenAPI & Swagger

Self-Documenting APIs From Your Decorators

OpenAPI & Swagger

`@nestjs/swagger` reads your controllers and DTOs and generates an interactive OpenAPI documentation page. Almost no extra effort.

4 min read Level 2/5 #nestjs#openapi#swagger
What you'll learn
  • Install @nestjs/swagger
  • Set up SwaggerModule in main.ts
  • Annotate controllers and DTOs

Half the value of writing typed DTOs and decorated controllers is that something can generate API documentation from them. @nestjs/swagger does exactly that — it produces an OpenAPI spec and a Swagger UI page with very little extra code.

Install

npm i @nestjs/swagger

Hook It Into main.ts

import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('My API')
    .setVersion('1.0')
    .addBearerAuth()
    .build();

  const doc = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('docs', app, doc);

  await app.listen(3000);
}
bootstrap();

Visit http://localhost:3000/docs and you’ll see an interactive UI listing every route — with “Try it out” buttons that actually call your API.

Decorate Controllers and DTOs

The generator infers what it can from TypeScript, but explicit decorators give richer docs.

import { ApiTags, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';

@ApiTags('users')
@ApiBearerAuth()
@Controller('users')
export class UsersController {
  @Get(':id')
  @ApiResponse({ status: 200, type: UserDto })
  @ApiResponse({ status: 404, description: 'User not found' })
  findOne(@Param('id') id: string) { /* ... */ }
}
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsString } from 'class-validator';

export class CreateUserDto {
  @ApiProperty({ example: 'a@b.com' })
  @IsEmail()
  email: string;

  @ApiProperty({ minLength: 2 })
  @IsString()
  name: string;
}

class-validator rules feed into the spec automatically — minLength, required, format — so consumers see the same constraints the server enforces.

Adding @ApiProperty() to every field gets old. Turn on the Swagger CLI plugin and it’ll infer them from your TypeScript types.

// nest-cli.json
{
  "compilerOptions": {
    "plugins": ["@nestjs/swagger"]
  }
}

With this on, plain TypeScript classes generate accurate schemas. You still add decorators for examples, descriptions, or overriding types — but you skip the boilerplate.

Exporting the Spec

Want to share the OpenAPI JSON with a frontend team or feed it to a client generator?

import { writeFileSync } from 'fs';
writeFileSync('./openapi.json', JSON.stringify(doc, null, 2));

Drop that into your build and tools like openapi-typescript will give your frontend fully-typed API clients for free.

WebSockets With Socket.IO →