Agent skill
api-design-patterns
Design RESTful APIs with proper HTTP methods, status codes, pagination, filtering, error responses, and OpenAPI documentation. Follows FastAPI best practices with Pydantic validation.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/documents/api-design-patterns-ils15-copilot-global-confi
SKILL.md
API Design Patterns Skill
When to Use
Use this skill when:
- Designing new API endpoints
- Reviewing API consistency
- Implementing pagination and filtering
- Creating error response formats
- Writing OpenAPI documentation
- Validating HTTP status codes
- Building request/response schemas
RESTful Design Principles
1. HTTP Methods
GET /users - List users
GET /users/{id} - Get single user
POST /users - Create user
PUT /users/{id} - Full update
PATCH /users/{id} - Partial update
DELETE /users/{id} - Delete user
2. Status Codes
2xx Success:
- 200 OK - Successful GET, PUT, PATCH
- 201 Created - Successful POST
- 204 No Content - Successful DELETE
4xx Client Errors:
- 400 Bad Request - Invalid input
- 401 Unauthorized - Not authenticated
- 403 Forbidden - Not authorized
- 404 Not Found - Resource not found
- 409 Conflict - Duplicate resource
- 422 Unprocessable - Validation error
5xx Server Errors:
- 500 Internal Error - Unexpected error
- 503 Service Unavail - Maintenance
3. Pagination Pattern
from pydantic import BaseModel
from typing import Generic, TypeVar, List
T = TypeVar('T')
class PaginatedResponse(BaseModel, Generic[T]):
items: List[T]
total: int
page: int
size: int
pages: int
class Config:
from_attributes = True
# Endpoint
@router.get("/users", response_model=PaginatedResponse[UserResponse])
async def list_users(
page: int = Query(1, ge=1),
size: int = Query(20, ge=1, le=100),
):
total = await user_service.count()
items = await user_service.get_page(page, size)
return PaginatedResponse(
items=items,
total=total,
page=page,
size=size,
pages=(total + size - 1) // size
)
4. Filtering Pattern
from typing import Optional
from fastapi import Query
@router.get("/products")
async def list_products(
# Search
q: Optional[str] = Query(None, min_length=2, max_length=100),
# Filters
category: Optional[str] = None,
min_price: Optional[float] = Query(None, ge=0),
max_price: Optional[float] = Query(None, ge=0),
in_stock: Optional[bool] = None,
# Sorting
sort_by: str = Query("created_at", regex="^(name|price|created_at)$"),
order: str = Query("desc", regex="^(asc|desc)$"),
# Pagination
page: int = Query(1, ge=1),
size: int = Query(20, ge=1, le=100),
):
return await product_service.search(
q=q, category=category,
min_price=min_price, max_price=max_price,
in_stock=in_stock,
sort_by=sort_by, order=order,
page=page, size=size
)
5. Error Response Format
from pydantic import BaseModel
from typing import Optional, List
class ErrorDetail(BaseModel):
loc: List[str]
msg: str
type: str
class ErrorResponse(BaseModel):
error: str
message: str
details: Optional[List[ErrorDetail]] = None
request_id: Optional[str] = None
# Usage
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
return JSONResponse(
status_code=exc.status_code,
content=ErrorResponse(
error=exc.detail,
message=str(exc.detail),
request_id=request.state.request_id
).model_dump()
)
6. Request/Response Schemas
from pydantic import BaseModel, EmailStr, Field
from datetime import datetime
from typing import Optional
# Create (input)
class UserCreate(BaseModel):
email: EmailStr
name: str = Field(..., min_length=2, max_length=100)
password: str = Field(..., min_length=8)
# Update (partial)
class UserUpdate(BaseModel):
email: Optional[EmailStr] = None
name: Optional[str] = Field(None, min_length=2, max_length=100)
# Response (output)
class UserResponse(BaseModel):
id: int
email: str
name: str
created_at: datetime
class Config:
from_attributes = True
# List response
class UserListResponse(BaseModel):
id: int
name: str # Minimal fields for list
7. OpenAPI Documentation
@router.post(
"/users",
response_model=UserResponse,
status_code=201,
summary="Create a new user",
description="Register a new user account with email and password.",
responses={
201: {"description": "User created successfully"},
400: {"description": "Invalid input data"},
409: {"description": "Email already exists"},
},
tags=["users"],
)
async def create_user(user: UserCreate):
"""
Create a new user with the following information:
- **email**: valid email address (unique)
- **name**: user display name (2-100 chars)
- **password**: secure password (min 8 chars)
"""
return await user_service.create(user)
Output Format
## API Design Review
### Endpoints Analyzed
- GET /users - ✅ Correct
- POST /users - ⚠️ Missing 409 response
- DELETE /users/{id} - ❌ Returns 200 (should be 204)
### Issues Found
1. [Endpoint] - [Issue] - [Fix]
### Recommendations
1. Add pagination to list endpoints
2. Standardize error response format
3. Add request_id to all responses
Example Usage
@backend Design CRUD endpoints for products resource
@backend Review API consistency across all endpoints
@backend Add pagination to the orders list endpoint
@backend Create error response schema for the API
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?