好的 API 应该用一种最无聊的好方式来工作:URL 可预测、错误信息诚实、数据结构小而稳定、没有意外。这些原则塑造了 Noxyr Server API,借鉴了 Stripe、Resend、OpenAI 以及 Discord 官方 API 背后的行业标准。

A scan line moves through an API blueprint, lighting up versioning, hashed keys, scopes and honest errors. /api/v1/ versioned URLs SHA-256 hashed keys Scopes per-endpoint toggle error: "..." honest errors

1. 带版本号的 URL

每个端点都位于 /api/v1/ 之下。当我们引入不兼容的更改时,会放到 /api/v2/ 下:旧的集成依然可以正常工作。Discord 也是这样做的,使用 /api/v10/。如果你的 API 没有版本号,每次数据结构的变化都会变成一张客服工单。

2. 先资源,后动作

Noxyr 的端点以名词命名:server、tickets、activity、invoices、reviews、giveaways。目前全部是只读的,全部使用 GET。以后新增写入操作时,会在同样的资源上使用 POST/PATCH/DELETE。这样可以干净地对应 REST 约定,也让心智模型保持很小。

3. Bearer 令牌,只有一个密钥

认证方式是 Authorization: Bearer nxr_...。不需要签名请求,对于只读的服务器数据也不需要 OAuth 流程。现代面向开发者的 API 都趋向于这种方式,因为它在任何地方都能用:curl、浏览器、Postman、无服务器边缘节点。Discord 对经过 OAuth 授权的用户同样使用 Bearer 令牌;这种模式非常通用。

4. 只存储哈希值

每一个 Noxyr 密钥在服务器端都会经过 SHA-256 哈希处理。原始值只在生成时显示一次,之后再也不会显示。即使我们的数据库泄露,也没有任何密钥能被直接使用。Stripe、GitHub、Resend 以及其他运营良好的 API 厂商都是这样做的,可逆的密钥存储是一个危险信号。

5. 细粒度的权限范围

一个密钥,六个相互独立的开关。评价是公开数据,销售数据则是私密的;把它们分开,你就可以把一个只能访问评价的密钥分享给营销合作伙伴,同时把收入数字放在另一个开关后面。权限范围的更改会立即生效(每次请求都会检查),因此撤销密钥时无需轮换密钥。

6. 诚实的错误响应

每一个错误都是 JSON,包含稳定的机器可读代码和人类可读的消息:

{ "error": "scope_disabled", "message": "The \"tickets\" scope is turned off for this key. Enable it on the dashboard API page." }

机器可读的代码让重试和仪表盘变得简单,人类可读的消息让调试快速高效。2026 年 7 月,“discord increased api errors”的搜索量激增(Google Trends 显示为“breakout”),这说明了当错误信息含糊不清时,用户只能靠猜。

7. 时间序列零值填充

/api/v1/activity 端点会返回请求范围内的每一天,即使当天的数量为零。前端不必自己填补空缺,图表也不会在稀疏的日期之间跳动。这是一个很小的便利,却能极大地提升使用体验。

8. 带请求头的速率限制

每个响应都会携带 RateLimit-* 请求头,让客户端能在触发 429 之前主动退避。这是标准化的 IETF 草案格式,与 GitHub 及其他现代 API 的格式一致,因此任何支持该格式的现有客户端库都可以开箱即用。

9. 只读数据使用宽松的 CORS

只读端点会返回 Access-Control-Allow-Origin: *。因为认证依据的是密钥,而不是请求来源,开放 CORS 在安全上不会带来额外成本,还能让浏览器工具直接调用 API,无需代理脚手架,也不需要 localhost 的变通方案。

10. 小而稳定的数据结构

每个响应都能在一屏之内看完。没有可选的嵌套对象,也没有只在某个功能开关打开时才出现的字段。小的数据结构易于缓存、易于测试,也便于在 TypeScript 中定义类型。

实际用法可以参考:Server API 教程。当 Discord 本身出现问题时,可以看看这些 Discord API 错误的真正含义。