错误和响应代码
Discuse API 通过两种方式表示问题:带有 message 的 HTTP 错误状态,或者字段说明实际情况的普通 200 响应。本页列出所有情况,帮助你正确处理它们——并解释一个容易让人踩坑的点:计费配额耗尽不是 HTTP 错误。
API 会返回哪些 HTTP 状态?
| Status | When | What to do |
|---|---|---|
200 |
成功——包括“配额耗尽”的情况 | 检查响应正文;200 并不总是代表一切正常(见下文) |
400 |
请求验证失败——内容为空、text 超过 10,000 个字符,或媒体 URL 过多 |
修正请求;不要在不修改的情况下重试 |
401 |
缺少 API 密钥或 API 密钥无效 | 检查 X-API-Key 标头;不要在不修改的情况下重试 |
429 |
该密钥超出速率限制 | 退避,并在一分钟窗口结束后重试 |
500 |
下游/内部错误 | 使用退避策略重试 |
请读取任何非 2xx 响应中的 message。身份验证失败会返回 401,速率限制失败会返回 429,请求验证失败会返回 400;将 5xx 视为临时性问题,并使用退避策略重试。
为什么“配额耗尽”是 200,而不是错误?
当项目用完每月 API 请求额度后,POST /api/v2/check 仍会返回 200——内容会被视为没有违规,同时返回一条说明配额已耗尽的 message,以及一个显示剩余次数为零的 usage 对象:
{
"has_violations": false,
"message": "API quota exceeded. Current: 10000, Limit: 10000",
"usage": {
"api_requests_used": 10000,
"api_requests_limit": 10000,
"api_requests_remaining": 0
}
}
这是有意设计的:配额用尽不应该看起来像服务器故障,也不应该用异常阻塞你的流水线。请检查 usage.api_requests_remaining(以及 message),而不是只依赖状态码。如果你在遇到 200 时选择放行,配额耗尽会导致内容在未检查的情况下悄悄通过——因此请明确基于这些字段进行分支处理。
如何读取成功响应?
来自 /api/v2/check 的 200 响应始终包含 has_violations 和 cached;其余字段是可选的:
| Field | Type | Meaning |
|---|---|---|
has_violations |
boolean | 如果任何已启用的检查标记了该内容,则为 True |
cached |
boolean | 如果结果来自近期相同请求的缓存,则为 True |
message |
string | 在配额耗尽(以及类似的非错误通知)时出现 |
request_id |
string | 如果你发送了该字段,会原样回传 |
processing_time_ms |
number | 当项目启用计时时出现 |
usage |
object | api_requests_used、api_requests_limit、api_requests_remaining |
results |
object | 各项检查的详细信息(spamfinder、sentiment、images 等)以及顶层 hits 标志 |
使用 has_violations 判断整体结论,然后查看 results.<check>.hit 以确定是哪项检查被触发。
缓存如何影响响应?
同一项目的相同请求会被去重:重复请求会返回 cached: true,并带有相同结果。缓存按项目隔离。请注意,缓存请求仍会计入你的 API 请求配额——它节省的是处理时间,而不是配额。
你可以在请求中附加 request_id 用于自己的关联追踪;它会在响应中原样回传。
一个最小且正确的客户端
async function check(content, settings) {
const response = await fetch('https://api.discuse.com/api/v2/check', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.DISCUSE_API_KEY
},
body: JSON.stringify({ content, settings })
});
// 400: bad request — fix it, don't retry. 5xx: transient/auth/rate-limit — retry with backoff.
if (response.status === 400) {
throw new Error('Invalid request: ' + (await response.text()));
}
if (!response.ok) {
throw new Error(`Discuse error ${response.status}`); // retry upstream with backoff
}
const data = await response.json();
// Quota exhausted is a 200 — never treat it as "checked and clean".
if (data.usage && data.usage.api_requests_remaining === 0 && data.message) {
throw new Error('Quota exhausted: ' + data.message);
}
return data; // inspect data.has_violations and data.results
}
相关内容
- 身份验证和 API 密钥 — 密钥、
X-API-Key标头和速率限制 - 快速入门指南 — 几分钟内完成你的第一个请求
- 文本分析 — 详细了解
results对象