<link rel="stylesheet" href="styles-3GBANQL6.css">
← Back to blog

NestJS

NestJS Swagger API Documentation

NestJS Swagger API Documentation

Introduction

In the world of API development, clear and comprehensive documentation is crucial. It not only helps developers understand how to interact with your API but also serves as a contract between your backend and frontend teams. NestJS, a powerful Node.js framework, integrates seamlessly with Swagger to generate beautiful and interactive API documentation. In this blog post, we'll explore tips and tricks to make the most of NestJS Swagger, including practical examples to illustrate each point.

Setting Up Swagger in Your NestJS Project

First things first: let’s set up Swagger in your NestJS application. If you haven’t done so already, install the necessary packages:

npm install --save @nestjs/swagger swagger-ui-express

Next, you can configure Swagger in your main application file:


import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

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

  const config = new DocumentBuilder()
    .setTitle('My API')
    .setDescription('The API description')
    .setVersion('1.0')
    .addTag('cats')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);

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

This setup will expose your API documentation at http://localhost:3000/api. Now let’s explore how to enhance this documentation further.

Using Decorators to Enhance Your Endpoints

One of the most powerful features of NestJS Swagger is the ability to use decorators to enrich your API endpoints. These decorators help you define the metadata that Swagger uses to generate documentation.

For example, consider the following controller:


import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { ApiTags, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';

class CreateCatDto {
  name: string;
  age: number;
}

@ApiTags('cats')
@Controller('cats')
export class CatsController {
  private cats = [];

  @Post()
  @ApiBody({ type: CreateCatDto })
  @ApiResponse({ status: 201, description: 'Cat created successfully' })
  createCat(@Body() createCatDto: CreateCatDto) {
    this.cats.push(createCatDto);
    return { message: `Cat ${createCatDto.name} added!` };
  }

  @Get(':id')
  @ApiResponse({ status: 200, description: 'The found record' })
  @ApiResponse({ status: 404, description: 'Cat not found' })
  @ApiParam({ name: 'id', required: true, description: 'Cat ID' })
  getCat(@Param('id') id: string) {
    const cat = this.cats.find(c => c.name === id);
    if (!cat) {
      throw new NotFoundException(`Cat with ID ${id} not found`);
    }
    return cat;
  }
}
    

In this example:

  • @ApiTags categorizes the endpoints in the documentation, making it easier for users to navigate.
  • @ApiResponse provides information about the possible HTTP responses, enhancing the clarity of your API.
  • @ApiParam describes the parameters accepted by the endpoint.
  • @ApiBody specifies the expected structure of the request body using a Data Transfer Object (DTO).

Documenting Request Bodies and Query Parameters

To make your API more user-friendly, it’s important to document request bodies and query parameters. Use the @ApiBody and @ApiQuery decorators to achieve this:


import { Controller, Post, Body, Query } from '@nestjs/common';
import { ApiBody, ApiQuery } from '@nestjs/swagger';

class CreateCatDto {
  name: string;
  age: number;
}

@Controller('cats')
export class CatsController {
  private cats = [];

  @Post()
  @ApiBody({ type: CreateCatDto })
  createCat(@Body() createCatDto: CreateCatDto) {
    this.cats.push(createCatDto);
    return `Cat ${createCatDto.name} added!`;
  }

  @Get()
  @ApiQuery({ name: 'age', required: false, description: 'Filter cats by age' })
  findCats(@Query('age') age: number) {
    return age
      ? this.cats.filter(cat => cat.age === age)
      : this.cats;
  }
}
    

In this snippet:

  • @ApiBody specifies the expected structure of the request body using a Data Transfer Object (DTO).
  • @ApiQuery documents the query parameters, improving the API's usability.

Testing API Requests through Swagger UI

One of the great advantages of using Swagger UI is the ability to test your API endpoints directly through the interface. Here’s how you can do this:

Sending a POST Request

1. Navigate to the Swagger UI at http://localhost:3000/api.

2. Find the Create Cat endpoint under the cats tag.

3. Click on the endpoint, then click on Try it out.

4. Enter the following JSON in the request body:


{
  "name": "Fluffy",
  "age": 3
}
    

5. Click Execute to send the request. You should receive a response indicating that the cat has been added successfully.

Sending a GET Request

1. Under the same Swagger UI, find the Get Cat endpoint.

2. Click on the endpoint and then click on Try it out.

3. Enter the cat’s name (e.g., Fluffy) in the parameter field.

4. Click Execute to fetch the cat's information. If the cat exists, you should see the cat's details in the response.

5. If you enter a name that doesn't exist, you will receive a 404 error message indicating that the cat was not found.

Grouping Endpoints with Tags

Organizing your API endpoints into logical groups makes documentation easier to navigate. You can use tags to categorize endpoints. For example:


@ApiTags('cats')
@Controller('cats')
export class CatsController {
  // endpoint definitions...
}

@ApiTags('dogs')
@Controller('dogs')
export class DogsController {
  // endpoint definitions...
}
    

This way, users can quickly find all related endpoints under a specific tag in the Swagger UI. Tags can also provide additional context or functionality, such as versioning.

Customizing Swagger UI

Swagger allows for some customization of the UI, which can enhance the user experience. You can add custom CSS or JavaScript by modifying the Swagger setup:


SwaggerModule.setup('api', app, document, {
  swaggerOptions: {
    docExpansion: 'full',
    presets: [
      SwaggerModule.Preset.redoc,
      SwaggerModule.Preset.swagger,
    ],
  },
});
    

In this setup, we define how the documentation should expand and the presets used to display it, allowing you to tailor the Swagger UI to your specific needs.

Conclusion

Effective API documentation is essential for any successful application. By leveraging NestJS's integration with Swagger, you can create clear, comprehensive, and interactive API documentation that will benefit both your team and external developers.

The tips and tricks outlined in this post—from setting up Swagger to customizing the UI—will help you maximize your API’s documentation potential. Remember, a well-documented API is a happy API!

LET'S BUILD WHAT'S NEXT

Ready to turn your idea into a real solution?

Let's discuss how we can help you create value with technology.

Let's Talk