Swagger es una herramienta que genera documentación interactiva de tu API automáticamente. En lugar de documentar manualmente cada endpoint en un Word o Notion, Swagger lee tu código y genera una interfaz web donde cualquier developer puede ver y probar la API sin usar Postman o PowerShell
Extendiendo el proyecto de Usuario: Enlace
Podemos incluirle el Swagger para documentar la API.
instalar
npm install @nestjs/swagger
Es asi que al archivo de main.ts le voy a incluir o habilitar Swagger, hay que importar en el main y agregar las siguientes lineas
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
// Swagger
const config = new DocumentBuilder()
.setTitle('Sistema de Usuario API')
.setDescription('API para gestion de usuarios')
.setVersion('1.0')
.addTag('usuario')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
Quedando el archivo main.ts de la siguiente manera.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common'; // Validator
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // Elimina los campos que no estan en los DTOs
forbidNonWhitelisted: true, // Lanza un error si llegan campos extra
transform: true, // Transforma tipos automaticamente.
}));
// Swagger
const config = new DocumentBuilder()
.setTitle('Sistema de Usuario API')
.setDescription('API para gestion de usuarios')
.setVersion('1.0')
.addTag('usuario')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
Luego hay que decorar los DTOs, importando el ApiProperty y utilizar el decorador en cada campo con la estructura de datos con example y description.
import { IsEmail, IsNotEmpty, IsString, IsNumber, Min, Max } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty } from '@nestjs/swagger';
export class CreateUsuarioDto {
@ApiProperty({ example: 'Jefferson', description: 'Nombre del usuario'})
@IsNotEmpty({message: 'El nombre es obligatorio'})
@IsString()
nombre!: string;
@ApiProperty({ example: 'jeffsp@gmail.com', description: 'Correo del usuario'})
@IsNotEmpty()
@IsEmail({}, {message: 'Email inválido'})
email!: string;
@ApiProperty({ example: '30', description: 'Edad del usuario'})
@IsNumber()
@Min(18, {message: 'Debe de ser mayor de 18'})
@Max(99)
@Type( () => Number) //Aqui se utiliza la clase transform explicitamente.
edad!: number;
}
Finalmente, mejorar el controlador con: ApiTags, ApiOperation y ApiResponse
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { UsuarioService } from './usuario.service';
import { CreateUsuarioDto } from './dto/create-usuario.dto';
import { UpdateUsuarioDto } from './dto/update-usuario.dto';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
@ApiTags('usuario')
@Controller('usuario')
export class UsuarioController {
constructor(private readonly usuarioService: UsuarioService) {}
@ApiOperation({summary:'Crear nuevo usuario'})
@ApiResponse({status:201, description:'Usuario creado'})
@ApiResponse({status:400, description:'Datos inválidos'})
@Post()
create(@Body() createUsuarioDto: CreateUsuarioDto) {
return this.usuarioService.create(createUsuarioDto);
}
@ApiOperation({summary: 'Listar todos los usuarios'})
@ApiResponse({status:200, description:'Lista de usuarios'})
@Get()
findAll() {
return this.usuarioService.findAll();
}
@ApiOperation({summary: 'Obtener usuario por ID'})
@ApiResponse({status:200, description: 'Usuario encontrado'})
@ApiResponse({status:404, description: 'Usuario no encontrado'})
@Get(':id')
findOne(@Param('id') id: string) {
return this.usuarioService.findOne(+id);
}
@ApiOperation({summary: 'Actualizar usuario'})
@ApiResponse({status: 200, description: 'Usuario actualizado'})
@Patch(':id')
update(@Param('id') id: string, @Body() updateUsuarioDto: UpdateUsuarioDto) {
return this.usuarioService.update(+id, updateUsuarioDto);
}
@ApiOperation({summary: 'Eliminar usuario'})
@ApiResponse({status: 200, description: 'Usuario Eliminado'})
@Delete(':id')
remove(@Param('id') id: string) {
return this.usuarioService.remove(+id);
}
}
Descripción de decoradores:
- @ApiTags(‘usuario’) = Agrupa endpoints bajo una sección en la UI
- @ApiProperty() = Documenta cada campo del DTO con ejemplo
- @ApiOperation() = Describe qué hace el endpoint
- @ApiResponse() = Documenta los posibles códigos de respuesta
Ello seria suficiente para tener una API documentada.
Una vez configurado, accede a http://localhost:3000/api para ver la documentación interactiva.

¡Saludos!