Api design
Skills I use and develop to deliver better outcomes faster and with less effort.
npx -y skills add viktorbezdek/skillstack --skill api-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 10 stars10 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Design production-grade REST, GraphQL, gRPC, and Python library APIs with correct schemas, error contracts, auth, and versioning. Use when the user asks to design an API, define endpoints, create an OpenAPI/Swagger spec, design a GraphQL schema, build a gRPC service, model request/response with Pydantic, add pagination, or review API contracts. NOT for building MCP server tools (use mcp-server). NOT for Node.js/Express API routes or backend patterns (use backend-patterns or typescript-development).
SKILL.md
11.4 KB, as published. Nobody here has run it
API Design
Comprehensive API design skill combining REST, GraphQL, gRPC, and Python library architecture expertise with patterns, templates, and tools for production-grade APIs.
When to Activate
- Creating new API endpoints (REST, GraphQL, gRPC)
- Designing resource hierarchies and schemas
- Writing OpenAPI/Swagger specifications
- Implementing authentication and authorization
- Setting up pagination, filtering, and sorting
- Configuring rate limiting and CORS
- Designing Python library APIs
- Reviewing API designs in pull requests
Decision Tree: API Style Selection
What are you building?
+-- CRUD resources with clear entity model? --> REST
| Best for: resource-oriented operations, caching, wide tooling support
+-- Complex queries with varying client needs? --> GraphQL
| Best for: over-fetching prevention, nested data, multiple client types
+-- High-throughput service-to-service? --> gRPC
| Best for: low latency, strong typing, streaming, polyglot microservices
+-- Reusable Python package? --> Python Library API
Best for: SDKs, internal tooling, developer experience
Quick Reference
RESTful Resource Design
URL Patterns:
/api/v1/users(plural nouns, lowercase with hyphens)/api/v1/organizations/{org_id}/teams(hierarchical, max 2 levels)- Never use verbs:
/getUsersor underscores:/user_profiles
HTTP Methods:
GET- Retrieve (safe, idempotent, cacheable)POST- Create (returns 201 with Location header)PUT- Replace entire resource (idempotent)PATCH- Partial update (only changed fields)DELETE- Remove (idempotent, returns 204)
HTTP Status Codes
| Category | Code | When |
|---|---|---|
| Success | 200 | GET, PUT, PATCH success |
| Success | 201 | POST success (include Location header) |
| Success | 204 | DELETE success |
| Client Error | 400 | Malformed request |
| Client Error | 401 | Missing/invalid authentication |
| Client Error | 403 | Insufficient permissions |
| Client Error | 404 | Resource doesn't exist |
| Client Error | 409 | Duplicate resource |
| Client Error | 422 | Validation errors |
| Client Error | 429 | Rate limit exceeded |
| Server Error | 500 | Unhandled exception |
| Server Error | 503 | Database/service down |
Error Response Format
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
],
"requestId": "req_abc123",
"timestamp": "2025-10-25T10:30:00Z"
}
}
GraphQL Schema Design
type User {
id: ID!
email: String!
profile: Profile
posts(first: Int, after: String): PostConnection!
createdAt: DateTime!
}
type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type Query {
user(id: ID!): User
users(first: Int, after: String): UserConnection!
me: User
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
}
FastAPI Route Pattern
from fastapi import APIRouter, Depends, HTTPException, status
router = APIRouter(prefix="/api/v1/users", tags=["users"])
@router.post("", response_model=UserRead, status_code=status.HTTP_201_CREATED)
async def create_user(
user_data: UserCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> UserRead:
"""Create a new user in the current tenant."""
repository = UserRepository(db, tenant_id=current_user.tenant_id)
user = await repository.create(user_data)
return user
Pydantic Schema Pattern
from pydantic import BaseModel, EmailStr, Field, ConfigDict
class UserCreate(BaseModel):
email: EmailStr
full_name: str = Field(..., min_length=1, max_length=255)
password: str = Field(..., min_length=8)
class UserRead(BaseModel):
id: str
tenant_id: str
email: EmailStr
full_name: str
created_at: datetime
model_config = ConfigDict(from_attributes=True)
Pagination Patterns
Cursor-Based (recommended for large datasets):
GET /posts?limit=20&cursor=***
{ "data": [...], "pagination": { "nextCursor": "***", "hasMore": true } }
Offset-Based (simpler, for small datasets):
GET /posts?limit=20&offset=40
{ "data": [...], "pagination": { "total": 500, "limit": 20, "offset": 40 } }
Authentication Patterns
| Flow | Use Case |
|---|---|
| JWT Bearer tokens | API authentication, stateless sessions |
| API Key (X-API-Key) | Service-to-service, developer access |
| OAuth 2.0 Authorization Code | Web apps with backend |
| OAuth 2.0 Client Credentials | Service-to-service |
| OAuth 2.0 PKCE | Mobile/SPA apps |
Rate Limiting Headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 75
X-RateLimit-Reset: 1698340800
Retry-After: 60
Available Resources
References
| File | Description |
|---|---|
references/rest-best-practices.md | Comprehensive REST API patterns and status codes |
references/authentication.md | OAuth 2.0, JWT, API keys, MFA patterns |
references/versioning-strategies.md | API versioning and deprecation |
references/common-patterns.md | Health checks, webhooks, batch operations |
references/schema-patterns.md | GraphQL schema design patterns |
references/federation-guide.md | Apollo Federation architecture |
references/performance-optimization.md | GraphQL performance, DataLoader, caching |
references/architectural-principles.md | Python library SOLID principles |
references/pep-standards.md | Python PEP quick reference |
references/fastapi-setup.md | FastAPI main app configuration |
references/openapi.md | OpenAPI customization |
references/error-handlers.md | FastAPI exception handlers |
references/cors-rate-limiting.md | CORS and rate limiting setup |
references/openapi-spec.yaml | Complete OpenAPI 3.1 example |
references/graphql-schema.graphql | GraphQL with Relay connections |
references/grpc-service.proto | Protocol Buffer definitions |
references/rate-limiting.yaml | Tier-based rate limit config |
references/api-security.yaml | Auth, CORS, security headers |
Templates
| File | Description |
|---|---|
templates/fastapi-crud-endpoint.py | Complete CRUD router template |
templates/pydantic-schemas.py | Request/response schema template |
templates/repository-pattern.py | Repository with tenant isolation |
templates/rate-limiter.py | Upstash Redis rate limiter |
templates/error-handler.py | FastAPI exception handlers |
templates/tanstack-server-function.ts | TanStack Start server functions |
Examples
| File | Description |
|---|---|
examples/fastapi-crud.md | CRUD endpoints with repository |
examples/pydantic-schemas.md | Validation schema examples |
examples/pagination.md | Pagination implementation |
examples/testing.md | API testing patterns |
examples/tanstack-start.md | TanStack Start examples |
examples/openapi-spec.yaml | Blog API OpenAPI specification |
examples/graphql-schema.graphql | Full GraphQL schema with subscriptions |
Scripts
| File | Description |
|---|---|
scripts/schema_analyzer.py | Analyze GraphQL schemas for quality |
scripts/resolver_generator.py | Generate TypeScript resolvers |
scripts/federation_scaffolder.py | Scaffold Apollo Federation subgraphs |
scripts/api_helper.py | OpenAPI validation and docs generation |
scripts/validate-api-spec.sh | Validate API specifications |
Assets (Python Library)
| File | Description |
|---|---|
assets/pyproject.toml.template | Production-ready pyproject.toml |
assets/README.md.template | Library README template |
assets/CONTRIBUTING.md.template | Contribution guide |
assets/project-structure.txt | Recommended package layout |
assets/test-structure.txt | Test organization |
assets/example-exceptions.py | Exception hierarchy pattern |
assets/example-config.py | Configuration pattern |
Checklists
| File | Description |
|---|---|
checklists/api-design-checklist.md | API design review checklist |
checklists/security-review.md | Security review checklist |
Core Workflows
1. Design a REST API
- Identify resources (nouns): Users, Posts, Comments
- Design URL structure with proper nesting
- Choose appropriate HTTP methods
- Define request/response schemas
- Document with OpenAPI specification
- Implement pagination and filtering
- Add authentication and rate limiting
2. Build a GraphQL API
- Define schema types with descriptions
- Design queries with pagination (Relay connections)
- Create mutations with input types and payloads
- Implement DataLoader for N+1 prevention
- Add authentication in resolvers
- Configure caching and complexity limits
3. Validate API Specification
# Validate OpenAPI spec
python scripts/api_helper.py validate --spec openapi.yaml
# Analyze GraphQL schema
python scripts/schema_analyzer.py schema.graphql --validate
# Generate documentation
python scripts/api_helper.py docs --spec openapi.yaml --output docs/
Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Verb-based URLs | /getUsers violates REST conventions | Use /users with GET method |
| Inconsistent response envelopes | Clients can't parse predictably | Always use consistent structure |
| Breaking changes without versioning | Clients break on updates | Use semantic versioning; deprecation headers |
| N+1 queries in GraphQL | Each resolver fires separate DB query | Use DataLoader for batching |
| Over-fetching REST endpoints | Clients get more data than needed | Support sparse fieldsets, filtering |
| Missing pagination | List endpoints return unbounded results | Always paginate list endpoints |
| No idempotency keys | Duplicate mutations from retries | Accept Idempotency-Key header |
| Leaky internal errors | Stack traces exposed to clients | Generic messages in production |
| Missing CORS configuration | Browser requests blocked | Configure allowed origins explicitly |
| No rate limiting | API abuse and DoS | Implement per-user/per-endpoint limits |
| PUT for partial updates | Overwrites unchanged fields | Use PATCH for partial updates |
| Monolithic GraphQL schema | Schema becomes unmaintainable | Use Federation for schema separation |
Quality Checklist
[ ] All endpoints use nouns, not verbs
[ ] Consistent response envelope structure
[ ] Error responses include codes and actionable messages
[ ] Pagination on all list endpoints
[ ] Authentication/authorization documented
[ ] Rate limit headers defined
[ ] Versioning strategy documented
[ ] CORS configured for known origins
[ ] Idempotency keys for mutating operations
[ ] OpenAPI spec validates without errors
[ ] Examples for all request/response types
Version: 1.1.0 Last Updated: 2026-04-18