Awesome-omni-skill api-design-patterns
Design robust APIs with RESTful patterns, GraphQL schemas, versioning strategies, and error handling conventions. Supports OpenAPI/Swagger documentation and SDK generation patterns. Triggers on API design, schema definition, endpoint architecture, or developer experience requests.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/api-design-patterns-organvm-iv-taxis" ~/.claude/skills/diegosouzapw-awesome-omni-skill-api-design-patterns-ec6e25 && rm -rf "$T"
manifest:
skills/development/api-design-patterns-organvm-iv-taxis/SKILL.mdsource content
API Design Patterns
Build APIs that developers love to use.
Design Principles
The Three Laws of API Design
- Predictable: Consistent patterns throughout
- Discoverable: Self-documenting, intuitive naming
- Evolvable: Can change without breaking clients
API-First Mindset
Design → Document → Mock → Build → Test → Deploy NOT: Build → Document (maybe) → Hope it works
REST Patterns
Resource Naming
# Collection GET /users # List users POST /users # Create user # Item GET /users/{id} # Get user PUT /users/{id} # Replace user PATCH /users/{id} # Update user DELETE /users/{id} # Delete user # Nested resources GET /users/{id}/posts # User's posts POST /users/{id}/posts # Create post for user # Actions (when CRUD doesn't fit) POST /users/{id}/activate POST /orders/{id}/cancel
Naming Conventions
| Do | Don't |
|---|---|
| , |
| |
| |
| Plural nouns | Verbs in URLs |
| Lowercase, hyphens | camelCase, underscores |
HTTP Methods
| Method | Purpose | Idempotent | Safe |
|---|---|---|---|
| GET | Read | Yes | Yes |
| POST | Create | No | No |
| PUT | Replace | Yes | No |
| PATCH | Update | No* | No |
| DELETE | Remove | Yes | No |
*PATCH can be idempotent if designed carefully
Status Codes
| Code | Meaning | Use When |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST with new resource |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Invalid input |
| 401 | Unauthorized | Missing/invalid auth |
| 403 | Forbidden | Valid auth, no permission |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate, state conflict |
| 422 | Unprocessable | Valid syntax, invalid semantics |
| 429 | Too Many Requests | Rate limited |
| 500 | Server Error | Unhandled server error |
Request/Response Patterns
Request Body
{ "email": "user@example.com", "name": "John Doe", "preferences": { "newsletter": true } }
Response: Single Resource
{ "data": { "id": "usr_123", "type": "user", "attributes": { "email": "user@example.com", "name": "John Doe", "createdAt": "2024-01-15T10:30:00Z" }, "relationships": { "organization": { "id": "org_456", "type": "organization" } } } }
Response: Collection
{ "data": [ { "id": "usr_123", "type": "user", ... }, { "id": "usr_124", "type": "user", ... } ], "meta": { "total": 150, "page": 1, "perPage": 20 }, "links": { "self": "/users?page=1", "next": "/users?page=2", "last": "/users?page=8" } }
Error Response
{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid request parameters", "details": [ { "field": "email", "code": "INVALID_FORMAT", "message": "Must be a valid email address" } ], "requestId": "req_abc123" } }
Pagination Patterns
Offset-Based
GET /users?page=2&perPage=20 GET /users?offset=20&limit=20
Pros: Simple, familiar Cons: Inconsistent with real-time data, slow on large datasets
Cursor-Based
GET /users?cursor=eyJpZCI6MTIzfQ&limit=20
Response:
{ "data": [...], "cursors": { "before": "eyJpZCI6MTAzfQ", "after": "eyJpZCI6MTIzfQ" }, "hasMore": true }
Pros: Consistent, performant Cons: Can't jump to page N
Keyset-Based
GET /users?after_id=123&limit=20
Pros: Very performant Cons: Requires sortable unique field
Filtering, Sorting, Search
Filtering
# Simple GET /users?status=active # Multiple values GET /users?status=active,pending # Operators GET /users?created_at[gte]=2024-01-01 GET /users?name[contains]=john # Nested GET /users?organization.name=Acme
Sorting
# Single field GET /users?sort=createdAt # Descending GET /users?sort=-createdAt # Multiple fields GET /users?sort=-createdAt,name
Field Selection
GET /users?fields=id,name,email GET /users?fields[user]=id,name&fields[posts]=title
Search
GET /users?q=john GET /users?search=john+doe
Versioning Strategies
URL Path (Recommended for major versions)
GET /v1/users GET /v2/users
Pros: Explicit, cacheable Cons: URL pollution
Header
GET /users Accept: application/vnd.api+json; version=2
Pros: Clean URLs Cons: Harder to test, less visible
Query Parameter
GET /users?version=2
Pros: Easy to test Cons: Breaks caching, URL pollution
Deprecation Pattern
Deprecation: true Sunset: Sat, 31 Dec 2024 23:59:59 GMT Link: </v2/users>; rel="successor-version"
Authentication Patterns
API Keys
# Header Authorization: Api-Key sk_live_abc123 # Query (avoid - logged in URLs) GET /users?api_key=sk_live_abc123 <!-- allow-secret -->
Bearer Tokens (OAuth2/JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Signing Requests (AWS-style)
Authorization: HMAC-SHA256 Credential=key/date/region/service, SignedHeaders=host;x-date, Signature=abc123
Rate Limiting
Headers
X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1640000000 Retry-After: 60
Response (429)
{ "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded", "retryAfter": 60 } }
Strategies
| Strategy | Description | Use Case |
|---|---|---|
| Fixed Window | X requests per minute | Simple limiting |
| Sliding Window | Rolling time window | Smoother limiting |
| Token Bucket | Burst allowance | Traffic spikes |
| Leaky Bucket | Constant rate | Steady throughput |
GraphQL Patterns
Schema Design
type User { id: ID! email: String! name: String posts(first: Int, after: String): PostConnection! createdAt: DateTime! } type Post { id: ID! title: String! content: String! author: User! } type PostConnection { edges: [PostEdge!]! pageInfo: PageInfo! } type Query { user(id: ID!): User users(filter: UserFilter, first: Int, after: String): UserConnection! } type Mutation { createUser(input: CreateUserInput!): CreateUserPayload! updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload! }
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Types | PascalCase | , |
| Fields | camelCase | , |
| Arguments | camelCase | , |
| Enums | SCREAMING_SNAKE | , |
| Mutations | verbNoun | , |
Error Handling
{ "data": null, "errors": [ { "message": "User not found", "locations": [{ "line": 2, "column": 3 }], "path": ["user"], "extensions": { "code": "NOT_FOUND", "timestamp": "2024-01-15T10:30:00Z" } } ] }
OpenAPI Documentation
Basic Structure
openapi: 3.0.3 info: title: My API version: 1.0.0 description: API description servers: - url: https://api.example.com/v1 description: Production paths: /users: get: summary: List users operationId: listUsers tags: [Users] parameters: - name: page in: query schema: type: integer default: 1 responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/UserList' components: schemas: User: type: object required: [id, email] properties: id: type: string format: uuid email: type: string format: email
Related Skills
Complementary Skills (Use Together)
- backend-implementation-patterns - Implement the APIs you design
- testing-patterns - Test your API endpoints
- deployment-cicd - Deploy and version your APIs
Alternative Skills (Similar Purpose)
- mcp-builder - If building MCP servers instead of REST/GraphQL APIs
Prerequisite Skills (Learn First)
- None required - this is a foundational design skill
References
- Full OpenAPI templatereferences/openapi-template.md
- Standard error code catalogreferences/error-codes.md
- Client SDK design patternsreferences/sdk-patterns.md