楔子:为什么你的API总是被人白眼?
写API这件事,说难听点,就是一个让人公开处刑的过程。你以为自己设计得很优雅,结果调用方心里想的是「这TM是什么鬼」。
我见过太多工程师,写代码是一把好手,写起API来却像在写情书——自己感动自己,对方完全看不懂。今天我就来掏心窝子,讲讲这些年见过的API设计通病。
原则一:URL设计不是汉字拼图游戏
先看几个「佳作」:
GET /getUserInfoByIdAndDateRange
POST /createNewUserRecord
DELETE /deleteUserByUserId
看到这些URL,你什么感受?反正我的感受是「工程师今天又没睡醒」。
RESTful的核心是资源,不是动词。你的URL应该是名词,而且要保持一致性:
GET /users # 获取用户列表
GET /users/123 # 获取ID为123的用户
POST /users # 创建用户
PUT /users/123 # 更新用户
DELETE /users/123 # 删除用户
记住:HTTP方法本身就是动词。你的URL里面不需要再带动词了。
原则二:状态码不是胡编乱造
我见过最离谱的API,所有的错误统一返回200,然后在body里面写{"success": false, "message": "参数错误"}。这不是脱了裤子放屁——多此一举吗?
HTTP状态码是给调用方的礼物。用它来表达真实的错误类型:
- 200:成功(但别啥都返回200)
- 201:资源创建成功
- 400:客户端参数错误,你需要告诉调用方错在哪
- 401:未认证(没登录)
- 403:已认证但没权限
- 404:资源不存在
- 409:冲突(比如用户名已被占用)
- 429:请求过于频繁,悠着点
- 500:服务器抽风了,这个必须记日志
最关键的是:错误响应的body必须包含有意义的错误信息,而不是一个空壳。
{"error": {"code": "VALIDATION_FAILED", "message": "Email格式不正确", "field": "email"}}
原则三:分页不是玄学
有些API返回10条数据,有些返回50条,有些干脆返回全部——然后客户端内存崩溃了。
分页是API的基本礼貌。推荐使用Cursor式分页,避免偏移量分页的性能问题:
GET /articles?limit=20&cursor=eyJpZCI6MTAwfQ
# 响应
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTIwfQ",
"has_more": true
}
}
如果你非要用偏移量分页,至少告诉调用方总共有多少页:
{"data": [...], "total": 1234, "page": 1, "per_page": 20}
原则四:版本管理要优雅,不要学淘宝、京东
看到这样的URL你什么感觉?
/api/v1/user/getInfo
/api/v2/user/info
/api/v3/users/{id}
这简直是历史博物馆。版本管理应该清晰且有预期性:
GET /v1/users/123 # v1版本
GET /v2/users/123 # v2版本,平滑迁移
重要原则:一旦发布的API,原则上不做破坏性修改。增加可选参数、新增endpoint都可以,但不要修改既有响应结构或行为。如果必须修改,请升级版本号。
原则五:时间和时间格式,折腾死人不偿命
时间格式的混乱程度,堪称API界的切尔诺贝利:
"2026-01-15"
"2026/01/15 14:30:00";
"1705312200000";
"2026-01-15T14:30:00+08:00";
必须使用ISO 8601格式(YYYY-MM-DDTHH:mm:ssZ),并明确标注时区。UTC最佳,否则你会在除夕夜为什么红包没到账这个问题上和用户扯皮半小时。
原则六:认证不是把用户名密码放在URL参数里
我知道你懒,但把密码放在URL里面相当于把日记本放在广场上:
# 万万不可
GET /api/user?username=admin&password=123456
# 推荐方式:JWT Token
GET /api/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
另外,千万不要自己发明认证机制。OAuth 2.0、JWT这些成熟方案不香吗?自己写的加密,迟早出事。
原则七:Documentation不仅仅是「将来再补」
你见过那种API文档吗?写着「用户ID,类型整形,用户ID」。看完了等于没看。
好文档的标准:
- 每个endpoint都有示例(请求+响应)
- 错误码有说明,告诉调用方如何处理
- 标注必填项和可选项
- 说明业务场景,为什么需要这个API
推荐使用OpenAPI/Swagger规范编写文档,不仅清晰,还能自动生成客户端SDK。
原则八:缓冲策略,别让调用方每分钟打扰你一千次
如果你的API数据更新频率不高,却让调用方每秒请求一次,那是你有问题。
善用HTTP缓存头:
Cache-Control: max-age=3600
ETag: "33a64df551425fcc55e"
Last-Modified: Thu, 27 May 2026 10:00:00 GMT
这样调用方可以根据ETag判断是否需要更新数据,减轻你的服务器压力,也让用户体验更好。
原则九:限流要良心,别学某些平台的骚操作
有些平台的限流机制是「你已经触发了限制,请5秒后重试」,然后没有任何提示什么时候可以再用。调用方只能 sleep 5秒然后再试,体验灾难级。
良心限流应该包含:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1748503200
告诉调用方:你的配额是多少、还剩多少、什么时候重置。这样人家可以合理安排请求调度,而不是瞎等。
原则十:破坏性变更,必须提前预警
如果你要修改一个已发布的API:
- 至少提前一个月通知
- 在新版本中提供清晰的迁移指南
- 保持旧版本一段时间再下线
- 千万不要「今天上线,明天旧版就不能用了」
我见过太多「惊喜上线」的案例,调用方半夜起来排查问题,发现是你的API悄悄变了。那一刻,你在他心里的评分已经是零了。
结语:API是给别人用的,不是给自己看的
设计API的终极原则是:假设明天有个人看了你的文档,不需要问你任何问题,就能正确调用你的API。
如果做不到这一点,那就继续优化。API的好坏不在于你用多华丽的技术,在于调用方的血压高低。
记住:你是服务提供方,调用方是你的用户。把他们当白痴一样对待,你的API就差不多了。
题外话:如果你觉得这篇文章有帮助,说明你是一个愿意学习的人。如果你觉得这些都是常识,说明你已经踩过这些坑了。不论哪种情况恭喜你看到这里。