We use cookies to enhance your experience on the site
CodeWorlds

Advanced Responses - Imperial Edicts

In the imperial chancellery, every edict had to clearly define the consequences - what happens in case of success, what happens in case of a law violation, and what happens when the petitioner lacks authorization. In Swagger, we document this using specialized response decorators.

Specialized Response Decorators

Instead of the generic

@ApiResponse()
, NestJS Swagger offers dedicated decorators for each HTTP status code:

1import {
2  ApiOkResponse,
3  ApiCreatedResponse,
4  ApiNotFoundResponse,
5  ApiBadRequestResponse,
6  ApiUnauthorizedResponse,
7  ApiForbiddenResponse,
8  ApiConflictResponse,
9  ApiInternalServerErrorResponse,
10} from '@nestjs/swagger';

@ApiOkResponse (200) - Decree Executed

We use it when the endpoint returns data successfully:

1@ApiOkResponse({
2  description: 'List of Empire legions',
3  type: [LegionResponseDto],
4})
5@Get()
6findAll(): LegionResponseDto[] {
7  return this.legionService.findAll();
8}

@ApiCreatedResponse (201) - New Recruit Accepted

For endpoints creating new resources:

1@ApiCreatedResponse({
2  description: 'Legionary has been successfully recruited',
3  type: LegionaryResponseDto,
4})
5@Post()
6recruit(@Body() dto: CreateLegionaryDto): LegionaryResponseDto {
7  return this.legionService.recruit(dto);
8}

@ApiNotFoundResponse (404) - Not Found in the Annals

When the requested resource does not exist:

1@ApiNotFoundResponse({
2  description: 'Legion with the given ID was not found in the annals of the Empire',
3})
4@Get(':id')
5findOne(@Param('id') id: string) {
6  return this.legionService.findOne(id);
7}

@ApiBadRequestResponse (400) - Defective Parchment

When the input data is invalid:

1@ApiBadRequestResponse({
2  description: 'Invalid recruitment data - check the required fields',
3})
4@Post()
5recruit(@Body() dto: CreateLegionaryDto) {
6  return this.legionService.recruit(dto);
7}

@ApiUnauthorizedResponse (401) - Missing Imperial Seal

When the user is not authenticated:

1@ApiUnauthorizedResponse({
2  description: 'Missing valid JWT token - imperial seal required',
3})
4@ApiBearerAuth('JWT-auth')
5@UseGuards(JwtAuthGuard)
6@Delete(':id')
7dismiss(@Param('id') id: string) {
8  return this.legionService.dismiss(id);
9}

Combining Multiple Response Decorators

In practice, each endpoint should document all possible responses:

1@ApiOperation({ summary: 'Promote a legionary' })
2@ApiOkResponse({
3  description: 'Legionary has been promoted',
4  type: LegionaryResponseDto,
5})
6@ApiNotFoundResponse({
7  description: 'Legionary not found',
8})
9@ApiUnauthorizedResponse({
10  description: 'Unauthorized - JWT token required',
11})
12@ApiBadRequestResponse({
13  description: 'Invalid target rank',
14})
15@ApiBearerAuth('JWT-auth')
16@UseGuards(JwtAuthGuard)
17@Patch(':id/promote')
18promote(
19  @Param('id') id: string,
20  @Body() dto: PromoteLegionaryDto,
21): LegionaryResponseDto {
22  return this.legionService.promote(id, dto);
23}

Response Type with DTO

The

type
option in response decorators allows you to link the response to a specific DTO:

1// Single object response
2@ApiOkResponse({ type: LegionResponseDto })
3
4// Array of objects response
5@ApiOkResponse({ type: [LegionResponseDto] })
6
7// Response with description
8@ApiOkResponse({
9  description: 'Legion details',
10  type: LegionResponseDto,
11})

Thanks to this, Swagger UI will display the full response schema with example values.

Practical Exercise

Add advanced response decorators to the tribute controller of the Empire:

Go to CodeWorlds