API Standards Validator
Validate REST API design standards compliance including versioning, naming conventions, HTTP methods, status codes, pagination, and Swagger documentation.
What This Skill Does
Performs comprehensive API standards validation:
- •Versioning: Checks
/v1/prefix on all routes - •Resource Naming: Validates plural nouns, lowercase-with-hyphens
- •HTTP Methods: Validates proper method usage and status codes
- •Pagination: Ensures list endpoints support pagination
- •Swagger Docs: Verifies complete OpenAPI documentation
- •Error Mapping: Checks proper status code usage
When to Use This Skill
Use when you need to:
- •Validate API endpoints before deployment
- •Check new endpoints for standards compliance
- •Review API design during code review
- •Ensure Swagger documentation completeness
Examples:
- •"Validate the User API endpoints"
- •"Check if Product API follows design standards"
- •"Review Order API for compliance"
API Design Standards
Versioning Rules
All controllers MUST be prefixed with /v1/:
typescript
// ✅ CORRECT
@JsonController('/v1/users')
export class UserController {}
@JsonController('/v1/sms-messages')
export class SmsMessageController {}
// ❌ WRONG
@JsonController('/users') // Missing version
@JsonController('/api/users') // Wrong format
Resource Naming Rules
Must be:
- •Plural nouns:
/v1/usersnot/v1/user - •Lowercase with hyphens:
/v1/sms-messages - •No verbs:
/v1/usersnot/v1/getUsers
typescript
// ✅ CORRECT '/v1/users' '/v1/products' '/v1/sms-messages' '/v1/order-items' // ❌ WRONG '/v1/user' // Singular '/v1/getUsers' // Verb '/v1/Users' // Wrong casing '/v1/sms_messages' // Underscores
HTTP Methods and Status Codes
Expected patterns:
- •POST (Create) → 201 Created
- •GET (Read) → 200 OK
- •PATCH (Partial Update) → 200 OK
- •PUT (Full Update) → 200 OK
- •DELETE → 204 No Content
Error status codes:
- •400 Bad Request → Validation errors
- •401 Unauthorized → Authentication required
- •403 Forbidden → Permission denied
- •404 Not Found → Resource not found
- •409 Conflict → Duplicate resource
- •422 Unprocessable Entity → Business rule violation
- •500 Internal Server Error → Unexpected errors
Pagination Requirements
List endpoints MUST support pagination with DTOs:
typescript
// ✅ CORRECT
export class QueryEntityDto {
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(1)
limit?: number = 20;
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(0)
offset?: number = 0;
sortBy: z.enum(['createdAt', 'name']).optional(),
order: z.enum(['asc', 'desc']).default('desc'),
});
// Response format
{
items: Entity[],
total: number,
limit: number,
offset: number
}
Swagger Documentation Requirements
All endpoints MUST have:
typescript
.post('/', controller.create.bind(controller), {
body: CreateSchema,
detail: {
summary: 'Create entity', // Required
description: 'Detailed description', // Recommended
tags: ['Entities'], // Required
responses: { // Required
201: { description: 'Created' },
400: { description: 'Invalid input' },
409: { description: 'Duplicate' },
},
},
})
Validation Checks
Versioning Validation
Checks:
- •All route prefixes include
/v1/ - •No routes without versioning
- •Consistent version across all endpoints
Reports:
code
CRITICAL: Missing API version File: src/contexts/user/presentation/user.routes.ts:5 Issue: Route prefix '/users' lacks /v1/ Fix: Change to '/v1/users'
Resource Naming Validation
Checks:
- •Resources are plural nouns
- •Lowercase with hyphens (not underscores or camelCase)
- •No verbs in resource names
- •Proper REST conventions
Reports:
code
CRITICAL: Singular resource name File: src/contexts/user/presentation/user.routes.ts:5 Issue: Resource '/v1/user' is singular Fix: Change to '/v1/users' CRITICAL: Verb in resource name File: src/contexts/user/presentation/user.routes.ts:10 Issue: Resource '/v1/getUsers' contains verb Fix: Use '/v1/users' with GET method
HTTP Method Validation
Checks:
- •GET for reads (200 OK)
- •POST for creates (201 Created)
- •PATCH/PUT for updates (200 OK)
- •DELETE for deletions (204 No Content)
- •Swagger responses match expected codes
Reports:
code
CRITICAL: Wrong status code for POST File: src/contexts/user/presentation/user.routes.ts:15 Issue: POST endpoint documents 200, should be 201 Fix: Change response code to 201 in Swagger detail
Error Mapping Validation
Checks:
- •Controllers map domain errors to HTTP exceptions
- •Correct status codes used:
- •EntityNotFoundError → 404
- •DuplicateError → 409
- •ValidationError → 400
- •UnauthorizedError → 401
- •ForbiddenError → 403
- •BusinessRuleViolation → 422
Reports:
code
WARNING: Missing error mapping
File: src/contexts/user/presentation/user.controller.ts:20
Issue: EntityNotFoundError not mapped to HttpException
Fix: Add error mapping:
if (error instanceof EntityNotFoundError) {
throw new HttpException(404, error.message, error.code);
}
Pagination Validation
Checks:
- •List endpoints have
limitparameter - •List endpoints have
offsetparameter - •Defaults defined for pagination
- •Response includes total count
Reports:
code
CRITICAL: Missing pagination File: src/contexts/user/presentation/schemas/query-user.schema.ts Issue: Query schema lacks limit and offset Fix: Add pagination fields: limit: z.coerce.number().min(1).max(100).default(10), offset: z.coerce.number().min(0).default(0),
Swagger Documentation Validation
Checks:
- •All endpoints have
detailobject - •
summaryfield present - •
tagsarray present - •
responsesobject with status codes - •Response descriptions provided
Reports:
code
WARNING: Incomplete Swagger documentation
File: src/contexts/user/presentation/user.routes.ts:15
Issue: POST endpoint missing 'responses' in detail
Fix: Add responses object:
responses: {
201: { description: 'User created' },
400: { description: 'Invalid input' },
409: { description: 'Email exists' },
}
Controller Binding Validation
Checks:
- •Controller methods use
.bind(controller) - •Controller resolved from DI container
Reports:
code
CRITICAL: Controller method not bound
File: src/contexts/user/presentation/user.routes.ts:12
Issue: .post('/', controller.create) missing .bind()
Fix: Add .bind(controller): .post('/', controller.create.bind(controller))
Common Violations
Missing Versioning
typescript
// ❌ WRONG
new Elysia({ prefix: '/users' })
// ✅ CORRECT
new Elysia({ prefix: '/v1/users' })
Wrong Resource Naming
typescript
// ❌ WRONG - Singular
new Elysia({ prefix: '/v1/user' })
// ❌ WRONG - Verb
.get('/getUser', ...)
// ✅ CORRECT
new Elysia({ prefix: '/v1/users' })
.get('/:id', ...)
Wrong Status Code
typescript
// ❌ WRONG
.post('/', ..., {
detail: {
responses: {
200: {} // Should be 201 for POST
}
}
})
// ✅ CORRECT
.post('/', ..., {
detail: {
responses: {
201: { description: 'Created' }
}
}
})
Missing Pagination
typescript
// ❌ WRONG
export const QuerySchema = z.object({
search: z.string().optional(),
});
// ✅ CORRECT
export const QuerySchema = z.object({
limit: z.coerce.number().min(1).max(100).default(10),
offset: z.coerce.number().min(0).default(0),
search: z.string().optional(),
});
Incomplete Swagger
typescript
// ❌ WRONG
.post('/', controller.create.bind(controller), {
body: CreateSchema,
})
// ✅ CORRECT
.post('/', controller.create.bind(controller), {
body: CreateSchema,
detail: {
summary: 'Create user',
tags: ['Users'],
responses: {
201: { description: 'User created' },
400: { description: 'Invalid input' },
},
},
})
Report Format
- •Summary: Endpoints validated
- •Endpoint Inventory: List all found endpoints
- •Critical Issues: Must fix immediately
- •Warnings: Should fix before deployment
- •Suggestions: Nice-to-have improvements
- •Compliance Score: Percentage of standards met
Integration
The validator is read-only - it never modifies code. After review:
- •Fix critical issues (versioning, naming)
- •Address warnings (Swagger docs, pagination)
- •Consider suggestions (additional docs)
- •Re-run validator to verify compliance
Related Skills
- •ddd-validator: Validate DDD architecture
- •ddd-api-generator: Generate compliant APIs
- •di-helper: Check DI setup