Claude Code Plugins

Community-maintained marketplace

Feedback

Validate REST API standards compliance (versioning, naming, HTTP methods, status codes, pagination, Swagger). Use when checking endpoints before deployment, reviewing API design, or ensuring documentation completeness (e.g., "Validate User API", "Check Product endpoints").

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name api-validator
description Validate REST API standards compliance (versioning, naming, HTTP methods, status codes, pagination, Swagger). Use when checking endpoints before deployment, reviewing API design, or ensuring documentation completeness (e.g., "Validate User API", "Check Product endpoints").
allowed-tools Read, Glob, Grep

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/:

// ✅ 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/users not /v1/user
  • Lowercase with hyphens: /v1/sms-messages
  • No verbs: /v1/users not /v1/getUsers
// ✅ 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:

// ✅ 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:

.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:

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:

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:

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:

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 limit parameter
  • List endpoints have offset parameter
  • Defaults defined for pagination
  • Response includes total count

Reports:

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 detail object
  • summary field present
  • tags array present
  • responses object with status codes
  • Response descriptions provided

Reports:

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:

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

// ❌ WRONG
new Elysia({ prefix: '/users' })

// ✅ CORRECT
new Elysia({ prefix: '/v1/users' })

Wrong Resource Naming

// ❌ WRONG - Singular
new Elysia({ prefix: '/v1/user' })

// ❌ WRONG - Verb
.get('/getUser', ...)

// ✅ CORRECT
new Elysia({ prefix: '/v1/users' })
.get('/:id', ...)

Wrong Status Code

// ❌ WRONG
.post('/', ..., {
  detail: {
    responses: {
      200: {} // Should be 201 for POST
    }
  }
})

// ✅ CORRECT
.post('/', ..., {
  detail: {
    responses: {
      201: { description: 'Created' }
    }
  }
})

Missing Pagination

// ❌ 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

// ❌ 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

  1. Summary: Endpoints validated
  2. Endpoint Inventory: List all found endpoints
  3. Critical Issues: Must fix immediately
  4. Warnings: Should fix before deployment
  5. Suggestions: Nice-to-have improvements
  6. Compliance Score: Percentage of standards met

Integration

The validator is read-only - it never modifies code. After review:

  1. Fix critical issues (versioning, naming)
  2. Address warnings (Swagger docs, pagination)
  3. Consider suggestions (additional docs)
  4. Re-run validator to verify compliance

Related Skills

  • ddd-validator: Validate DDD architecture
  • ddd-api-generator: Generate compliant APIs
  • di-helper: Check DI setup