Claude-skill-registry designing-apis
Guides REST and GraphQL API design, endpoint patterns, request/response schemas, versioning, and API best practices. Use when building APIs, designing endpoints, or reviewing API contracts.
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/designing-apis-cloudai-x-opencode-workflow" ~/.claude/skills/majiayu000-claude-skill-registry-designing-apis-aca0a7 && rm -rf "$T"
manifest:
skills/data/designing-apis-cloudai-x-opencode-workflow/SKILL.mdsource content
Designing APIs
Principles and patterns for designing clean, consistent, and maintainable APIs.
When to Use This Skill
- Designing new API endpoints
- Reviewing API contracts
- Planning API versioning strategies
- Defining request/response schemas
- Building GraphQL schemas
- Documenting APIs
REST API Design Principles
Resource-Oriented Design
APIs should be organized around resources, not actions:
GOOD (Resource-oriented): GET /users → List users GET /users/123 → Get user 123 POST /users → Create user PUT /users/123 → Update user 123 DELETE /users/123 → Delete user 123 BAD (Action-oriented): POST /getUsers POST /createUser POST /updateUser POST /deleteUser
HTTP Method Semantics
| Method | Purpose | Idempotent | Safe | Request Body |
|---|---|---|---|---|
| GET | Retrieve resource(s) | Yes | Yes | No |
| POST | Create resource | No | No | Yes |
| PUT | Replace resource | Yes | No | Yes |
| PATCH | Partial update | Yes | No | Yes |
| DELETE | Remove resource | Yes | No | Optional |
URL Structure Patterns
Collection: /users Item: /users/{id} Nested: /users/{id}/posts Action: /users/{id}/activate (POST only, for non-CRUD) Filter: /users?status=active&role=admin Pagination: /users?page=2&limit=20 Sort: /users?sort=created_at&order=desc
Request Design
Path Parameters vs Query Parameters
| Use | Path Parameters | Query Parameters |
|---|---|---|
| Resource identification | | - |
| Required filters | | - |
| Optional filters | - | |
| Pagination | - | |
| Sorting | - | |
| Search | - | |
Request Body Patterns
// POST /users - Create { "email": "user@example.com", "name": "John Doe", "role": "admin" } // PATCH /users/123 - Partial update { "name": "Jane Doe" } // Bulk operations - POST /users/bulk { "operations": [ { "action": "create", "data": { "email": "..." } }, { "action": "update", "id": "123", "data": { "name": "..." } } ] }
Response Design
Consistent Response Envelope
// Success response { "data": { ... }, "meta": { "timestamp": "2024-01-15T10:30:00Z", "requestId": "abc123" } } // Collection response with pagination { "data": [ ... ], "meta": { "total": 100, "page": 2, "limit": 20, "hasMore": true } } // Error response { "error": { "code": "VALIDATION_ERROR", "message": "Invalid request data", "details": [ { "field": "email", "message": "Invalid email format" } ] }, "meta": { "timestamp": "2024-01-15T10:30:00Z", "requestId": "abc123" } }
HTTP Status Code Guidelines
| Range | Category | Common Codes |
|---|---|---|
| 2xx | Success | 200 OK, 201 Created, 204 No Content |
| 3xx | Redirect | 301 Moved, 304 Not Modified |
| 4xx | Client Error | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 422 Unprocessable |
| 5xx | Server Error | 500 Internal, 502 Bad Gateway, 503 Unavailable |
Status Code Decision Tree
Success? ├─ Yes │ ├─ Returning data? → 200 OK │ ├─ Created resource? → 201 Created │ └─ No content? → 204 No Content └─ No ├─ Client's fault? │ ├─ Bad syntax? → 400 Bad Request │ ├─ Not authenticated? → 401 Unauthorized │ ├─ Not authorized? → 403 Forbidden │ ├─ Not found? → 404 Not Found │ └─ Validation failed? → 422 Unprocessable Entity └─ Server's fault? → 500 Internal Server Error
API Versioning Strategies
URL Path Versioning (Recommended)
/api/v1/users /api/v2/users
Pros: Explicit, easy to understand, easy to route Cons: URL changes between versions
Header Versioning
GET /api/users Accept: application/vnd.myapi.v2+json
Pros: Clean URLs Cons: Hidden version, harder to test
Query Parameter Versioning
/api/users?version=2
Pros: Flexible, easy to test Cons: Can be forgotten, pollutes query string
GraphQL Design Patterns
Schema-First Design
type User { id: ID! email: String! name: String! posts: [Post!]! createdAt: DateTime! } type Post { id: ID! title: String! content: String! author: User! createdAt: DateTime! } type Query { user(id: ID!): User users(filter: UserFilter, page: PageInput): UserConnection! } type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! deleteUser(id: ID!): Boolean! }
Input Types Pattern
input CreateUserInput { email: String! name: String! role: Role = USER } input UpdateUserInput { email: String name: String role: Role } input UserFilter { status: UserStatus role: Role search: String }
Pagination Patterns
# Cursor-based (recommended for large datasets) type UserConnection { edges: [UserEdge!]! pageInfo: PageInfo! } type UserEdge { node: User! cursor: String! } type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String } # Offset-based (simpler, for smaller datasets) type UserList { items: [User!]! total: Int! page: Int! limit: Int! }
Authentication & Authorization
Authentication Patterns
| Pattern | Use Case | Header |
|---|---|---|
| Bearer Token | Standard API auth | |
| API Key | Server-to-server | |
| Basic Auth | Simple/legacy systems | |
| OAuth 2.0 | Third-party integration | OAuth flow |
Authorization Responses
Not authenticated → 401 Unauthorized (User identity unknown) Not authorized → 403 Forbidden (User known, but lacks permission)
Error Handling Patterns
Standardized Error Format
{ "error": { "code": "RESOURCE_NOT_FOUND", "message": "User with ID 123 not found", "target": "user", "details": [ { "code": "INVALID_ID", "message": "The provided ID does not exist", "target": "id" } ], "innererror": { "trace": "abc123", "timestamp": "2024-01-15T10:30:00Z" } } }
Common Error Codes
| Code | HTTP Status | When |
|---|---|---|
| 400/422 | Request data invalid |
| 401 | Auth required |
| 403 | Insufficient permissions |
| 404 | Resource doesn't exist |
| 409 | State conflict (duplicate) |
| 429 | Too many requests |
| 500 | Server failure |
API Documentation
OpenAPI/Swagger Structure
openapi: 3.0.3 info: title: My API version: 1.0.0 paths: /users: get: summary: List users parameters: - name: status in: query schema: type: string enum: [active, inactive] responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/UserList' components: schemas: User: type: object required: [id, email] properties: id: type: string email: type: string format: email
Anti-Patterns to Avoid
- Verbs in URLs - Use
not/users/getUsers - Ignoring HTTP Methods - Use proper methods, not POST for everything
- Inconsistent Naming - Pick snake_case or camelCase, stick with it
- Leaking Implementation - Don't expose internal IDs or DB structure
- Missing Pagination - Always paginate collections
- Ignoring Idempotency - PUT/DELETE must be idempotent
- No Versioning - Plan for API evolution from day one
Quick Reference
RESOURCE DESIGN: /resources → Collection /resources/{id} → Item /resources/{id}/sub → Nested HTTP METHODS: GET → Read (safe, idempotent) POST → Create (not idempotent) PUT → Replace (idempotent) PATCH → Update (idempotent) DELETE → Remove (idempotent) STATUS CODES: 200 OK, 201 Created, 204 No Content 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found 500 Internal Server Error VERSIONING: /api/v1/resources (recommended) PAGINATION: ?page=2&limit=20 (offset) ?cursor=abc123&limit=20 (cursor)