API Design Skill
Bonded to: api-development-agent
Quick Start
# Invoke api-design skill
"Design a REST API for user management with authentication"
"Implement JWT authentication for my FastAPI app"
"Generate OpenAPI documentation for my endpoints"
Instructions
- Analyze Requirements: Understand client needs and data flow
- Choose Paradigm: Select REST, GraphQL, or gRPC
- Design Endpoints: Create resource-oriented API structure
- Implement Security: Add authentication and authorization
- Document API: Generate OpenAPI specification
API Paradigm Selection
| Paradigm |
Best For |
Performance |
Complexity |
| REST |
Public APIs, CRUD, simple |
Good |
Low |
| GraphQL |
Complex data, mobile clients |
Good |
Medium |
| gRPC |
Internal services, real-time |
Excellent |
Medium |
| WebSocket |
Bi-directional real-time |
Excellent |
Medium |
Decision Tree
Client type?
│
├─→ Public/Third-party → REST
│
├─→ Mobile with complex data → GraphQL
│
├─→ Internal microservices
│ ├─→ High performance needed → gRPC
│ └─→ Standard HTTP preferred → REST
│
└─→ Real-time bi-directional → WebSocket
Examples
Example 1: REST API Design
# OpenAPI 3.1 Specification
openapi: 3.1.0
info:
title: User Management API
version: 1.0.0
paths:
/api/v1/users:
post:
summary: Create user
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUser'
responses:
'201':
description: User created
get:
summary: List users
parameters:
- name: page
in: query
schema:
type: integer
default: 1
responses:
'200':
description: User list
/api/v1/users/{id}:
get:
summary: Get user by ID
put:
summary: Update user
delete:
summary: Delete user
Example 2: JWT Authentication
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: dict) -> str:
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user_id: str = payload.get("sub")
if user_id is None:
raise credentials_exception
return user_id
except JWTError:
raise credentials_exception
Example 3: Rate Limiting
from fastapi import FastAPI, Request
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
app.state.limiter = limiter
@app.get("/api/v1/resource")
@limiter.limit("100/minute")
async def get_resource(request: Request):
return {"data": "rate limited endpoint"}
HTTP Status Codes
2xx Success
├── 200 OK → Standard success
├── 201 Created → Resource created
├── 204 No Content → Success, no body
4xx Client Error
├── 400 Bad Request → Invalid input
├── 401 Unauthorized → Auth required
├── 403 Forbidden → Permission denied
├── 404 Not Found → Resource not found
├── 422 Unprocessable → Validation error
├── 429 Too Many Reqs → Rate limited
5xx Server Error
├── 500 Internal Error → Server error
├── 502 Bad Gateway → Upstream error
├── 503 Unavailable → Service down
Troubleshooting
Common Issues
| Issue |
Cause |
Solution |
| 401 Unauthorized |
Invalid/expired token |
Check token, refresh if needed |
| CORS errors |
Missing headers |
Configure CORS middleware |
| 429 Rate Limited |
Too many requests |
Implement backoff, cache |
| Slow endpoints |
N+1 queries, no caching |
Optimize queries, add cache |
Debug Checklist
- Verify request format (headers, body)
- Check authentication:
curl -H "Authorization: Bearer <token>"
- Review API logs for errors
- Test with minimal example
- Validate against OpenAPI spec
Test Template
# tests/test_api.py
import pytest
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
class TestUserAPI:
def test_create_user_returns_201(self):
response = client.post(
"/api/v1/users",
json={"email": "test@example.com", "password": "secure123"}
)
assert response.status_code == 201
assert "id" in response.json()
def test_get_user_requires_auth(self):
response = client.get("/api/v1/users/123")
assert response.status_code == 401
def test_get_user_with_valid_token(self, auth_headers):
response = client.get("/api/v1/users/123", headers=auth_headers)
assert response.status_code == 200
References
See references/ directory for:
API_GUIDE.md - Detailed API patterns
openapi-template.yaml - OpenAPI starter template
Resources