Errors
Botect's stable JSON error shape, status codes, and the cases that are deliberately not errors.
Every API error returns a stable JSON shape so your client can switch on the machine-readable code. The code never changes without a major-version bump; error and message are human copy and may be reworded.
Error shape
{
"error": "Short title (stable)",
"message": "Human-readable detail (may change with copy)",
"code": "STABLE_MACHINE_CODE",
"details": { },
"retry_after": 0
}
details and retry_after are optional and only present where relevant.
Status codes
| Status | code | Meaning |
|---|---|---|
401 | UNAUTHENTICATED | Missing, malformed, or revoked credential — or a site/private key for a project without scoring enabled |
402 | NO_ACTIVE_SUBSCRIPTION | Valid credential, but the owning account has no active subscription |
403 | FEATURE_NOT_AVAILABLE | The account's plan does not include the requested feature |
422 | INVALID_PAYLOAD | Schema violation — malformed batch, non-whitelisted payload keys, or an invalid rule expression |
Canonical 402
{
"error": "No active subscription",
"message": "This account has no active subscription. Subscribe to a plan to access the API.",
"code": "NO_ACTIVE_SUBSCRIPTION"
}
What is not an error
Two cases that might look like failures are deliberately successful responses — this is what keeps Botect off your critical path:
Unknown or not-yet-scored session. A verdict read for a session Botect hasn't scored (or doesn't recognize) returns 200 with a fail-open body — not_computed, score 0, action allow — not a 404. This also avoids leaking which session tokens exist.
{
"verdict": "not_computed",
"score": 0,
"action": "allow",
"detection_ids": [],
"reason": "Score not available; allowing by default."
}
Over-quota ingest. Crossing your monthly quota does not error. The batch is accepted (202) and may carry "over_quota": true. See Plans & quotas.
No 429
The data plane is never rate-limited. There is no 429 and no Retry-After on ingest or verdict reads — volume is governed by quota, and under load the verdict path fails open. See Plans & quotas.
Handling errors
- Switch on
code, not onerror/messagetext. - Treat
401as a credential problem — check you're sending the right key for the endpoint (see Authentication). - Treat
402as "subscribe / renew", surfaced to an account owner. - Treat
422on rule creation as a grammar problem — themessagedescribes which token or field was rejected. - For verdict reads, you generally don't need error handling on the happy path: unknown sessions and load both resolve to a safe
allow.