Filtering
Control which endpoints appear in your generated OpenAPI spec.
Exclude endpoints from the generated spec using decorators or path filters.
Defaults: we already skip endpoints with ApiExcludeEndpoint and
ApiExcludeController. pathFilter is an include filter - only matching
paths remain.
Decorator-Based Exclusion
Using @ApiExcludeEndpoint
The standard @nestjs/swagger decorator for excluding individual endpoints:
import { ApiExcludeEndpoint } from '@nestjs/swagger';
@Controller('system')
export class SystemController {
@Get('health')
@ApiExcludeEndpoint()
healthCheck() {
return { status: 'ok' };
}
@Get('metrics')
@ApiExcludeEndpoint()
metrics() {
return this.metricsService.getAll();
}
@Get('status')
// This endpoint IS included in the spec
status() {
return { version: '1.0.0' };
}
}Using @ApiExcludeController
Exclude an entire controller:
import { ApiExcludeController } from '@nestjs/swagger';
@ApiExcludeController()
@Controller('internal')
export class InternalController {
// All endpoints in this controller are excluded
@Get('debug')
debug() {}
@Post('reset')
reset() {}
}Custom Exclusion Decorators
Configure custom decorator names to trigger exclusion:
// openapi.config.ts
export default defineConfig({
output: 'openapi.json',
openapi: {
info: { title: 'My API', version: '1.0.0' },
},
options: {
excludeDecorators: [
'ApiExcludeEndpoint', // Default
'ApiExcludeController', // Default
'Internal', // Custom
'AdminOnly', // Custom
'Deprecated', // Custom
],
},
});Create custom decorators:
// decorators/internal.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const Internal = () => SetMetadata('internal', true);Use them:
@Controller('admin')
export class AdminController {
@Get('users')
@Internal() // Excluded from spec
listAllUsers() {}
@Delete('cache')
@AdminOnly() // Excluded from spec
clearCache() {}
}Path-Based Filtering
Using Regex
Filter paths with a regular expression. Paths matching the regex are included:
// openapi.config.ts
export default defineConfig({
output: 'openapi.json',
openapi: {
info: { title: 'My API', version: '1.0.0' },
},
options: {
// Exclude paths containing '/internal/'
pathFilter: /^(?!.*\/internal\/).*/,
},
});Common patterns:
// Exclude internal paths
pathFilter: /^(?!.*\/internal\/).*/;
// Only include /api/v2 paths
pathFilter: /^\/api\/v2\//;
// Exclude admin and debug paths
pathFilter: /^(?!.*(\/admin\/|\/debug\/)).*/;
// Only include public API paths
pathFilter: /^\/public\//;Using a Function
For complex filtering logic, use a predicate function:
options: {
pathFilter: (path) => {
// Exclude internal paths
if (path.includes('/internal/')) return false;
// Exclude deprecated v1 API
if (path.startsWith('/api/v1/')) return false;
// Exclude admin endpoints
if (path.includes('/admin/')) return false;
// Include everything else
return true;
},
}Combining Filters
Decorator exclusion and path filtering work together:
// openapi.config.ts
export default defineConfig({
output: 'openapi.json',
openapi: {
info: { title: 'My API', version: '1.0.0' },
},
options: {
// Decorator-based exclusion
excludeDecorators: ['ApiExcludeEndpoint', 'Internal'],
// Path-based filtering
pathFilter: /^(?!.*\/internal\/).*/,
},
});An endpoint is excluded if:
- It has any decorator in
excludeDecorators, OR - Its path doesn't match
pathFilter
Use Cases
Public vs Internal APIs
Generate separate specs for public and internal APIs:
// public-openapi.config.ts
export default defineConfig({
output: 'openapi-public.json',
openapi: {
info: { title: 'Public API', version: '1.0.0' },
},
options: {
pathFilter: /^\/api\/public\//,
},
});
// internal-openapi.config.ts
export default defineConfig({
output: 'openapi-internal.json',
openapi: {
info: { title: 'Internal API', version: '1.0.0' },
},
options: {
pathFilter: /^\/api\/internal\//,
},
});API Versioning
Generate specs for different API versions:
// v1-openapi.config.ts
export default defineConfig({
output: 'openapi-v1.json',
openapi: {
info: { title: 'API v1', version: '1.0.0' },
},
options: {
pathFilter: /^\/api\/v1\//,
},
});
// v2-openapi.config.ts
export default defineConfig({
output: 'openapi-v2.json',
openapi: {
info: { title: 'API v2', version: '2.0.0' },
},
options: {
pathFilter: /^\/api\/v2\//,
},
});Health and Metrics Endpoints
Exclude infrastructure endpoints from public documentation:
options: {
excludeDecorators: ['ApiExcludeEndpoint'],
pathFilter: (path) => {
const infrastructurePaths = ['/health', '/ready', '/metrics', '/debug'];
return !infrastructurePaths.some(p => path.startsWith(p));
},
}Feature Flags
Conditionally include endpoints based on environment:
// openapi.config.ts
const includeExperimentalFeatures = process.env.INCLUDE_EXPERIMENTAL === 'true';
export default defineConfig({
output: 'openapi.json',
openapi: {
info: { title: 'My API', version: '1.0.0' },
},
options: {
pathFilter: (path) => {
if (path.includes('/experimental/') && !includeExperimentalFeatures) {
return false;
}
return true;
},
},
});Examples
Exclude by Multiple Criteria
options: {
excludeDecorators: [
'ApiExcludeEndpoint',
'ApiExcludeController',
'Internal',
'Deprecated',
'Beta',
],
pathFilter: (path) => {
// Exclude patterns
const excludePatterns = [
/^\/internal\//,
/^\/debug\//,
/^\/admin\/system\//,
/\/_private$/,
];
return !excludePatterns.some(pattern => pattern.test(path));
},
}Include Only Specific Tags
While this doesn't filter by OpenAPI tags directly, you can structure your paths:
options: {
// Only include user-related endpoints
pathFilter: /^\/(users|profiles|accounts)\//,
}Next Steps
- Serving Guide - Serve the spec at runtime
- Configuration Reference - Full config options
- Recipes: CI/CD - Generate specs in pipelines