api-design-principles by secondsky/claude-skills
npx skills add https://github.com/secondsky/claude-skills --skill api-design-principles掌握 REST 和 GraphQL API 设计原则,构建直观、可扩展且可维护的 API,让开发者满意并经受住时间的考验。
面向资源的架构
HTTP 方法语义:
GET:检索资源(幂等、安全)POST:创建新资源PUT:替换整个资源(幂等)PATCH:部分资源更新DELETE:删除资源(幂等)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
模式优先开发
查询结构:
URL 版本控制:
/api/v1/users
/api/v2/users
头部版本控制:
Accept: application/vnd.api+json; version=1
查询参数版本控制:
/api/users?version=1
# 良好:面向资源的端点
GET /api/users # 列出用户(带分页)
POST /api/users # 创建用户
GET /api/users/{id} # 获取特定用户
PUT /api/users/{id} # 替换用户
PATCH /api/users/{id} # 更新用户字段
DELETE /api/users/{id} # 删除用户
# 嵌套资源
GET /api/users/{id}/orders # 获取用户的订单
POST /api/users/{id}/orders # 为用户创建订单
# 不佳:面向操作的端点(避免)
POST /api/createUser
POST /api/getUserById
POST /api/deleteUser
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
from typing import List, Optional
class PaginatedResponse(BaseModel):
items: List[dict]
total: int
page: int
page_size: int
pages: int
@property
def has_next(self) -> bool:
return self.page < self.pages
app = FastAPI()
@app.get("/api/users", response_model=PaginatedResponse)
async def list_users(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
status: Optional[str] = Query(None),
search: Optional[str] = Query(None)
):
query = build_query(status=status, search=search)
total = await count_users(query)
offset = (page - 1) * page_size
users = await fetch_users(query, limit=page_size, offset=offset)
return PaginatedResponse(
items=users,
total=total,
page=page,
page_size=page_size,
pages=(total + page_size - 1) // page_size
)
from fastapi import HTTPException, status
STATUS_CODES = {
"success": 200,
"created": 201,
"no_content": 204,
"bad_request": 400,
"unauthorized": 401,
"forbidden": 403,
"not_found": 404,
"conflict": 409,
"unprocessable": 422,
"internal_error": 500
}
def raise_not_found(resource: str, id: str):
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={
"error": "NotFound",
"message": f"{resource} not found",
"details": {"id": id}
}
)
class UserResponse(BaseModel):
id: str
name: str
email: str
_links: dict
@classmethod
def from_user(cls, user: User, base_url: str):
return cls(
id=user.id,
name=user.name,
email=user.email,
_links={
"self": {"href": f"{base_url}/api/users/{user.id}"},
"orders": {"href": f"{base_url}/api/users/{user.id}/orders"},
"update": {"href": f"{base_url}/api/users/{user.id}", "method": "PATCH"},
"delete": {"href": f"{base_url}/api/users/{user.id}", "method": "DELETE"}
}
)
type User {
id: ID!
email: String!
name: String!
orders(first: Int = 20, after: String): OrderConnection!
}
type OrderConnection {
edges: [OrderEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
}
input CreateUserInput {
email: String!
name: String!
password: String!
}
type CreateUserPayload {
user: User
errors: [Error!]
}
from aiodataloader import DataLoader
class UserLoader(DataLoader):
async def batch_load_fn(self, user_ids: List[str]) -> List[Optional[dict]]:
users = await fetch_users_by_ids(user_ids)
user_map = {user["id"]: user for user in users}
return [user_map.get(user_id) for user_id in user_ids]
@deprecated 指令进行渐进式迁移每周安装次数
78
仓库
GitHub 星标数
93
首次出现
Jan 22, 2026
安全审计
安装于
claude-code67
gemini-cli63
codex62
opencode61
cursor61
github-copilot58
Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers and stand the test of time.
Resource-Oriented Architecture
HTTP Methods Semantics:
GET: Retrieve resources (idempotent, safe)POST: Create new resourcesPUT: Replace entire resource (idempotent)PATCH: Partial resource updatesDELETE: Remove resources (idempotent)Schema-First Development
Query Structure:
URL Versioning:
/api/v1/users
/api/v2/users
Header Versioning:
Accept: application/vnd.api+json; version=1
Query Parameter Versioning:
/api/users?version=1
# Good: Resource-oriented endpoints
GET /api/users # List users (with pagination)
POST /api/users # Create user
GET /api/users/{id} # Get specific user
PUT /api/users/{id} # Replace user
PATCH /api/users/{id} # Update user fields
DELETE /api/users/{id} # Delete user
# Nested resources
GET /api/users/{id}/orders # Get user's orders
POST /api/users/{id}/orders # Create order for user
# Bad: Action-oriented endpoints (avoid)
POST /api/createUser
POST /api/getUserById
POST /api/deleteUser
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
from typing import List, Optional
class PaginatedResponse(BaseModel):
items: List[dict]
total: int
page: int
page_size: int
pages: int
@property
def has_next(self) -> bool:
return self.page < self.pages
app = FastAPI()
@app.get("/api/users", response_model=PaginatedResponse)
async def list_users(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
status: Optional[str] = Query(None),
search: Optional[str] = Query(None)
):
query = build_query(status=status, search=search)
total = await count_users(query)
offset = (page - 1) * page_size
users = await fetch_users(query, limit=page_size, offset=offset)
return PaginatedResponse(
items=users,
total=total,
page=page,
page_size=page_size,
pages=(total + page_size - 1) // page_size
)
from fastapi import HTTPException, status
STATUS_CODES = {
"success": 200,
"created": 201,
"no_content": 204,
"bad_request": 400,
"unauthorized": 401,
"forbidden": 403,
"not_found": 404,
"conflict": 409,
"unprocessable": 422,
"internal_error": 500
}
def raise_not_found(resource: str, id: str):
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={
"error": "NotFound",
"message": f"{resource} not found",
"details": {"id": id}
}
)
class UserResponse(BaseModel):
id: str
name: str
email: str
_links: dict
@classmethod
def from_user(cls, user: User, base_url: str):
return cls(
id=user.id,
name=user.name,
email=user.email,
_links={
"self": {"href": f"{base_url}/api/users/{user.id}"},
"orders": {"href": f"{base_url}/api/users/{user.id}/orders"},
"update": {"href": f"{base_url}/api/users/{user.id}", "method": "PATCH"},
"delete": {"href": f"{base_url}/api/users/{user.id}", "method": "DELETE"}
}
)
type User {
id: ID!
email: String!
name: String!
orders(first: Int = 20, after: String): OrderConnection!
}
type OrderConnection {
edges: [OrderEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
}
input CreateUserInput {
email: String!
name: String!
password: String!
}
type CreateUserPayload {
user: User
errors: [Error!]
}
from aiodataloader import DataLoader
class UserLoader(DataLoader):
async def batch_load_fn(self, user_ids: List[str]) -> List[Optional[dict]]:
users = await fetch_users_by_ids(user_ids)
user_map = {user["id"]: user for user in users}
return [user_map.get(user_id) for user_id in user_ids]
@deprecated directive for gradual migrationWeekly Installs
78
Repository
GitHub Stars
93
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code67
gemini-cli63
codex62
opencode61
cursor61
github-copilot58
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
163,300 周安装
Google Calendar自动化工具:命令行管理日历事件、查找空闲时间、响应邀请
140 周安装
百度搜索API技能:AI代理网络搜索工具,支持高级筛选与资源类型过滤
139 周安装
Webflow 安全发布工具:自动化站点预览、验证与部署工作流
151 周安装
代码安全扫描工具 - 全面检测OWASP Top 10漏洞、密钥泄露与注入缺陷
142 周安装
社交媒体内容多平台适配器 - AI内容重制工具,一键优化Twitter/LinkedIn/Instagram/Facebook/TikTok
148 周安装
Rust Trait 探索器 - 快速查找 trait 实现与多态设计分析工具
232 周安装