Error and Response Codes
The Discuse API signals problems in two ways: an HTTP error status with a message, or a normal 200 response whose fields tell you what happened. This page lists every case so you can handle them correctly — and explains the one that trips people up: a billing-quota exhaustion is not an HTTP error.
What HTTP statuses does the API return?
| Status | When | What to do |
|---|---|---|
200 |
Success — including the "quota exhausted" case | Inspect the response body; a 200 is not always a green light (see below) |
400 |
Request validation failed — empty content, text over 10,000 characters, or too many media URLs |
Fix the request; do not retry unchanged |
401 |
Missing or invalid API key | Check the X-API-Key header; do not retry unchanged |
429 |
Rate limit exceeded for the key | Back off and retry after the one-minute window |
500 |
A downstream/internal error | Retry with backoff |
Read the message on any non-2xx response. Authentication failures return 401, rate-limit failures return 429, and request-validation failures return 400; treat 5xx as transient and retry with backoff.
Why is "quota exhausted" a 200, not an error?
When a project uses up its monthly API-request allowance, POST /api/v2/check still returns 200 — with the content treated as having no violations, a message explaining the quota is exhausted, and a usage object showing zero remaining:
{
"has_violations": false,
"message": "API quota exceeded. Current: 10000, Limit: 10000",
"usage": {
"api_requests_used": 10000,
"api_requests_limit": 10000,
"api_requests_remaining": 0
}
}
This is deliberate: a quota run-out should not look like a server failure or block your pipeline with an exception. Check usage.api_requests_remaining (and the message) instead of relying on the status code. If you fail open on a 200, an exhausted quota would silently let content through unchecked — so branch on these fields explicitly.
How should I read a successful response?
A 200 from /api/v2/check always carries has_violations and cached; the rest is optional:
| Field | Type | Meaning |
|---|---|---|
has_violations |
boolean | True if any enabled check flagged the content |
cached |
boolean | True if served from a recent identical-request cache |
message |
string | Present on quota exhaustion (and similar non-error notices) |
request_id |
string | Echoed back if you sent one |
processing_time_ms |
number | Present when timing is enabled for the project |
usage |
object | api_requests_used, api_requests_limit, api_requests_remaining |
results |
object | Per-check detail (spamfinder, sentiment, images, …) and the top-level hits flag |
Decide on has_violations for the overall verdict, then drill into results.<check>.hit for which check fired.
How does caching affect responses?
Identical requests for the same project are de-duplicated: a repeat returns cached: true with the same result. Caching is per project. Note that a cached request still counts against your API-request quota — it saves processing time, not quota.
You can attach a request_id to a request for your own correlation; it is echoed back in the response.
A minimal, correct client
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
}
Related
- Authentication and API Keys — keys, the
X-API-Keyheader, and rate limits - Quick Start Guide — your first request in a few minutes
- Text Analysis — the
resultsobject in detail