0
# Decorators
1
2
The **@nestjs/swagger** decorators provide a comprehensive annotation system for adding OpenAPI metadata to your NestJS applications. These TypeScript decorators attach metadata to classes, methods, properties, and parameters that is then used to generate accurate OpenAPI specifications.
3
4
## Property Decorators
5
6
Property decorators are used to annotate class properties, typically in DTOs (Data Transfer Objects) and entity classes.
7
8
### ApiProperty { .api }
9
10
```typescript
11
import { ApiProperty } from '@nestjs/swagger';
12
13
ApiProperty(options?: ApiPropertyOptions): PropertyDecorator
14
```
15
16
Marks a class property as an OpenAPI schema property with optional metadata configuration.
17
18
**Type Definitions:**
19
```typescript
20
type ApiPropertyOptions = ApiPropertyCommonOptions | (ApiPropertyCommonOptions & {
21
enumName: string;
22
enumSchema?: EnumSchemaAttributes;
23
});
24
25
type ApiPropertyCommonOptions = SchemaObjectMetadata & {
26
'x-enumNames'?: string[];
27
link?: () => Type<unknown> | Function;
28
};
29
30
interface SchemaObjectMetadata {
31
type?: any;
32
isArray?: boolean;
33
description?: string;
34
required?: boolean;
35
default?: any;
36
example?: any;
37
format?: string;
38
minimum?: number;
39
maximum?: number;
40
minLength?: number;
41
maxLength?: number;
42
pattern?: string;
43
enum?: any[];
44
enumName?: string;
45
deprecated?: boolean;
46
readOnly?: boolean;
47
writeOnly?: boolean;
48
nullable?: boolean;
49
discriminator?: DiscriminatorObject;
50
xml?: XMLObject;
51
additionalProperties?: boolean | SchemaObject;
52
items?: SchemaObject;
53
allOf?: SchemaObject[];
54
oneOf?: SchemaObject[];
55
anyOf?: SchemaObject[];
56
not?: SchemaObject;
57
}
58
```
59
60
**Usage:**
61
```typescript
62
class CreateProductDto {
63
@ApiProperty({
64
description: 'Product name',
65
example: 'iPhone 15',
66
minLength: 1,
67
maxLength: 100
68
})
69
name: string;
70
71
@ApiProperty({
72
description: 'Product price',
73
example: 999.99,
74
minimum: 0
75
})
76
price: number;
77
78
@ApiProperty({
79
description: 'Product category',
80
enum: ['electronics', 'clothing', 'books'],
81
example: 'electronics'
82
})
83
category: string;
84
85
@ApiProperty({
86
description: 'Product tags',
87
type: [String],
88
isArray: true,
89
example: ['mobile', 'apple', 'smartphone']
90
})
91
tags: string[];
92
}
93
```
94
95
### ApiPropertyOptional { .api }
96
97
```typescript
98
import { ApiPropertyOptional } from '@nestjs/swagger';
99
100
ApiPropertyOptional(options?: ApiPropertyOptions): PropertyDecorator
101
```
102
103
Creates an optional property annotation. Equivalent to `@ApiProperty({ required: false, ...options })`.
104
105
**Usage:**
106
```typescript
107
class UpdateProductDto {
108
@ApiPropertyOptional({ description: 'Updated product name' })
109
name?: string;
110
111
@ApiPropertyOptional({ description: 'Updated product price' })
112
price?: number;
113
114
@ApiPropertyOptional({ description: 'Product availability' })
115
inStock?: boolean;
116
}
117
```
118
119
### ApiResponseProperty { .api }
120
121
```typescript
122
import { ApiResponseProperty } from '@nestjs/swagger';
123
124
ApiResponseProperty(options?: Pick<ApiPropertyOptions, 'type' | 'example' | 'format' | 'deprecated' | 'enum'>): PropertyDecorator
125
```
126
127
Creates a read-only response property. Used for properties that only appear in API responses.
128
129
**Usage:**
130
```typescript
131
class ProductResponseDto {
132
@ApiResponseProperty({
133
example: 'prod_123456',
134
description: 'Unique product identifier'
135
})
136
readonly id: string;
137
138
@ApiResponseProperty({
139
example: '2023-01-15T10:30:00Z',
140
format: 'date-time'
141
})
142
readonly createdAt: Date;
143
144
@ApiResponseProperty({
145
example: '2023-01-16T14:20:00Z',
146
format: 'date-time'
147
})
148
readonly updatedAt: Date;
149
}
150
```
151
152
### ApiHideProperty { .api }
153
154
```typescript
155
import { ApiHideProperty } from '@nestjs/swagger';
156
157
ApiHideProperty(): PropertyDecorator
158
```
159
160
Excludes a property from the OpenAPI specification. Useful for sensitive or internal properties.
161
162
**Usage:**
163
```typescript
164
class UserDto {
165
@ApiProperty()
166
email: string;
167
168
@ApiHideProperty()
169
password: string; // Won't appear in OpenAPI spec
170
171
@ApiHideProperty()
172
internalId: number; // Hidden from documentation
173
}
174
```
175
176
## Method Decorators
177
178
Method decorators annotate controller methods and endpoints with OpenAPI operation metadata.
179
180
### ApiOperation { .api }
181
182
```typescript
183
import { ApiOperation } from '@nestjs/swagger';
184
185
ApiOperation(options: ApiOperationOptions, opts?: { overrideExisting?: boolean }): MethodDecorator
186
```
187
188
Describes an API operation (HTTP endpoint) with summary, description, and other metadata.
189
190
**Type Definitions:**
191
```typescript
192
type ApiOperationOptions = Partial<OperationObject>;
193
194
interface OperationObject {
195
summary?: string;
196
description?: string;
197
operationId?: string;
198
tags?: string[];
199
deprecated?: boolean;
200
security?: SecurityRequirementObject[];
201
externalDocs?: ExternalDocumentationObject;
202
callbacks?: Record<string, CallbackObject | ReferenceObject>;
203
}
204
```
205
206
**Usage:**
207
```typescript
208
@Controller('products')
209
export class ProductsController {
210
@Get()
211
@ApiOperation({
212
summary: 'Get all products',
213
description: 'Retrieves a paginated list of all available products',
214
operationId: 'getProducts'
215
})
216
findAll() {}
217
218
@Post()
219
@ApiOperation({
220
summary: 'Create product',
221
description: 'Creates a new product with the provided data'
222
})
223
create() {}
224
225
@Delete(':id')
226
@ApiOperation({
227
summary: 'Delete product',
228
description: 'Permanently deletes a product by ID',
229
deprecated: true
230
})
231
remove() {}
232
}
233
```
234
235
### ApiResponse { .api }
236
237
```typescript
238
import { ApiResponse } from '@nestjs/swagger';
239
240
ApiResponse(options: ApiResponseOptions, opts?: { overrideExisting?: boolean }): MethodDecorator & ClassDecorator
241
```
242
243
Defines response metadata for an endpoint, including status code, description, and schema.
244
245
**Type Definitions:**
246
```typescript
247
interface ApiResponseOptions {
248
status?: number | 'default' | '1XX' | '2XX' | '3XX' | '4XX' | '5XX';
249
description?: string;
250
type?: any;
251
isArray?: boolean;
252
schema?: SchemaObject & Partial<ReferenceObject>;
253
headers?: Record<string, HeaderObject>;
254
content?: Record<string, MediaTypeObject>;
255
links?: Record<string, LinkObject>;
256
}
257
```
258
259
**Usage:**
260
```typescript
261
@Controller('products')
262
export class ProductsController {
263
@Get()
264
@ApiResponse({
265
status: 200,
266
description: 'Products retrieved successfully',
267
type: [ProductDto],
268
isArray: true
269
})
270
@ApiResponse({
271
status: 404,
272
description: 'No products found'
273
})
274
findAll() {}
275
276
@Post()
277
@ApiResponse({
278
status: 201,
279
description: 'Product created successfully',
280
type: ProductDto
281
})
282
@ApiResponse({
283
status: 400,
284
description: 'Invalid product data',
285
schema: {
286
type: 'object',
287
properties: {
288
error: { type: 'string' },
289
message: { type: 'string' }
290
}
291
}
292
})
293
create() {}
294
}
295
```
296
297
### HTTP Status Response Decorators { .api }
298
299
Pre-configured response decorators for common HTTP status codes:
300
301
```typescript
302
import {
303
// 1xx Informational responses
304
ApiContinueResponse, // 100
305
ApiSwitchingProtocolsResponse, // 101
306
ApiProcessingResponse, // 102
307
ApiEarlyhintsResponse, // 103
308
309
// 2xx Success responses
310
ApiOkResponse, // 200
311
ApiCreatedResponse, // 201
312
ApiAcceptedResponse, // 202
313
ApiNonAuthoritativeInformationResponse, // 203
314
ApiNoContentResponse, // 204
315
ApiResetContentResponse, // 205
316
ApiPartialContentResponse, // 206
317
318
// 3xx Redirection responses
319
ApiAmbiguousResponse, // 300
320
ApiMovedPermanentlyResponse, // 301
321
ApiFoundResponse, // 302
322
ApiSeeOtherResponse, // 303
323
ApiNotModifiedResponse, // 304
324
ApiTemporaryRedirectResponse, // 307
325
ApiPermanentRedirectResponse, // 308
326
327
// 4xx Client error responses
328
ApiBadRequestResponse, // 400
329
ApiUnauthorizedResponse, // 401
330
ApiPaymentRequiredResponse, // 402
331
ApiForbiddenResponse, // 403
332
ApiNotFoundResponse, // 404
333
ApiMethodNotAllowedResponse, // 405
334
ApiNotAcceptableResponse, // 406
335
ApiProxyAuthenticationRequiredResponse, // 407
336
ApiRequestTimeoutResponse, // 408
337
ApiConflictResponse, // 409
338
ApiGoneResponse, // 410
339
ApiLengthRequiredResponse, // 411
340
ApiPreconditionFailedResponse, // 412
341
ApiPayloadTooLargeResponse, // 413
342
ApiUriTooLongResponse, // 414
343
ApiUnsupportedMediaTypeResponse, // 415
344
ApiRequestedRangeNotSatisfiableResponse, // 416
345
ApiExpectationFailedResponse, // 417
346
ApiIAmATeapotResponse, // 418
347
ApiMisdirectedResponse, // 421
348
ApiUnprocessableEntityResponse, // 422
349
ApiFailedDependencyResponse, // 424
350
ApiPreconditionRequiredResponse, // 428
351
ApiTooManyRequestsResponse, // 429
352
353
// 5xx Server error responses
354
ApiInternalServerErrorResponse, // 500
355
ApiNotImplementedResponse, // 501
356
ApiBadGatewayResponse, // 502
357
ApiServiceUnavailableResponse, // 503
358
ApiGatewayTimeoutResponse, // 504
359
ApiHttpVersionNotSupportedResponse // 505
360
} from '@nestjs/swagger';
361
362
// All have the same signature:
363
ApiOkResponse(options?: ApiResponseNoStatusOptions): MethodDecorator & ClassDecorator
364
365
type ApiResponseNoStatusOptions = Omit<ApiResponseOptions, 'status'>;
366
```
367
368
**Usage:**
369
```typescript
370
@Controller('products')
371
export class ProductsController {
372
@Get()
373
@ApiOkResponse({
374
description: 'Products retrieved successfully',
375
type: [ProductDto]
376
})
377
@ApiNotFoundResponse({ description: 'No products found' })
378
findAll() {}
379
380
@Post()
381
@ApiCreatedResponse({
382
description: 'Product created successfully',
383
type: ProductDto
384
})
385
@ApiBadRequestResponse({ description: 'Invalid product data' })
386
create() {}
387
388
@Delete(':id')
389
@ApiNoContentResponse({ description: 'Product deleted successfully' })
390
@ApiNotFoundResponse({ description: 'Product not found' })
391
remove() {}
392
}
393
```
394
395
### ApiDefaultResponse { .api }
396
397
```typescript
398
import { ApiDefaultResponse } from '@nestjs/swagger';
399
400
ApiDefaultResponse(options?: ApiResponseNoStatusOptions): MethodDecorator & ClassDecorator
401
```
402
403
Defines a default response that applies to all status codes not explicitly documented.
404
405
**Usage:**
406
```typescript
407
@Controller('products')
408
export class ProductsController {
409
@Get()
410
@ApiOkResponse({ type: [ProductDto] })
411
@ApiDefaultResponse({ description: 'Unexpected error occurred' })
412
findAll() {}
413
}
414
```
415
416
## Parameter Decorators
417
418
Parameter decorators describe the various types of parameters accepted by API endpoints.
419
420
### ApiParam { .api }
421
422
```typescript
423
import { ApiParam } from '@nestjs/swagger';
424
425
ApiParam(options: ApiParamOptions): ParameterDecorator
426
```
427
428
Describes a path parameter in the URL.
429
430
**Type Definitions:**
431
```typescript
432
interface ApiParamOptions {
433
name?: string;
434
description?: string;
435
required?: boolean;
436
type?: any;
437
enum?: any[];
438
example?: any;
439
examples?: Record<string, any>;
440
schema?: SchemaObject;
441
allowEmptyValue?: boolean;
442
style?: ParameterStyle;
443
explode?: boolean;
444
allowReserved?: boolean;
445
}
446
```
447
448
**Usage:**
449
```typescript
450
@Controller('products')
451
export class ProductsController {
452
@Get(':id')
453
@ApiParam({
454
name: 'id',
455
description: 'Product unique identifier',
456
type: 'string',
457
example: 'prod_123456'
458
})
459
findOne(@Param('id') id: string) {}
460
461
@Get('category/:category')
462
@ApiParam({
463
name: 'category',
464
description: 'Product category',
465
enum: ['electronics', 'clothing', 'books'],
466
example: 'electronics'
467
})
468
findByCategory(@Param('category') category: string) {}
469
}
470
```
471
472
### ApiQuery { .api }
473
474
```typescript
475
import { ApiQuery } from '@nestjs/swagger';
476
477
ApiQuery(options: ApiQueryOptions): ParameterDecorator
478
```
479
480
Describes a query parameter in the URL.
481
482
**Type Definitions:**
483
```typescript
484
interface ApiQueryOptions extends ApiParamOptions {
485
name?: string;
486
required?: boolean;
487
type?: any;
488
isArray?: boolean;
489
}
490
```
491
492
**Usage:**
493
```typescript
494
@Controller('products')
495
export class ProductsController {
496
@Get()
497
@ApiQuery({
498
name: 'limit',
499
description: 'Maximum number of products to return',
500
required: false,
501
type: Number,
502
example: 10
503
})
504
@ApiQuery({
505
name: 'offset',
506
description: 'Number of products to skip',
507
required: false,
508
type: Number,
509
example: 0
510
})
511
@ApiQuery({
512
name: 'categories',
513
description: 'Filter by categories',
514
required: false,
515
type: [String],
516
isArray: true,
517
example: ['electronics', 'books']
518
})
519
findAll(
520
@Query('limit') limit?: number,
521
@Query('offset') offset?: number,
522
@Query('categories') categories?: string[]
523
) {}
524
}
525
```
526
527
### ApiBody { .api }
528
529
```typescript
530
import { ApiBody } from '@nestjs/swagger';
531
532
ApiBody(options: ApiBodyOptions): MethodDecorator
533
```
534
535
Describes the request body content and schema.
536
537
**Type Definitions:**
538
```typescript
539
interface ApiBodyOptions {
540
description?: string;
541
type?: any;
542
isArray?: boolean;
543
required?: boolean;
544
schema?: SchemaObject & Partial<ReferenceObject>;
545
examples?: Record<string, any>;
546
}
547
```
548
549
**Usage:**
550
```typescript
551
@Controller('products')
552
export class ProductsController {
553
@Post()
554
@ApiBody({
555
description: 'Product data to create',
556
type: CreateProductDto,
557
examples: {
558
example1: {
559
summary: 'Basic product',
560
value: {
561
name: 'iPhone 15',
562
price: 999.99,
563
category: 'electronics'
564
}
565
}
566
}
567
})
568
create(@Body() createProductDto: CreateProductDto) {}
569
570
@Post('bulk')
571
@ApiBody({
572
description: 'Array of products to create',
573
type: [CreateProductDto],
574
isArray: true
575
})
576
createBulk(@Body() products: CreateProductDto[]) {}
577
}
578
```
579
580
### ApiHeader { .api }
581
582
```typescript
583
import { ApiHeader } from '@nestjs/swagger';
584
585
ApiHeader(options: ApiHeaderOptions): MethodDecorator & ClassDecorator
586
```
587
588
Describes a header parameter required by the endpoint.
589
590
**Type Definitions:**
591
```typescript
592
interface ApiHeaderOptions {
593
name?: string;
594
description?: string;
595
required?: boolean;
596
schema?: SchemaObject;
597
example?: any;
598
examples?: Record<string, any>;
599
}
600
```
601
602
**Usage:**
603
```typescript
604
@Controller('products')
605
export class ProductsController {
606
@Post()
607
@ApiHeader({
608
name: 'X-API-Key',
609
description: 'API key for authentication',
610
required: true,
611
example: 'abc123def456'
612
})
613
@ApiHeader({
614
name: 'Content-Language',
615
description: 'Preferred language for response',
616
required: false,
617
example: 'en-US'
618
})
619
create(@Body() createProductDto: CreateProductDto) {}
620
}
621
```
622
623
### ApiHeaders { .api }
624
625
```typescript
626
import { ApiHeaders } from '@nestjs/swagger';
627
628
ApiHeaders(headers: ApiHeaderOptions[]): MethodDecorator & ClassDecorator
629
```
630
631
Applies multiple header parameters at once using an array of header options.
632
633
**Usage:**
634
```typescript
635
@Controller('products')
636
export class ProductsController {
637
@Post()
638
@ApiHeaders([
639
{
640
name: 'X-API-Key',
641
description: 'API key for authentication',
642
required: true,
643
example: 'abc123def456'
644
},
645
{
646
name: 'Content-Language',
647
description: 'Preferred language for response',
648
required: false,
649
example: 'en-US'
650
},
651
{
652
name: 'X-Request-ID',
653
description: 'Unique request identifier',
654
required: false,
655
example: 'req_12345'
656
}
657
])
658
create(@Body() createProductDto: CreateProductDto) {}
659
}
660
```
661
662
### ApiCookieAuth { .api }
663
664
```typescript
665
import { ApiCookieAuth } from '@nestjs/swagger';
666
667
ApiCookieAuth(name = 'cookie'): MethodDecorator & ClassDecorator
668
```
669
670
Describes a cookie parameter used by the endpoint.
671
672
**Type Definitions:**
673
```typescript
674
interface ApiCookieOptions {
675
name?: string;
676
description?: string;
677
required?: boolean;
678
schema?: SchemaObject;
679
example?: any;
680
}
681
```
682
683
**Usage:**
684
```typescript
685
@Controller('products')
686
export class ProductsController {
687
@Get()
688
@ApiCookieAuth('session') // Cookie-based authentication
689
findUserProducts() {}
690
}
691
```
692
693
## Content Type Decorators
694
695
### ApiConsumes { .api }
696
697
```typescript
698
import { ApiConsumes } from '@nestjs/swagger';
699
700
ApiConsumes(...mimeTypes: string[]): MethodDecorator & ClassDecorator
701
```
702
703
Specifies the MIME types that the operation can consume in request bodies.
704
705
**Usage:**
706
```typescript
707
@Controller('uploads')
708
export class UploadsController {
709
@Post('image')
710
@ApiConsumes('multipart/form-data', 'image/jpeg', 'image/png')
711
uploadImage(@Body() data: any) {}
712
713
@Post('document')
714
@ApiConsumes('application/pdf', 'application/msword')
715
uploadDocument(@Body() data: any) {}
716
}
717
```
718
719
### ApiProduces { .api }
720
721
```typescript
722
import { ApiProduces } from '@nestjs/swagger';
723
724
ApiProduces(...mimeTypes: string[]): MethodDecorator & ClassDecorator
725
```
726
727
Specifies the MIME types that the operation can produce in responses.
728
729
**Usage:**
730
```typescript
731
@Controller('products')
732
export class ProductsController {
733
@Get(':id/image')
734
@ApiProduces('image/jpeg', 'image/png', 'image/webp')
735
getProductImage(@Param('id') id: string) {}
736
737
@Get('export')
738
@ApiProduces('application/json', 'text/csv', 'application/xlsx')
739
exportProducts(@Query('format') format: string) {}
740
}
741
```
742
743
## Security Decorators
744
745
### ApiSecurity { .api }
746
747
```typescript
748
import { ApiSecurity } from '@nestjs/swagger';
749
750
ApiSecurity(name: string, requirements?: string[]): MethodDecorator & ClassDecorator
751
```
752
753
Applies a security requirement to an operation or controller.
754
755
**Usage:**
756
```typescript
757
@Controller('admin')
758
@ApiSecurity('bearer') // Applies to all endpoints in controller
759
export class AdminController {
760
@Get('users')
761
@ApiSecurity('api-key') // Additional security for this endpoint
762
getUsers() {}
763
764
@Post('users')
765
@ApiSecurity('oauth2', ['admin:write']) // OAuth2 with specific scopes
766
createUser() {}
767
}
768
```
769
770
### ApiBearerAuth { .api }
771
772
```typescript
773
import { ApiBearerAuth } from '@nestjs/swagger';
774
775
ApiBearerAuth(name?: string): MethodDecorator & ClassDecorator
776
```
777
778
Applies Bearer token authentication (JWT) to an endpoint or controller.
779
780
**Usage:**
781
```typescript
782
@Controller('products')
783
@ApiBearerAuth() // Default name: 'bearer'
784
export class ProductsController {
785
@Get()
786
findAll() {} // Requires Bearer token
787
788
@Post()
789
@ApiBearerAuth('admin-bearer') // Custom security scheme name
790
create() {}
791
}
792
```
793
794
### ApiBasicAuth { .api }
795
796
```typescript
797
import { ApiBasicAuth } from '@nestjs/swagger';
798
799
ApiBasicAuth(name?: string): MethodDecorator & ClassDecorator
800
```
801
802
Applies HTTP Basic authentication to an endpoint or controller.
803
804
**Usage:**
805
```typescript
806
@Controller('legacy')
807
@ApiBasicAuth() // Default name: 'basic'
808
export class LegacyController {
809
@Get()
810
getData() {} // Requires Basic auth
811
812
@Post()
813
@ApiBasicAuth('admin-basic') // Custom security scheme name
814
createData() {}
815
}
816
```
817
818
### ApiOAuth2 { .api }
819
820
```typescript
821
import { ApiOAuth2 } from '@nestjs/swagger';
822
823
ApiOAuth2(scopes?: string[], name?: string): MethodDecorator & ClassDecorator
824
```
825
826
Applies OAuth2 authentication with optional scopes to an endpoint or controller.
827
828
**Usage:**
829
```typescript
830
@Controller('api')
831
export class ApiController {
832
@Get('public')
833
getPublicData() {} // No auth required
834
835
@Get('user')
836
@ApiOAuth2(['read']) // OAuth2 with read scope
837
getUserData() {}
838
839
@Post('admin')
840
@ApiOAuth2(['read', 'write', 'admin'], 'oauth2') // Multiple scopes
841
adminAction() {}
842
}
843
```
844
845
## Organization Decorators
846
847
### ApiTags { .api }
848
849
```typescript
850
import { ApiTags } from '@nestjs/swagger';
851
852
ApiTags(...tags: string[]): MethodDecorator & ClassDecorator
853
```
854
855
Groups operations by tags in the Swagger UI for better organization.
856
857
**Usage:**
858
```typescript
859
@Controller('products')
860
@ApiTags('Products') // All endpoints tagged as 'Products'
861
export class ProductsController {
862
@Get()
863
findAll() {}
864
865
@Post()
866
@ApiTags('Products', 'Admin') // Multiple tags
867
create() {}
868
}
869
870
@Controller('users')
871
@ApiTags('User Management', 'Authentication')
872
export class UsersController {}
873
```
874
875
### ApiExcludeEndpoint { .api }
876
877
```typescript
878
import { ApiExcludeEndpoint } from '@nestjs/swagger';
879
880
ApiExcludeEndpoint(disable?: boolean): MethodDecorator
881
```
882
883
Excludes a specific endpoint from the OpenAPI specification.
884
885
**Usage:**
886
```typescript
887
@Controller('products')
888
export class ProductsController {
889
@Get()
890
findAll() {} // Included in OpenAPI
891
892
@Get('internal')
893
@ApiExcludeEndpoint() // Excluded from OpenAPI
894
internalEndpoint() {}
895
896
@Get('debug')
897
@ApiExcludeEndpoint(process.env.NODE_ENV === 'production') // Conditional exclusion
898
debugEndpoint() {}
899
}
900
```
901
902
### ApiExcludeController { .api }
903
904
```typescript
905
import { ApiExcludeController } from '@nestjs/swagger';
906
907
ApiExcludeController(disable?: boolean): ClassDecorator
908
```
909
910
Excludes an entire controller from the OpenAPI specification.
911
912
**Usage:**
913
```typescript
914
@Controller('internal')
915
@ApiExcludeController() // Entire controller excluded
916
export class InternalController {
917
@Get()
918
internalData() {} // Not in OpenAPI
919
920
@Post()
921
internalAction() {} // Not in OpenAPI
922
}
923
924
@Controller('debug')
925
@ApiExcludeController(process.env.NODE_ENV === 'production')
926
export class DebugController {} // Excluded in production only
927
```
928
929
## Advanced Decorators
930
931
### ApiExtraModels { .api }
932
933
```typescript
934
import { ApiExtraModels } from '@nestjs/swagger';
935
936
ApiExtraModels(...models: Function[]): ClassDecorator
937
```
938
939
Adds extra models to the OpenAPI components section for reference in schemas.
940
941
**Usage:**
942
```typescript
943
@Controller('products')
944
@ApiExtraModels(ProductDto, CategoryDto, TagDto) // Models available for $ref
945
export class ProductsController {
946
@Get()
947
@ApiResponse({
948
status: 200,
949
schema: {
950
allOf: [
951
{ $ref: getSchemaPath(ProductDto) },
952
{
953
properties: {
954
category: { $ref: getSchemaPath(CategoryDto) },
955
tags: {
956
type: 'array',
957
items: { $ref: getSchemaPath(TagDto) }
958
}
959
}
960
}
961
]
962
}
963
})
964
findAll() {}
965
}
966
```
967
968
### ApiExtension { .api }
969
970
```typescript
971
import { ApiExtension } from '@nestjs/swagger';
972
973
ApiExtension(extensionKey: string, extensionProperties: any): MethodDecorator & ClassDecorator
974
```
975
976
Adds custom OpenAPI extensions (x-* properties) to operations or schemas.
977
978
**Usage:**
979
```typescript
980
@Controller('products')
981
export class ProductsController {
982
@Get()
983
@ApiExtension('x-codeSamples', [
984
{
985
lang: 'JavaScript',
986
source: 'const products = await api.getProducts();'
987
},
988
{
989
lang: 'Python',
990
source: 'products = api.get_products()'
991
}
992
])
993
findAll() {}
994
995
@Post()
996
@ApiExtension('x-rate-limit', { requests: 100, window: '1h' })
997
create() {}
998
}
999
```
1000
1001
### ApiSchema { .api }
1002
1003
```typescript
1004
import { ApiSchema } from '@nestjs/swagger';
1005
1006
ApiSchema(options?: ApiSchemaOptions): ClassDecorator
1007
```
1008
1009
Defines custom schema metadata for a class, overriding auto-generated schema properties.
1010
1011
**Type Definitions:**
1012
```typescript
1013
interface ApiSchemaOptions {
1014
name?: string;
1015
description?: string;
1016
deprecated?: boolean;
1017
discriminator?: DiscriminatorObject;
1018
additionalProperties?: boolean | SchemaObject;
1019
example?: any;
1020
}
1021
```
1022
1023
**Usage:**
1024
```typescript
1025
@ApiSchema({
1026
name: 'Product',
1027
description: 'A product in the system',
1028
example: {
1029
id: 'prod_123',
1030
name: 'iPhone 15',
1031
price: 999.99
1032
}
1033
})
1034
export class ProductDto {
1035
@ApiProperty()
1036
id: string;
1037
1038
@ApiProperty()
1039
name: string;
1040
1041
@ApiProperty()
1042
price: number;
1043
}
1044
```
1045
1046
### ApiCallbacks { .api }
1047
1048
```typescript
1049
import { ApiCallbacks } from '@nestjs/swagger';
1050
1051
ApiCallbacks(...callbackObjects: Array<CallBackObject<any>>): MethodDecorator
1052
```
1053
1054
Defines callback objects for asynchronous operations like webhooks.
1055
1056
**Type Definitions:**
1057
```typescript
1058
interface CallBackObject<T> {
1059
name: string;
1060
callbackUrl: string;
1061
method: string;
1062
requestBody: {
1063
type: T;
1064
};
1065
expectedResponse: {
1066
status: number;
1067
description?: string;
1068
};
1069
}
1070
```
1071
1072
**Usage:**
1073
```typescript
1074
@Controller('webhooks')
1075
export class WebhookController {
1076
@Post('subscribe')
1077
@ApiCallbacks(
1078
{
1079
name: 'orderUpdate',
1080
callbackUrl: 'http://callback.example.com/order-update',
1081
method: 'post',
1082
requestBody: {
1083
type: OrderUpdateDto
1084
},
1085
expectedResponse: {
1086
status: 200,
1087
description: 'Callback received successfully'
1088
}
1089
},
1090
{
1091
name: 'paymentNotification',
1092
callbackUrl: 'http://callback.example.com/payment-notification',
1093
method: 'post',
1094
requestBody: {
1095
type: PaymentNotificationDto
1096
},
1097
expectedResponse: {
1098
status: 200
1099
}
1100
}
1101
)
1102
subscribe() {}
1103
}
1104
```
1105
1106
### ApiLink { .api }
1107
1108
```typescript
1109
import { ApiLink } from '@nestjs/swagger';
1110
1111
ApiLink(options: ApiLinkOptions): PropertyDecorator
1112
```
1113
1114
Creates OpenAPI link objects for describing relationships between operations.
1115
1116
**Type Definitions:**
1117
```typescript
1118
interface ApiLinkOptions {
1119
operationId?: string;
1120
description?: string;
1121
parameters?: Record<string, any>;
1122
requestBody?: any;
1123
}
1124
```
1125
1126
**Usage:**
1127
```typescript
1128
class ProductDto {
1129
@ApiProperty()
1130
@ApiLink({
1131
operationId: 'getProductById',
1132
description: 'Link to get full product details'
1133
})
1134
id: string;
1135
1136
@ApiProperty()
1137
name: string;
1138
}
1139
```
1140
1141
### ApiDefaultGetter { .api }
1142
1143
```typescript
1144
import { ApiDefaultGetter } from '@nestjs/swagger';
1145
1146
ApiDefaultGetter(type: Type<unknown> | Function, parameter: string): MethodDecorator
1147
```
1148
1149
Marks a method as the default getter for OpenAPI link generation with Swagger link objects.
1150
1151
**Parameters:**
1152
- `type` - The type for which the decorated function is the default getter
1153
- `parameter` - Name of the parameter in the route that corresponds to the id of the type
1154
1155
**Usage:**
1156
```typescript
1157
import { Type } from '@nestjs/common';
1158
1159
class UserGet {
1160
id: string;
1161
name: string;
1162
}
1163
1164
@Controller('users')
1165
export class UsersController {
1166
@Get(':userId')
1167
@ApiDefaultGetter(UserGet, 'userId') // Links UserGet type to this getter
1168
@ApiOperation({ operationId: 'getUserById' })
1169
findOne(@Param('userId') userId: string) {}
1170
}
1171
```
1172
1173
## Best Practices
1174
1175
### Comprehensive API Documentation
1176
```typescript
1177
@Controller('products')
1178
@ApiTags('Products')
1179
@ApiExtraModels(ProductDto, CreateProductDto, UpdateProductDto)
1180
export class ProductsController {
1181
@Get()
1182
@ApiOperation({
1183
summary: 'Get all products',
1184
description: 'Retrieves a paginated list of all products with optional filtering'
1185
})
1186
@ApiQuery({ name: 'page', required: false, type: Number })
1187
@ApiQuery({ name: 'limit', required: false, type: Number })
1188
@ApiOkResponse({ type: [ProductDto], description: 'Products retrieved successfully' })
1189
@ApiBadRequestResponse({ description: 'Invalid query parameters' })
1190
async findAll(@Query() query: PaginationDto) {}
1191
1192
@Post()
1193
@ApiOperation({ summary: 'Create product' })
1194
@ApiBody({ type: CreateProductDto })
1195
@ApiCreatedResponse({ type: ProductDto })
1196
@ApiBadRequestResponse({ description: 'Invalid product data' })
1197
@ApiBearerAuth()
1198
async create(@Body() createProductDto: CreateProductDto) {}
1199
}
1200
```
1201
1202
### DTO Annotations
1203
```typescript
1204
class CreateProductDto {
1205
@ApiProperty({
1206
description: 'Product name',
1207
minLength: 1,
1208
maxLength: 100,
1209
example: 'iPhone 15'
1210
})
1211
name: string;
1212
1213
@ApiProperty({
1214
description: 'Product description',
1215
maxLength: 1000,
1216
example: 'Latest iPhone with advanced features'
1217
})
1218
description: string;
1219
1220
@ApiProperty({
1221
description: 'Product price in USD',
1222
minimum: 0,
1223
example: 999.99
1224
})
1225
price: number;
1226
1227
@ApiPropertyOptional({
1228
description: 'Product availability',
1229
default: true
1230
})
1231
inStock?: boolean;
1232
}
1233
```
1234
1235
This comprehensive decorator system provides everything needed to create detailed, accurate OpenAPI documentation for your NestJS applications with minimal effort while maintaining full type safety.