Claude Code Plugins

Community-maintained marketplace

Feedback

Production-grade API architecture skill for REST, gRPC, GraphQL design, versioning, and security patterns

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-architecture
description Production-grade API architecture skill for REST, gRPC, GraphQL design, versioning, and security patterns
sasmp_version 1.3.0
bonded_agent 04-api-design
bond_type PRIMARY_BOND

API Architecture Skill

Purpose: Atomic skill for API design with comprehensive validation, error handling, and security patterns.

Skill Identity

Attribute Value
Scope REST, gRPC, GraphQL Design
Responsibility Single: API contract and protocol design
Invocation Skill("api-architecture")

Parameter Schema

Input Validation

parameters:
  api_context:
    type: object
    required: true
    properties:
      protocol:
        type: string
        enum: [REST, gRPC, GraphQL, hybrid]
        required: true
      resources:
        type: array
        items:
          type: object
          properties:
            name: { type: string, pattern: "^[a-z][a-z0-9-]*$" }
            operations: { type: array, items: { type: string } }
        minItems: 1
      consumers:
        type: array
        items:
          type: string
          enum: [web, mobile, third_party, internal, iot]
      security:
        type: object
        properties:
          auth_method: { type: string, enum: [oauth2, api_key, jwt, mtls] }
          rate_limiting: { type: boolean, default: true }
      constraints:
        type: object
        properties:
          max_latency_ms: { type: integer, minimum: 1 }
          backward_compatible: { type: boolean, default: true }

validation_rules:
  - name: "resource_naming"
    rule: "resources[*].name matches /^[a-z][a-z0-9-]*$/"
    error: "Resource names must be lowercase with hyphens"
  - name: "public_api_security"
    rule: "consumers includes 'third_party' implies auth_method is set"
    error: "Public APIs require authentication"

Output Schema

output:
  type: object
  properties:
    endpoints:
      type: array
      items:
        type: object
        properties:
          method: { type: string }
          path: { type: string }
          request_schema: { type: object }
          response_schema: { type: object }
          status_codes: { type: array }
    openapi_spec:
      type: string
      format: yaml
    security_config:
      type: object
      properties:
        auth: { type: object }
        rate_limits: { type: object }
        cors: { type: object }

Core Patterns

REST Design Principles

Resource Naming:
├── Nouns, plural: /users, /orders
├── Hierarchical: /users/{id}/orders
├── Actions as sub-resources: /orders/{id}/cancel
├── Query params for filtering: ?status=active
└── Kebab-case: /user-profiles

HTTP Methods:
├── GET     → Read (idempotent, cacheable)
├── POST    → Create (not idempotent)
├── PUT     → Replace (idempotent)
├── PATCH   → Update partial (idempotent)
├── DELETE  → Remove (idempotent)
├── HEAD    → Metadata only
└── OPTIONS → CORS preflight

Status Codes:
├── 200 OK: Successful GET/PUT/PATCH
├── 201 Created: Successful POST (with Location header)
├── 204 No Content: Successful DELETE
├── 400 Bad Request: Validation error
├── 401 Unauthorized: Not authenticated
├── 403 Forbidden: Not authorized
├── 404 Not Found: Resource missing
├── 409 Conflict: State conflict
├── 422 Unprocessable: Semantic error
├── 429 Too Many Requests: Rate limited
├── 500 Internal Error: Server bug
├── 502 Bad Gateway: Upstream error
├── 503 Unavailable: Maintenance
└── 504 Gateway Timeout: Upstream timeout

gRPC Patterns

Service Types:
├── Unary: request → response
├── Server Streaming: request → stream<response>
├── Client Streaming: stream<request> → response
└── Bidirectional: stream<request> → stream<response>

Proto Best Practices:
├── Use proto3
├── Package: company.service.v1
├── Reserve deleted field numbers
├── Use well-known types
└── Backward compatible changes only

GraphQL Patterns

Schema Design:
├── Types: Clear domain modeling
├── Queries: Read operations
├── Mutations: Write operations
├── Subscriptions: Real-time
└── Input types: Separate from output

Security:
├── Query depth limiting
├── Complexity analysis
├── Field-level authorization
├── Persisted queries
└── Rate limiting by complexity

Retry Logic

Client Retry Configuration

retry_config:
  http_client:
    max_attempts: 3
    initial_delay_ms: 100
    max_delay_ms: 10000
    multiplier: 2.0
    jitter_factor: 0.2

  retryable_status_codes:
    - 429  # Rate limited (use Retry-After)
    - 502  # Bad gateway
    - 503  # Service unavailable
    - 504  # Gateway timeout

  non_retryable:
    - 400  # Bad request
    - 401  # Unauthorized
    - 403  # Forbidden
    - 404  # Not found
    - 409  # Conflict
    - 422  # Unprocessable

  idempotency:
    header: "Idempotency-Key"
    required_for: [POST, PATCH]
    cache_ttl_seconds: 86400

Logging & Observability

Log Format

log_schema:
  level: { type: string }
  timestamp: { type: string, format: ISO8601 }
  skill: { type: string, value: "api-architecture" }
  request_id: { type: string }
  event:
    type: string
    enum:
      - endpoint_designed
      - schema_generated
      - validation_passed
      - security_configured
      - rate_limit_set
  context:
    type: object
    properties:
      method: { type: string }
      path: { type: string }
      protocol: { type: string }

example:
  level: INFO
  request_id: "req_abc123"
  event: endpoint_designed
  context:
    method: POST
    path: /v1/users
    protocol: REST

Metrics

metrics:
  - name: api_request_total
    type: counter
    labels: [method, path, status]

  - name: api_request_duration_seconds
    type: histogram
    labels: [method, path]
    buckets: [0.005, 0.01, 0.05, 0.1, 0.5, 1, 5]

  - name: api_rate_limit_exceeded_total
    type: counter
    labels: [client_id, path]

  - name: api_error_total
    type: counter
    labels: [method, path, error_code]

Troubleshooting

Common Issues

Issue Cause Resolution
400 errors Schema mismatch Validate against OpenAPI
401 errors Token expired Implement refresh flow
429 errors Rate limit hit Implement backoff, cache
CORS errors Missing headers Configure allowed origins
Slow response N+1 queries Batch, DataLoader

Debug Checklist

□ Request matches OpenAPI spec?
□ Auth token valid and not expired?
□ Rate limit headers checked?
□ Error response format consistent?
□ Retry-After header on 429/503?
□ CORS configured for all origins?
□ Pagination implemented?

Unit Test Templates

API Validation Tests

# test_api_architecture.py

def test_valid_rest_resource():
    params = {
        "api_context": {
            "protocol": "REST",
            "resources": [
                {"name": "users", "operations": ["list", "get", "create", "update", "delete"]},
                {"name": "orders", "operations": ["list", "get", "create"]}
            ],
            "consumers": ["web", "mobile"],
            "security": {"auth_method": "oauth2", "rate_limiting": True}
        }
    }
    result = validate_parameters(params)
    assert result.valid == True

def test_invalid_resource_naming():
    params = {
        "api_context": {
            "protocol": "REST",
            "resources": [
                {"name": "Users", "operations": ["list"]}  # Should be lowercase
            ]
        }
    }
    result = validate_parameters(params)
    assert result.valid == False
    assert "lowercase" in result.errors[0]

def test_public_api_requires_auth():
    params = {
        "api_context": {
            "protocol": "REST",
            "resources": [{"name": "data", "operations": ["list"]}],
            "consumers": ["third_party"]
            # Missing security.auth_method
        }
    }
    result = validate_parameters(params)
    assert result.valid == False
    assert "authentication" in result.errors[0]

def test_endpoint_generation():
    resource = {"name": "users", "operations": ["list", "get", "create"]}
    endpoints = generate_endpoints(resource)

    assert endpoints[0] == {"method": "GET", "path": "/v1/users"}
    assert endpoints[1] == {"method": "GET", "path": "/v1/users/{id}"}
    assert endpoints[2] == {"method": "POST", "path": "/v1/users"}

Status Code Tests

def test_status_code_for_create():
    operation = "create"
    result = determine_status_codes(operation)
    assert 201 in result.success
    assert 400 in result.client_error
    assert 409 in result.client_error  # Conflict for duplicate

def test_rate_limit_headers():
    response = generate_rate_limit_headers(
        limit=1000,
        remaining=998,
        reset_epoch=1640995200
    )
    assert response["X-RateLimit-Limit"] == "1000"
    assert response["X-RateLimit-Remaining"] == "998"
    assert response["X-RateLimit-Reset"] == "1640995200"

def test_error_response_format():
    error = generate_error_response(
        code="VALIDATION_ERROR",
        message="Invalid email format",
        details=[{"field": "email", "reason": "must be valid email"}],
        request_id="req_123"
    )
    assert error["error"]["code"] == "VALIDATION_ERROR"
    assert error["error"]["request_id"] == "req_123"
    assert len(error["error"]["details"]) == 1

Version History

Version Date Changes
2.0.0 2025-01 Production-grade rewrite with security patterns
1.0.0 2024-12 Initial release