NestJS Swagger Docs
Swagger generates interactive API documentation automatically from your NestJS code. Instead of writing and maintaining a separate API documentation file, you add decorators to your controllers and DTOs, and Swagger produces a live, browsable documentation page that shows every endpoint, what data it accepts, what it returns, and lets you send real test requests directly from the browser.
What Swagger Gives You
Without Swagger: - Write API docs manually in Google Docs or Notion - Docs go out of sync with code changes - Frontend devs guess request/response shapes - Testing requires Postman setup per developer With Swagger: - Docs auto-generated from code annotations - Always current — changes to code update docs immediately - Interactive: test endpoints from the browser - Machine-readable OpenAPI JSON for code generators
Installing Swagger
npm install @nestjs/swagger
Setting Up Swagger in main.ts
// main.ts
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
const config = new DocumentBuilder()
.setTitle('My App API')
.setDescription('API documentation for My App')
.setVersion('1.0')
.addBearerAuth() // adds JWT Authorization header to Swagger UI
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
// Docs available at http://localhost:3000/api
await app.listen(3000);
}
Swagger UI Screenshot Description
http://localhost:3000/api shows:
MY APP API v1.0
─────────────────────────────────────────
USERS [collapse]
GET /users Get all users
POST /users Create a user
GET /users/{id} Get user by ID
PATCH /users/{id} Update a user
DELETE /users/{id} Delete a user
AUTH [collapse]
POST /auth/login Login
POST /auth/register Register
[Each endpoint is expandable → shows request body schema, response examples, and a "Try it out" button]
Controller Decorators
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
@ApiTags('users') // groups routes under "users" section
@ApiBearerAuth() // shows lock icon — JWT required
@Controller('users')
export class UsersController {
@ApiOperation({ summary: 'Get all users' })
@ApiResponse({ status: 200, description: 'Returns array of users' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
@Get()
@UseGuards(JwtAuthGuard)
findAll() { ... }
@ApiOperation({ summary: 'Get user by ID' })
@ApiResponse({ status: 200, description: 'Returns the user', type: User })
@ApiResponse({ status: 404, description: 'User not found' })
@Get(':id')
findOne(@Param('id') id: string) { ... }
}
DTO Decorators — Documenting Request Bodies
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class CreateUserDto {
@ApiProperty({
description: 'The full name of the user',
example: 'Alice Smith',
minLength: 2,
maxLength: 100,
})
@IsString()
@IsNotEmpty()
name: string;
@ApiProperty({
description: 'A valid email address',
example: 'alice@example.com',
})
@IsEmail()
email: string;
@ApiProperty({ description: 'Age in years', minimum: 1, maximum: 120, example: 30 })
@IsInt()
age: number;
@ApiPropertyOptional({ description: 'User role', enum: ['user', 'admin'], default: 'user' })
@IsOptional()
@IsString()
role?: string;
}
Response Type Annotation
@ApiResponse({
status: 201,
description: 'User created successfully',
type: UserResponseDto, // Swagger shows the response schema
})
@Post()
create(@Body() dto: CreateUserDto): Promise<UserResponseDto> {
return this.usersService.create(dto);
}
Documenting Authentication Flow in Swagger
// 1. Call POST /auth/login — copy the access_token from response // 2. Click "Authorize" button at top of Swagger UI // 3. Enter: Bearer eyJhb... // 4. Click Authorize — all locked endpoints now send the token automatically
OpenAPI JSON Export
Swagger also exposes the raw OpenAPI specification as JSON:
GET http://localhost:3000/api-json → Returns the complete OpenAPI 3.0 spec as JSON This file can be: - Imported into Postman as a collection - Used by code generators to create typed client SDKs - Uploaded to API management platforms (AWS API Gateway, Apigee) - Shared with frontend teams for automatic TypeScript type generation
Hiding Swagger in Production
// Only enable Swagger in non-production environments
if (process.env.NODE_ENV !== 'production') {
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
}
Swagger documentation transforms your API from a black box into a self-explaining, testable interface. Frontend developers stop asking "what does this endpoint return?" and start reading the docs. New team members onboard faster. API contracts get validated before any code is written. For a few lines of configuration and a handful of decorators, Swagger delivers a documentation system that stays accurate automatically because it reads directly from your code.
