
Api Architect
- 157 installs
- 178 repo stars
- Updated July 14, 2026
- erichowens/some_claude_skills
Design API boundaries, resources, auth flows, versioning, and integration contracts before implementation so services stay consistent, evolvable, and consumable by web, mobile, and partner clients.
About
api-architect from erichowens/some_claude_skills supports validate-stage API design. It scopes resources, authentication, versioning, and integration contracts before backend implementation so SaaS, mobile, and partner consumers inherit a coherent, evolvable service boundary from the start.
- Resource and endpoint modeling
- Auth and versioning strategy
- Integration contract design
- Pre-implementation API review
- Cross-client consistency planning
Api Architect by the numbers
- 157 all-time installs (skills.sh)
- Ranked #2,381 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/erichowens/some_claude_skills --skill api-architectAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 157 |
|---|---|
| repo stars | ★ 178 |
| Last updated | July 14, 2026 |
| Repository | erichowens/some_claude_skills ↗ |
What it does
Design API boundaries, resources, auth flows, versioning, and integration contracts before implementation so services stay consistent, evolvable, and consumable by web, mobile, and partner clients.
Files
API Architect
Expert API designer specializing in REST, GraphQL, gRPC, and WebSocket architectures.
Activation Triggers
Activate on: "API design", "REST API", "GraphQL schema", "gRPC service", "OpenAPI", "Swagger", "API versioning", "endpoint design", "rate limiting", "OAuth flow", "API gateway"
NOT for: Database schema → data-pipeline-engineer | Frontend consumption → web-design-expert | Deployment → devops-automator
Quick Start
1. Define API contract first (API-first design) 2. Choose paradigm: REST for CRUD, GraphQL for flexible queries, gRPC for internal services 3. Write the spec: OpenAPI for REST, SDL for GraphQL, .proto for gRPC 4. Design error responses with consistent structure 5. Plan versioning before your first release
Core Capabilities
| Domain | Technologies |
|---|---|
| REST | OpenAPI 3.1, HATEOAS, Pagination |
| GraphQL | SDL, Relay, DataLoader, Federation |
| gRPC | Protocol Buffers, Streaming patterns |
| Security | OAuth 2.0, JWT, API Keys, RBAC |
| DX | Swagger UI, SDK generation, Sandboxes |
Architecture Patterns
API-First Development
Design Contract → Generate Stubs → Implement → Test Against SpecResponse Envelope
success: { data: <resource>, meta: { page, total } }
error: { error: { code, message, details: [{ field, issue }] } }Versioning Options
- URL:
/v1/users(most explicit) - Header:
Accept: application/vnd.api+json;version=1 - Query:
/users?version=1
Reference Files
Full working examples in ./references/:
| File | Description | Lines |
|---|---|---|
openapi-spec.yaml | Complete OpenAPI 3.1 spec | 162 |
graphql-schema.graphql | GraphQL with Relay connections | 111 |
grpc-service.proto | Protocol Buffer, all streaming | 95 |
rate-limiting.yaml | Tier-based rate limit config | 85 |
api-security.yaml | Auth, CORS, security headers | 130 |
Anti-Patterns (AVOID These)
1. Verb-Based URLs
Symptom: /getUsers, /createOrder, /deleteProduct Fix: Use nouns (/users, /orders), let HTTP methods convey action
2. Inconsistent Response Envelopes
Symptom: {data: [...]} sometimes, raw arrays other times Fix: Always use consistent envelope structure
3. Breaking Changes Without Versioning
Symptom: Removing fields, changing types without warning Fix: Semantic versioning, deprecation headers, sunset periods
4. N+1 in GraphQL
Symptom: Resolver queries database per item in list Fix: DataLoader pattern for batching, @defer for large payloads
5. Over-fetching REST Endpoints
Symptom: /users returns 50 fields when clients need 3 Fix: Sparse fieldsets (?fields=id,name,email) or GraphQL
6. Missing Pagination
Symptom: List endpoints return all records Fix: Default limits, cursor-based pagination, hasMore indicator
7. No Idempotency Keys
Symptom: Duplicate POST requests create duplicate resources Fix: Accept Idempotency-Key header, return cached response
8. Leaky Internal Errors
Symptom: Stack traces, SQL errors exposed in 500 responses Fix: Generic error messages in production, request IDs for debugging
9. Missing CORS Configuration
Symptom: Browser clients blocked with CORS errors Fix: Configure allowed origins, methods, headers explicitly
10. No Rate Limiting
Symptom: API vulnerable to abuse, no usage visibility Fix: Implement limits per tier, return X-RateLimit-* headers
Validation Script
Run ./scripts/validate-api-spec.sh to check:
- OpenAPI specs for versions, security schemes, operationIds
- GraphQL schemas for Query types, pagination, error handling
- Protocol Buffers for syntax, packages, field numbers
- Common issues like hardcoded URLs, missing versioning
Quality Checklist
[ ] All endpoints use nouns, not verbs
[ ] Consistent response envelope structure
[ ] Error responses include codes and actionable messages
[ ] Pagination on all list endpoints
[ ] Authentication/authorization documented
[ ] Rate limit headers defined
[ ] Versioning strategy documented
[ ] CORS configured for known origins
[ ] Idempotency keys for mutating operations
[ ] OpenAPI spec validates without errors
[ ] SDK generation tested
[ ] Examples for all request/response typesOutput Artifacts
1. OpenAPI Specifications - Complete API contracts 2. GraphQL Schemas - Type definitions with connections 3. Protocol Buffers - gRPC service definitions 4. API Documentation - Developer guides 5. SDK Examples - Client code samples 6. Postman Collections - API test suites
Tools Available
Read,Write,Edit- File operations for specsBash(npm:*, npx:*)- OpenAPI linting, code generationBash(openapi-generator:*)- SDK generation
Changelog
All notable changes to the api-architect skill will be documented in this file.
[2.0.0] - 2024-12-12
Changed
- BREAKING: Restructured SKILL.md from 561 lines to ~170 lines for progressive disclosure
- Moved all large code examples to
./references/directory - Expanded anti-patterns section from 5 to 10 patterns
Added
references/openapi-spec.yaml- Complete OpenAPI 3.1 specification examplereferences/graphql-schema.graphql- Full GraphQL schema with Relay connectionsreferences/grpc-service.proto- Protocol Buffer with all streaming patternsreferences/rate-limiting.yaml- Tier-based rate limiting configurationreferences/api-security.yaml- Authentication, authorization, and security headersscripts/validate-api-spec.sh- Validation script for OpenAPI, GraphQL, and Protobuf- New anti-patterns: Inconsistent Naming, Missing Pagination, No Idempotency, Leaky Abstractions, Missing CORS
- Expanded quality checklist with 12 items
- Version number in frontmatter
Removed
- Inline code examples (now in references/)
- Redundant capability descriptions
[1.0.0] - 2024-12-10
Added
- Initial release
- REST API design patterns
- GraphQL schema design
- gRPC service definitions
- API security patterns
- Rate limiting design
- Developer experience guidelines
# API Security Patterns Reference
# Complete security configuration for authentication, authorization, and protection
# Authentication methods
authentication:
# API Key authentication
api_key:
header: "X-API-Key"
query_param: "api_key" # Fallback (not recommended)
format: "prefix_random" # e.g., "sk_live_abc123..."
rotation_period_days: 90
# JWT Bearer token
jwt:
header: "Authorization"
scheme: "Bearer"
algorithm: "RS256" # Prefer asymmetric for microservices
issuer: "https://auth.example.com"
audience: "https://api.example.com"
expiration_minutes: 15
refresh_token_days: 7
claims:
required: ["sub", "iat", "exp", "aud"]
optional: ["scope", "role", "tenant_id"]
# OAuth 2.0 flows
oauth2:
authorization_endpoint: "https://auth.example.com/authorize"
token_endpoint: "https://auth.example.com/token"
scopes:
read: "Read access to resources"
write: "Write access to resources"
delete: "Delete access to resources"
admin: "Administrative operations"
flows:
authorization_code:
use_case: "Web applications with backend"
pkce_required: true
client_credentials:
use_case: "Service-to-service"
device_code:
use_case: "CLI tools, TV apps"
# Authorization patterns
authorization:
# Role-based access control
rbac:
roles:
viewer:
permissions: ["read:users", "read:posts"]
editor:
permissions: ["read:*", "write:users", "write:posts"]
admin:
permissions: ["*"]
inheritance:
admin: ["editor"]
editor: ["viewer"]
# Attribute-based access control
abac:
policies:
- name: "own_resources"
condition: "resource.owner_id == user.id"
effect: "allow"
- name: "tenant_isolation"
condition: "resource.tenant_id == user.tenant_id"
effect: "allow"
- name: "time_restricted"
condition: "current_time.hour >= 9 AND current_time.hour <= 17"
effect: "allow"
# Input validation
validation:
# Request body limits
max_body_size: "1MB"
max_json_depth: 10
max_array_length: 1000
# Common patterns
patterns:
email: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
uuid: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
phone: "^\\+[1-9]\\d{1,14}$"
# Sanitization
sanitize:
html: "escape" # Escape HTML entities
sql: "parameterize" # Use parameterized queries
path: "normalize" # Prevent path traversal
# CORS configuration
cors:
allowed_origins:
- "https://app.example.com"
- "https://admin.example.com"
allowed_methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
allowed_headers: ["Authorization", "Content-Type", "X-Request-ID"]
exposed_headers: ["X-RateLimit-Remaining", "X-Request-ID"]
max_age: 86400 # 24 hours
credentials: true
# Security headers
security_headers:
Strict-Transport-Security: "max-age=31536000; includeSubDomains"
X-Content-Type-Options: "nosniff"
X-Frame-Options: "DENY"
X-XSS-Protection: "1; mode=block"
Content-Security-Policy: "default-src 'self'"
Referrer-Policy: "strict-origin-when-cross-origin"
# Error handling (don't leak information)
error_handling:
production:
include_stack_trace: false
include_internal_message: false
generic_500_message: "An unexpected error occurred"
development:
include_stack_trace: true
include_internal_message: true
# Audit logging
audit:
events:
- "authentication.success"
- "authentication.failure"
- "authorization.denied"
- "resource.created"
- "resource.updated"
- "resource.deleted"
- "api_key.rotated"
include:
- "timestamp"
- "user_id"
- "ip_address"
- "user_agent"
- "request_id"
- "endpoint"
- "method"
- "response_code"
# GraphQL Schema Reference
# Complete schema with queries, mutations, subscriptions, and Relay connections
type Query {
user(id: ID!): User
users(
first: Int = 20
after: String
filter: UserFilter
): UserConnection!
me: User
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
deleteUser(id: ID!): DeleteUserPayload!
}
type Subscription {
userCreated: User!
userUpdated(id: ID): User!
}
type User {
id: ID!
email: String!
name: String
posts(first: Int = 10): PostConnection!
createdAt: DateTime!
updatedAt: DateTime
}
# Relay-style connections for pagination
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type UserEdge {
cursor: String!
node: User!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
# Filters
input UserFilter {
email: StringFilter
createdAt: DateTimeFilter
}
input StringFilter {
eq: String
contains: String
startsWith: String
}
input DateTimeFilter {
after: DateTime
before: DateTime
}
# Mutation inputs
input CreateUserInput {
email: String!
name: String
}
input UpdateUserInput {
name: String
email: String
}
# Mutation payloads with errors
type CreateUserPayload {
user: User
errors: [UserError!]
}
type UpdateUserPayload {
user: User
errors: [UserError!]
}
type DeleteUserPayload {
deletedId: ID
errors: [UserError!]
}
type UserError {
field: String
message: String!
code: ErrorCode!
}
enum ErrorCode {
VALIDATION_ERROR
DUPLICATE_EMAIL
NOT_FOUND
UNAUTHORIZED
}
scalar DateTime
// gRPC Service Reference
// Complete Protocol Buffer definition with all streaming patterns
syntax = "proto3";
package user.v1;
option go_package = "github.com/example/user/v1;userv1";
import "google/protobuf/timestamp.proto";
import "google/protobuf/field_mask.proto";
// UserService demonstrates all gRPC communication patterns
service UserService {
// Unary RPC - Single request, single response
rpc GetUser(GetUserRequest) returns (User);
// Unary RPC - Create operation
rpc CreateUser(CreateUserRequest) returns (User);
// Unary RPC - Update with field mask
rpc UpdateUser(UpdateUserRequest) returns (User);
// Server streaming - Watch for changes
rpc WatchUsers(WatchUsersRequest) returns (stream UserEvent);
// Client streaming - Bulk operations
rpc BulkCreateUsers(stream CreateUserRequest) returns (BulkCreateResponse);
// Bidirectional streaming - Real-time sync
rpc SyncUsers(stream SyncRequest) returns (stream SyncResponse);
}
// Core domain message
message User {
string id = 1;
string email = 2;
string name = 3;
google.protobuf.Timestamp created_at = 4;
google.protobuf.Timestamp updated_at = 5;
}
// Request messages
message GetUserRequest {
string id = 1;
}
message CreateUserRequest {
string email = 1;
string name = 2;
}
message UpdateUserRequest {
string id = 1;
User user = 2;
google.protobuf.FieldMask update_mask = 3; // Partial update support
}
message WatchUsersRequest {
repeated string user_ids = 1; // Empty = watch all
}
// Event message for streaming
message UserEvent {
enum EventType {
EVENT_TYPE_UNSPECIFIED = 0;
EVENT_TYPE_CREATED = 1;
EVENT_TYPE_UPDATED = 2;
EVENT_TYPE_DELETED = 3;
}
EventType type = 1;
User user = 2;
google.protobuf.Timestamp timestamp = 3;
}
// Bulk operation response
message BulkCreateResponse {
int32 created_count = 1;
repeated string created_ids = 2;
repeated Error errors = 3;
}
// Standard error message
message Error {
string code = 1;
string message = 2;
map<string, string> metadata = 3;
}
// Bidirectional sync messages
message SyncRequest {
oneof payload {
User user = 1;
string delete_id = 2;
}
}
message SyncResponse {
bool success = 1;
string id = 2;
Error error = 3;
}
# OpenAPI 3.1 Specification Reference
# Complete REST API specification example
openapi: 3.1.0
info:
title: User Service API
version: 1.0.0
description: Manages user accounts and profiles
servers:
- url: https://api.example.com/v1
description: Production
paths:
/users:
get:
operationId: listUsers
summary: List all users
parameters:
- name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
- name: cursor
in: query
schema:
type: string
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/UserList'
post:
operationId: createUser
summary: Create a new user
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: Created
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/users/{userId}:
parameters:
- name: userId
in: path
required: true
schema:
type: string
format: uuid
get:
operationId: getUser
summary: Get user by ID
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: Not Found
components:
schemas:
User:
type: object
required: [id, email, createdAt]
properties:
id:
type: string
format: uuid
email:
type: string
format: email
name:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
CreateUserRequest:
type: object
required: [email]
properties:
email:
type: string
format: email
name:
type: string
minLength: 1
maxLength: 100
UserList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
meta:
type: object
properties:
nextCursor:
type: string
hasMore:
type: boolean
ValidationError:
type: object
properties:
error:
type: object
properties:
code:
type: string
enum: [VALIDATION_ERROR]
message:
type: string
details:
type: array
items:
type: object
properties:
field:
type: string
issue:
type: string
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: []
# Rate Limiting Design Reference
# Complete rate limiting configuration with tiers, headers, and responses
# Tier-based rate limits
tiers:
free:
requests_per_minute: 60
requests_per_day: 1000
burst: 10
description: "Basic tier for evaluation and small projects"
starter:
requests_per_minute: 300
requests_per_day: 10000
burst: 50
description: "For small production applications"
pro:
requests_per_minute: 600
requests_per_day: 50000
burst: 100
description: "For growing production workloads"
enterprise:
requests_per_minute: 6000
requests_per_day: unlimited
burst: 1000
description: "Custom limits negotiated per contract"
# Rate limit response headers (always include these)
headers:
X-RateLimit-Limit: "60" # Max requests allowed in current window
X-RateLimit-Remaining: "45" # Requests remaining in current window
X-RateLimit-Reset: "1640000000" # Unix timestamp when window resets
X-RateLimit-Policy: "60;w=60" # Policy: 60 requests per 60 seconds
Retry-After: "30" # Seconds until retry (only on 429)
# Sliding window configuration
sliding_window:
window_size_seconds: 60
precision: 1 # 1-second granularity
algorithm: "sliding_log" # Options: fixed_window, sliding_log, token_bucket
# Token bucket (alternative algorithm)
token_bucket:
capacity: 100 # Maximum tokens
refill_rate: 10 # Tokens added per second
initial_tokens: 100 # Starting tokens
# Per-endpoint limits (override tier limits)
endpoint_limits:
"/auth/token":
requests_per_minute: 5
burst: 2
reason: "Prevent brute force attacks"
"/search":
requests_per_minute: 30
burst: 5
reason: "Expensive operation"
"/export":
requests_per_hour: 10
burst: 1
reason: "Very expensive, generates large files"
# 429 Too Many Requests response
error_response:
status: 429
headers:
Content-Type: "application/json"
Retry-After: "30"
body:
error:
code: "RATE_LIMIT_EXCEEDED"
message: "Too many requests. Please retry after 30 seconds."
retryAfter: 30
limit: 60
window: "1 minute"
documentation: "https://api.example.com/docs/rate-limits"
# Graceful degradation
degradation:
soft_limit: 0.8 # At 80% of limit, add warning header
headers_at_soft_limit:
X-RateLimit-Warning: "Approaching rate limit"
# IP-based vs API-key-based
identification:
primary: "api_key" # X-API-Key header
fallback: "client_ip" # For unauthenticated requests
header_name: "X-API-Key"
# Exempt paths (no rate limiting)
exempt_paths:
- "/health"
- "/metrics"
- "/.well-known/*"
#!/bin/bash
# API Architect Skill Validation Script
# Validates API specifications for common issues and best practices
set -e
ERRORS=0
WARNINGS=0
echo "═══════════════════════════════════════════════════════════════"
echo "API Architect Skill Validator"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Check for OpenAPI specifications
check_openapi() {
echo "📋 Checking OpenAPI specifications..."
for spec in *.yaml *.yml openapi/*.yaml openapi/*.yml api/*.yaml api/*.yml; do
[ -f "$spec" ] || continue
# Check if it's an OpenAPI file
if ! grep -q "openapi:" "$spec" 2>/dev/null; then
continue
fi
echo " Checking: $spec"
# Check for version
if ! grep -qE "openapi:\s*(3\.[0-9]+\.[0-9]+)" "$spec" 2>/dev/null; then
echo "⚠️ WARN: $spec may be using outdated OpenAPI version (prefer 3.0+)"
((WARNINGS++))
fi
# Check for info section
if ! grep -q "^info:" "$spec" 2>/dev/null; then
echo "❌ ERROR: $spec missing info section"
((ERRORS++))
fi
# Check for servers
if ! grep -q "^servers:" "$spec" 2>/dev/null; then
echo "⚠️ WARN: $spec missing servers section"
((WARNINGS++))
fi
# Check for security schemes
if ! grep -q "securitySchemes:" "$spec" 2>/dev/null; then
echo "⚠️ WARN: $spec missing security schemes"
((WARNINGS++))
fi
# Check for operationId
if grep -q "get:\|post:\|put:\|patch:\|delete:" "$spec" 2>/dev/null; then
if ! grep -q "operationId:" "$spec" 2>/dev/null; then
echo "⚠️ WARN: $spec missing operationId (required for SDK generation)"
((WARNINGS++))
fi
fi
# Check for verb-based paths (anti-pattern)
if grep -qE "/get[A-Z]|/create[A-Z]|/update[A-Z]|/delete[A-Z]" "$spec" 2>/dev/null; then
echo "❌ ERROR: $spec contains verb-based URLs (use nouns, let HTTP methods convey action)"
((ERRORS++))
fi
# Check for consistent error schemas
if grep -q "responses:" "$spec" 2>/dev/null; then
if ! grep -qE "'4[0-9]{2}':|\"4[0-9]{2}\":" "$spec" 2>/dev/null; then
echo "⚠️ WARN: $spec missing 4xx error responses"
((WARNINGS++))
fi
fi
done
}
# Check GraphQL schemas
check_graphql() {
echo ""
echo "🔷 Checking GraphQL schemas..."
for schema in *.graphql schema/*.graphql graphql/*.graphql; do
[ -f "$schema" ] || continue
echo " Checking: $schema"
# Check for Query type
if ! grep -q "type Query" "$schema" 2>/dev/null; then
echo "❌ ERROR: $schema missing Query type"
((ERRORS++))
fi
# Check for Relay-style pagination
if grep -q "type.*Connection" "$schema" 2>/dev/null; then
if ! grep -q "type PageInfo" "$schema" 2>/dev/null; then
echo "⚠️ WARN: $schema has Connection types but missing PageInfo"
((WARNINGS++))
fi
fi
# Check for mutation payloads with errors
if grep -q "type Mutation" "$schema" 2>/dev/null; then
if ! grep -qE "errors:\s*\[" "$schema" 2>/dev/null; then
echo "⚠️ WARN: $schema mutations should return error arrays in payloads"
((WARNINGS++))
fi
fi
# Check for custom scalars
if grep -qE "DateTime|Date|JSON|UUID" "$schema" 2>/dev/null; then
if ! grep -q "scalar DateTime\|scalar Date\|scalar JSON\|scalar UUID" "$schema" 2>/dev/null; then
echo "⚠️ WARN: $schema uses custom types without scalar definitions"
((WARNINGS++))
fi
fi
done
}
# Check Protocol Buffer definitions
check_protobuf() {
echo ""
echo "🔌 Checking Protocol Buffer definitions..."
for proto in *.proto proto/*.proto; do
[ -f "$proto" ] || continue
echo " Checking: $proto"
# Check for syntax version
if ! grep -q 'syntax = "proto3"' "$proto" 2>/dev/null; then
echo "⚠️ WARN: $proto not using proto3 syntax"
((WARNINGS++))
fi
# Check for package definition
if ! grep -q "^package " "$proto" 2>/dev/null; then
echo "❌ ERROR: $proto missing package definition"
((ERRORS++))
fi
# Check for go_package option
if ! grep -q "option go_package" "$proto" 2>/dev/null; then
echo "⚠️ WARN: $proto missing go_package option"
((WARNINGS++))
fi
# Check for field numbers > 0
if grep -qE "=\s*0\s*;" "$proto" 2>/dev/null; then
# Check if it's in an enum (0 is required for enums)
if ! grep -B5 "= 0;" "$proto" | grep -q "enum" 2>/dev/null; then
echo "❌ ERROR: $proto has field number 0 (must be positive for messages)"
((ERRORS++))
fi
fi
done
}
# Check for common API design issues
check_common_issues() {
echo ""
echo "🔍 Checking for common API design issues..."
# Check for hardcoded localhost/IP addresses
for file in *.yaml *.yml *.json; do
[ -f "$file" ] || continue
if grep -qE "localhost|127\.0\.0\.1|0\.0\.0\.0" "$file" 2>/dev/null; then
if ! echo "$file" | grep -qE "dev|local|test" 2>/dev/null; then
echo "⚠️ WARN: $file contains localhost/IP (use environment variables)"
((WARNINGS++))
fi
fi
done
# Check for API versioning
has_versioning=false
if grep -rqE "/v[0-9]+/" *.yaml *.yml 2>/dev/null; then
has_versioning=true
fi
if grep -rq "version:" *.yaml *.yml 2>/dev/null | grep -qE "header|query" 2>/dev/null; then
has_versioning=true
fi
if [ "$has_versioning" = false ]; then
echo "ℹ️ INFO: No API versioning strategy detected"
fi
}
# Run all checks
check_openapi
check_graphql
check_protobuf
check_common_issues
# Summary
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "Validation Complete"
echo "═══════════════════════════════════════════════════════════════"
echo "Errors: $ERRORS"
echo "Warnings: $WARNINGS"
echo ""
if [ $ERRORS -gt 0 ]; then
echo "❌ Validation FAILED - fix errors before publishing API"
exit 1
elif [ $WARNINGS -gt 5 ]; then
echo "⚠️ Validation PASSED with warnings - review recommended"
exit 0
else
echo "✅ Validation PASSED"
exit 0
fi