RESTful API design patterns and best practices. Use when creating endpoints, designing APIs, or implementing routes.
View on GitHubxiaobei930/claude-code-best-practices
cc-best
January 25, 2026
Select agents to install to:
npx add-skill https://github.com/xiaobei930/claude-code-best-practices/blob/main/skills/api-development/SKILL.md -a claude-code --skill api-developmentInstallation paths:
.claude/skills/api-development/# API 开发技能
本技能提供 RESTful API 开发的最佳实践和模式。
## 触发条件
- 创建 API 端点
- 设计 REST API
- 实现后端路由
- 处理请求/响应
- API 版本控制
## RESTful 设计原则
### URL 设计
```
# 资源命名 - 使用名词复数
GET /api/v1/users # 获取用户列表
GET /api/v1/users/:id # 获取单个用户
POST /api/v1/users # 创建用户
PUT /api/v1/users/:id # 更新用户(完整替换)
PATCH /api/v1/users/:id # 更新用户(部分更新)
DELETE /api/v1/users/:id # 删除用户
# 嵌套资源
GET /api/v1/users/:id/orders # 用户的订单
GET /api/v1/users/:id/orders/:orderId # 用户的特定订单
# 动作资源
POST /api/v1/users/:id/activate # 激活用户
POST /api/v1/orders/:id/cancel # 取消订单
```
### HTTP 方法语义
| 方法 | 语义 | 幂等 | 安全 |
| ------ | -------- | ---- | ---- |
| GET | 读取资源 | ✅ | ✅ |
| POST | 创建资源 | ❌ | ❌ |
| PUT | 完整更新 | ✅ | ❌ |
| PATCH | 部分更新 | ❌ | ❌ |
| DELETE | 删除资源 | ✅ | ❌ |
## 统一响应格式
### 成功响应
```typescript
// 单个资源
{
"success": true,
"data": {
"id": "123",
"name": "张三",
"email": "zhangsan@example.com"
}
}
// 列表资源
{
"success": true,
"data": [
{ "id": "1", "name": "用户1" },
{ "id": "2", "name": "用户2" }
],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 100,
"totalPages": 5
}
}
// 创建成功
{
"success": true,
"data": { "id": "123", ... },
"message": "创建成功"
}
```
### 错误响应
```typescript
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数无效",
"details": [
{ "field": "email", "message": "邮箱格式不正确" },
{ "field": "age", "message": "年龄必须大于 0" }
]
}
}
```
## API 路由实现
### Next.js App Router
```typescript
// app/api/users/route.ts
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
const CreateUserSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).optional(),
});
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const page = parseInt(se