OpenAPI is a language-agnostic specification for declaring API documentation for REST APIs. It contains the following information:
- API information like title, description, version
- endpoints definitions with request and response parameters
- DTOs and security schemas
openapi: 3.0.0
paths:
/users:
post:
operationId: UsersController_createUser
summary: Create user
description: Create a new user
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserDto'
responses:
'201':
description: 'User is created'
info:
title: nestjs-starter
description: Minimal NestJS boilerplate
version: 0.1.0
contact: {}
tags: []
servers: []
components:
securitySchemes:
token:
type: apiKey
scheme: api_key
in: header
name: auth-token
schemas:
CreateUserDto:
type: object
properties:
firstName:
type: string
example: tester
description: first name of the user
required:
- firstName
NestJS provides a Swagger plugin for generating the API docs.
Setup
Configure API documentation with the specified endpoint, like /api-docs
, which shows the generated docs.
const SWAGGER_API_ENDPOINT = '/api-docs';
// ...
export const setupApiDocs = (app: INestApplication): void => {
const options = new DocumentBuilder()
.setTitle(SWAGGER_API_TITLE)
.setDescription(SWAGGER_API_DESCRIPTION)
.setVersion(SWAGGER_API_VERSION)
.addSecurity('token', {
type: 'apiKey',
scheme: 'api_key',
in: 'header',
name: 'auth-token',
})
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup(SWAGGER_API_ENDPOINT, app, document);
};
Configure the plugin in the NestJS config file.
{
"compilerOptions": {
"plugins": ["@nestjs/swagger"]
}
}
JSON and YAML formats are generated at /api-docs-json
and /api-docs-yaml
endpoints, respectively.
Decorators
-
ApiTags
groups endpoints
@ApiTags('users')
@Controller('users')
export class UsersController {
// ...
}
-
ApiOperation
provides more details like a summary and description of the endpoint
@ApiOperation({
summary: 'Get user',
description: 'Get user by id',
})
@Get(':id')
async getById(
@Param('id', new ParseUUIDPipe()) id: string,
): Promise<UserDto> {
// ...
}
-
ApiOperation
can be used to mark an endpoint as deprecated
@ApiOperation({ deprecated: true })
-
@ApiProperty
and@ApiPropertyOptional
should be used for request and response DTOs fields. Example and description values will be shown in the generated documentation.
export class CreateUserDto {
@ApiProperty({ example: 'John', description: 'first name of the user' })
// ...
public firstName: string;
@ApiPropertyOptional({ example: 'Doe', description: 'last name of the user' })
// ...
public lastName?: string;
}
-
ApiHeader
documents endpoint headers
@ApiHeader({
name: 'correlation-id',
required: false,
description: 'unique id for correlated logs',
example: '7ea2c7f7-8b46-475d-86f8-7aaaa9e4a35b',
})
@Get()
getHello(): string {
// ...
}
-
ApiResponse
specifies which responses are expected, like error responses. NestJS' Swagger package provides decorators for specific status codes likeApiBadRequestResponse
.
// ...
@ApiResponse({ type: NotFoundException, status: HttpStatus.NOT_FOUND })
@ApiBadRequestResponse({ type: BadRequestException })
@Get(':id')
async getById(
@Param('id', new ParseUUIDPipe()) id: string,
): Promise<UserDto> {
return this.userService.findById(id);
}
// ...
-
ApiSecurity('token')
uses a custom-defined security strategy,token
in this case. Other options are to use already defined strategies likeApiBearerAuth
.
@ApiSecurity('token')
@Controller()
export class AppController {
// ...
}
// ...
@ApiBearerAuth()
@Controller()
export class AppController {
// ...
}
-
ApiExcludeEndpoint
andApiExcludeController
exclude one endpoint and the whole controller, respectively.
export class AppController {
@ApiExcludeEndpoint()
@Get()
getHello(): string {
// ...
}
}
// ...
@ApiExcludeController()
@Controller()
export class AppController {
// ...
}
-
ApiBody
withApiExtraModels
add an example for the request body
const CreateUserDtoExample = {
firstName: 'Tester',
};
@ApiExtraModels(CreateUserDto)
@ApiBody({
schema: {
oneOf: refs(CreateUserDto),
example: CreateUserDtoExample,
},
})
@Post()
async createUser(@Body() newUser: CreateUserDto): Promise<UserDto> {
// ...
}
Importing API to Postman
Import JSON version of API docs as Postman API with Import → Link option (e.g., URL http://localhost:8081/api-docs-json
). Imported API collection will be available in the APIs tab.
Boilerplate
Here is the link to the boilerplate I use for the development. It contains the examples mentioned above with more details.
Top comments (2)
Great content
Thanks, I'm glad you find this article to be helpful