GET /v1/sessions/{session_token}/verdict
Read the bot-detection decision for a session. Authenticated by private key, Redis-cached, fails open, under 50 ms p99.
curl https://api.botect.ai/v1/sessions/sess_9f3c.../verdict \
-H "Authorization: Bearer sk_YOUR_PRIVATE_KEY"
const res = await fetch(
`https://api.botect.ai/v1/sessions/${sessionToken}/verdict`,
{ headers: { Authorization: `Bearer ${process.env.BOTECT_PRIVATE_KEY}` } },
);
const { action } = await res.json();
if (action === 'block') return reject();
if (action === 'challenge') return showChallenge();
import os, requests
r = requests.get(
f"https://api.botect.ai/v1/sessions/{session_token}/verdict",
headers={"Authorization": f"Bearer {os.environ['BOTECT_PRIVATE_KEY']}"},
)
v = r.json()
{
"verdict": "likely_human",
"score": 87,
"action": "allow",
"detection_ids": [],
"reason": "No bot signals; natural interaction profile."
}
{
"verdict": "definite",
"score": 8,
"action": "block",
"detection_ids": [50331648, 50331651],
"reason": "Headless automation signature; no human interaction recorded."
}
{
"verdict": "not_computed",
"score": 0,
"action": "allow",
"detection_ids": [],
"reason": "Score not available; allowing by default."
}
Your backend calls this from request middleware to decide what to do with a visitor. Authenticated by the private key (secret). Cached in Redis and fails open — your site never hard-breaks on a Botect lookup.
GET https://api.botect.ai/v1/sessions/{session_token}/verdict
Authentication
Private key via Authorization: Bearer sk_… (or the X-Botect-Private-Key header). The session must belong to the authenticated project; if not, it's treated as unknown and returns the fail-open body (not a 404, which would leak existence). See Authentication.
Authorization: Bearer sk_YOUR_PRIVATE_KEY
Path parameters
The session token your SDK obtained from ingest (typically read from the botect_session cookie).
Example
Response fields
The score band: not_computed, definite, likely_automated, likely_human, or verified. See Score bands.
0 (not computed) or 1–99, where lower is more bot-confident.
What to do: allow, challenge, block, log, or delay. Resolved from rules + toggles. Branch on this, not on score.
Stable IDs explaining the score. Empty for clean humans; populated for bot-banded or enforced verdicts.
Plain-English summary of the decision.
Caching & fail-open
- Cached per
project+session_token(default TTL 60s). The cache is busted on rescore and whenever a toggle or rule changes. - An unknown / not-yet-scored session, or any load error, returns the fail-open
200body (not_computed, score0, actionallow). Your site continues to serve traffic even if Botect is degraded. - A blocking resolution records a block (with score, reason, and detection IDs) for audit.
Errors
| Status | code | When |
|---|---|---|
401 | UNAUTHENTICATED | Missing / bad private key |
402 | NO_ACTIVE_SUBSCRIPTION | Owning account has no active subscription |
An unknown session is not an error — it returns the fail-open 200 above. There is no 429: the verdict path is never rate-limited and fails open under load.