Fullstack CourseLearn by building
Back to week 3

Topic

Swagger / OpenAPI — reading /docs

Definition

OpenAPI is a machine-readable specification of an HTTP API’s routes, parameters, and schemas, and Swagger is the tooling — including an interactive UI — that Nest’s @nestjs/swagger module generates from decorators already present on controllers and DTOs.

In simpler words

Swagger reads the same decorators you already wrote for routing and validation, and turns them into a browsable, testable API reference at /docs.

In a Nest API, Swagger is typically wired up in main.ts. Treat this topic as conceptual: understand what generates the document and how to read it, rather than configuring it from scratch.

After this you can

  • Explain what generates the /docs page
  • Match a DTO’s decorators to its Swagger schema
  • Use /docs to confirm a route’s auth requirement

What produces the /docs page

Definition

SwaggerModule.createDocument builds an OpenAPI document from a DocumentBuilder configuration plus the ApiTags, ApiCookieAuth, ApiProperty, and similar decorators already present on controllers and DTOs, and SwaggerModule.setup serves an interactive UI for that document at a chosen path.

In simpler words

You are not writing separate documentation — you are letting Nest read the same decorators that already do routing and validation.

main.ts configures the title, description, version, and addCookieAuth("access_token"), then serves the result at /docs.

ApiProperty / ApiPropertyOptional on DTO fields is what makes CreateTicketDto’s shape visible in the generated schema — an undecorated field can still validate but will not show accurately in Swagger.

Swagger setup

const swagger = new DocumentBuilder()
  .setTitle('API')
  .setVersion('0.1.0')
  .addCookieAuth('access_token')
  .build();
SwaggerModule.setup('docs', app, SwaggerModule.createDocument(app, swagger));

addCookieAuth registers the same cookie scheme the controllers reference with @ApiCookieAuth.

Reading /docs like a contract, not just a form

Definition

The generated document is the same contract AllExceptionsFilter and each DTO already enforce, so reading it is a fast way to confirm required fields, enums, and auth requirements without opening source files.

In simpler words

Swagger’s Authorize button and its Try it out panel exercise the real endpoints — a 401 there means the same thing a 401 means from curl.

@ApiCookieAuth marks which controllers expect the cookie session, matching the scheme name registered by addCookieAuth.

Because JwtStrategy also accepts a bearer Authorization header, Swagger’s Authorize dialog can supply a raw token for testing without a browser cookie.

Reading a route’s auth requirement

@ApiTags('tickets')
@ApiCookieAuth('access_token')
@Controller('tickets')
export class TicketsController { /* ... */ }

Every route in this controller expects the access_token cookie scheme shown in /docs; role restrictions like @Roles still live in the code, not in this class-level decorator.

Keep in mind

  • Treat Swagger as generated, not authored — fix the DTO/decorator, not the JSON it produces.
  • Use /docs to sanity-check a contract before writing a curl command by hand.
  • Keep API descriptions current when a route’s behavior changes.

Test

Check your understanding

At least 10 questions — mix of concept, syntax, practical, and logic. Score ≥80% (enforced by the API) to save progress.

Checking your session…

15 questions · concept 5 · syntax 3 · practical 4 · logic 3

1. How is /docs generated?
Concept
2. Does ApiProperty change ValidationPipe behavior?
Syntax
3. Why decorate DTOs for Swagger?
Practical
4. What does ApiCookieAuth communicate?
Logic
5. Does /docs update when you add routes?
Concept
6. Is a separate OpenAPI YAML required?
Practical
7. What should stay accurate in Swagger?
Syntax
8. Can Swagger Try it out replace Postman learning?
Logic
9. What is DocumentBuilder for?
Concept
10. Why tag controllers with ApiTags?
Practical
11. Does adding @ApiProperty validate the title at runtime?
Conceptintermediate
export class CreateTicketDto {
  @ApiProperty({ example: 'Login bug' })
  title: string;
}
12. What does addCookieAuth do in the generated docs?
Syntaxintermediate
const config = new DocumentBuilder()
  .setTitle('Tickets API')
  .addCookieAuth('access_token')
  .build();
13. What contract problem does this create?
Practicaladvanced
@Get()
@ApiOkResponse({ type: TicketDto })
list(): TicketWithSecretDto[] { /* ... */ }
14. What does @ApiTags affect here?
Logicintermediate
@ApiTags('tickets')
@Controller('tickets')
export class TicketsController {}
15. Why does Try it out fail on this protected route?
Conceptadvanced
// Swagger "Try it out" on DELETE /tickets/:id returns 401

Checking your session…