Claude-skill-registry api-design-patterns
Comprehensive REST and GraphQL API design patterns with versioning, pagination, error handling, and HATEOAS principles. Use when designing APIs, defining endpoints, or architecting service contracts requiring production-grade patterns.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/api-design-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-api-design-patterns && rm -rf "$T"
manifest:
skills/data/api-design-patterns/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- references API keys
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
API Design Patterns
Expert guidance for designing scalable, maintainable REST and GraphQL APIs with industry-standard patterns for versioning, pagination, error handling, authentication, and service contracts.
When to Use This Skill
- Designing new REST or GraphQL APIs from scratch
- Refactoring existing APIs for better scalability and consistency
- Defining service contracts for microservices architectures
- Implementing versioning strategies for API evolution
- Standardizing error handling and response formats across services
- Designing pagination for large datasets
- Implementing HATEOAS or hypermedia-driven APIs
- Creating API specifications (OpenAPI, GraphQL Schema)
Core Principles
1. Resource-Oriented Design (REST)
URLs represent resources, not actions:
✓ GET /users/123 ✓ POST /users ✓ PUT /users/123 ✓ DELETE /users/123 ✗ GET /getUser?id=123 ✗ POST /createUser ✗ POST /deleteUser
Use HTTP methods semantically:
- GET: Retrieve resource(s), idempotent, cacheable
- POST: Create resource, non-idempotent
- PUT: Replace entire resource, idempotent
- PATCH: Partial update, idempotent
- DELETE: Remove resource, idempotent
2. Consistent Naming Conventions
Resources: /users, /orders, /products (plural nouns) Nested: /users/123/orders Collections: /users?status=active&page=2 Sub-resources: /users/123/settings Actions (rare): /users/123/activate (POST)
3. HTTP Status Codes
Success:
- 200 OK: Standard response for GET, PUT, PATCH
- 201 Created: Resource created (POST), return Location header
- 202 Accepted: Async processing started
- 204 No Content: Success with no response body (DELETE)
Client Errors:
- 400 Bad Request: Invalid syntax or validation failure
- 401 Unauthorized: Authentication required or failed
- 403 Forbidden: Authenticated but insufficient permissions
- 404 Not Found: Resource doesn't exist
- 409 Conflict: State conflict (duplicate, version mismatch)
- 422 Unprocessable Entity: Semantic validation failure
- 429 Too Many Requests: Rate limit exceeded
Server Errors:
- 500 Internal Server Error: Unexpected server failure
- 502 Bad Gateway: Upstream service failure
- 503 Service Unavailable: Temporary overload or maintenance
- 504 Gateway Timeout: Upstream timeout
Versioning Strategies
URI Versioning (Most Common)
GET /v1/users/123 GET /v2/users/123 Pros: Clear, easy to route, browser-testable Cons: URL proliferation, cache fragmentation When: Public APIs, major breaking changes
Header Versioning
GET /users/123 Accept: application/vnd.myapi.v2+json Pros: Clean URLs, content negotiation Cons: Harder to test, caching complexity When: Internal APIs, minor version differences
Query Parameter Versioning
GET /users/123?version=2 Pros: Simple, backward compatible Cons: Pollutes query space, inconsistent When: Rare, legacy compatibility
Deprecation Headers
Sunset: Sat, 31 Dec 2024 23:59:59 GMT Deprecation: true Link: <https://api.example.com/v2/users/123>; rel="successor-version"
Pagination Patterns
Offset-Based Pagination
GET /users?limit=20&offset=40 Response: { "data": [...], "pagination": { "limit": 20, "offset": 40, "total": 1543 }, "links": { "next": "/users?limit=20&offset=60", "prev": "/users?limit=20&offset=20" } } Pros: Simple, predictable, supports total count Cons: Inconsistent with concurrent writes, performance degrades When: Small datasets, stable data, admin UIs
Cursor-Based Pagination
GET /users?limit=20&cursor=eyJpZCI6MTIzfQ Response: { "data": [...], "pagination": { "next_cursor": "eyJpZCI6MTQzfQ", "has_more": true }, "links": { "next": "/users?limit=20&cursor=eyJpZCI6MTQzfQ" } } Pros: Consistent with writes, scalable, efficient Cons: No total count, can't jump to arbitrary page When: Large datasets, real-time feeds, infinite scroll
Keyset Pagination (Seek Method)
GET /users?limit=20&after_id=123&created_after=2024-01-01T00:00:00Z Pros: Most performant, index-friendly Cons: Requires sortable field, complex queries When: Very large datasets, time-series data
Error Response Format
Standard Error Schema
{ "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "details": [ { "field": "email", "code": "INVALID_FORMAT", "message": "Email format is invalid" }, { "field": "age", "code": "OUT_OF_RANGE", "message": "Age must be between 18 and 120" } ], "request_id": "req_a3f7c9b2", "timestamp": "2024-01-15T10:30:00Z", "documentation_url": "https://docs.api.com/errors/VALIDATION_ERROR" } }
Error Code Patterns
Format: CATEGORY_SPECIFIC_REASON Authentication: - AUTH_MISSING_TOKEN - AUTH_INVALID_TOKEN - AUTH_EXPIRED_TOKEN Authorization: - AUTHZ_INSUFFICIENT_PERMISSIONS - AUTHZ_RESOURCE_FORBIDDEN Validation: - VALIDATION_MISSING_FIELD - VALIDATION_INVALID_FORMAT - VALIDATION_OUT_OF_RANGE Business Logic: - BUSINESS_DUPLICATE_EMAIL - BUSINESS_INSUFFICIENT_BALANCE - BUSINESS_OPERATION_NOT_ALLOWED System: - SYSTEM_INTERNAL_ERROR - SYSTEM_SERVICE_UNAVAILABLE - SYSTEM_RATE_LIMIT_EXCEEDED
Filtering and Searching
Query Parameters for Filtering
GET /users?status=active&role=admin&created_after=2024-01-01 GET /users?search=john&fields=name,email GET /users?sort=-created_at,name # - prefix for descending
Complex Filtering (FIQL/RSQL)
GET /users?filter=status==active;role==admin,role==moderator # AND between semicolons, OR between commas GET /products?filter=price>100;price<500;category==electronics
Full-Text Search
GET /users?q=john+smith&fields=name,bio,company Response includes relevance scoring: { "data": [ { "id": 123, "name": "John Smith", "_score": 0.95 } ] }
Field Selection (Sparse Fieldsets)
GET /users/123?fields=id,name,email Response: { "id": 123, "name": "John Doe", "email": "john@example.com" } # Nested resources GET /users/123?fields=id,name,profile(avatar,bio) Benefits: - Reduced payload size - Faster response times - Lower bandwidth consumption - Better mobile performance
HATEOAS (Hypermedia)
HAL (Hypertext Application Language)
{ "id": 123, "name": "John Doe", "email": "john@example.com", "_links": { "self": { "href": "/users/123" }, "orders": { "href": "/users/123/orders" }, "update": { "href": "/users/123", "method": "PUT" }, "delete": { "href": "/users/123", "method": "DELETE" } }, "_embedded": { "recent_orders": [ { "id": 456, "total": 99.99, "_links": { "self": { "href": "/orders/456" } } } ] } }
JSON:API Format
{ "data": { "type": "users", "id": "123", "attributes": { "name": "John Doe", "email": "john@example.com" }, "relationships": { "orders": { "links": { "self": "/users/123/relationships/orders", "related": "/users/123/orders" } } }, "links": { "self": "/users/123" } } }
Rate Limiting Headers
X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 742 X-RateLimit-Reset: 1705320000 Retry-After: 3600 # Standard (RFC 6585) RateLimit-Limit: 1000 RateLimit-Remaining: 742 RateLimit-Reset: 3600
Authentication Patterns
Bearer Token (OAuth 2.0, JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs... Pros: Stateless, scalable, standard Cons: Token size, revocation complexity When: Modern APIs, microservices
API Key
X-API-Key: ak_live_a3f7c9b2d8e1f4g6h9 Pros: Simple, server-side management Cons: Less secure, harder to scope When: Internal services, admin APIs
Basic Auth
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= Pros: Simple, built-in browser support Cons: Credentials in every request When: Internal tools, development only
Idempotency
Idempotency Keys (POST)
POST /payments Idempotency-Key: a3f7c9b2-d8e1-4f6g-h9i0-j1k2l3m4n5o6 Content-Type: application/json { "amount": 100.00, "currency": "USD", "description": "Payment for order #123" } # Server stores key + response for 24 hours # Duplicate requests return cached response with 200 OK
Natural Idempotency
PUT /users/123 # Always idempotent DELETE /users/123 # Idempotent (404 on repeat) POST /users/123/follow # Use PUT for idempotency
Caching Strategies
ETags (Conditional Requests)
# Initial request GET /users/123 ETag: "a3f7c9b2" # Subsequent request GET /users/123 If-None-Match: "a3f7c9b2" # Response if unchanged: 304 Not Modified
Cache-Control Headers
# Never cache Cache-Control: no-store # Cache for 1 hour, revalidate Cache-Control: max-age=3600, must-revalidate # Cache forever (immutable) Cache-Control: public, max-age=31536000, immutable
GraphQL Patterns
Query Structure
query GetUser($id: ID!) { user(id: $id) { id name email orders(first: 10) { edges { node { id total status } } pageInfo { hasNextPage endCursor } } } }
Error Handling
{ "data": { "user": null }, "errors": [ { "message": "User not found", "locations": [{ "line": 2, "column": 3 }], "path": ["user"], "extensions": { "code": "NOT_FOUND", "userId": "123" } } ] }
Mutation Patterns
mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { user { id name email } errors { field message } } }
Best Practices Summary
- Consistency: Follow conventions across all endpoints
- Versioning: Plan deprecation strategy from day one
- Documentation: Use OpenAPI/GraphQL schemas, keep updated
- Error Handling: Detailed, actionable error messages with codes
- Security: Always use HTTPS, validate inputs, rate limit
- Performance: Implement caching, pagination, field selection
- Monitoring: Log request IDs, track latency and error rates
- Backward Compatibility: Additive changes only within versions
- Testing: Contract tests, integration tests, load tests
- Documentation: Interactive docs (Swagger UI, GraphQL Playground)
Anti-Patterns to Avoid
- Chatty APIs: Too many round trips (use batching, GraphQL)
- Over-fetching: Returning unnecessary data (use field selection)
- Under-fetching: Requiring multiple calls (use includes/embeds)
- Leaking Implementation: Exposing DB structure in API
- Poor Error Messages: Generic errors without details
- Breaking Changes: Modifying existing fields without versioning
- No Rate Limiting: Allowing resource exhaustion
- Missing Documentation: Undocumented endpoints and parameters
- Inconsistent Naming: Mixed conventions across endpoints
- Ignoring HTTP Semantics: Misusing status codes and methods
Resources
- REST: Roy Fielding's dissertation, RFC 7231 (HTTP semantics)
- OpenAPI: https://spec.openapis.org/oas/latest.html
- GraphQL: https://graphql.org/learn/
- HAL: https://stateless.group/hal_specification.html
- JSON:API: https://jsonapi.org/
- RFC 7807: Problem Details for HTTP APIs