--- title: Fraud Prevention — Verdict Reference --- # Verdict Reference Every Fraud Prevention verdict — whether delivered to your `onVerdict` callback in the [Web SDK](./web-sdk) or pulled from the [Data API](./data-api) — is the same `BotVerdict` object. This page documents each field and how to act on it. ```json { "is_bot": false, "score": 18, "level": "low", "action": "record_only", "consistency": { "ok": true }, "degraded": false } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `is_bot` | boolean | The headline verdict. `true` = the visit is judged to be automated or invalid traffic; `false` = it looks like a real person. This is the single field most integrations branch on. | | `score` | number (0–100) | How suspicious the visit is. **Higher means more suspicious.** Use it to set your own thresholds — e.g. exclude visits above a cut-off you choose. The exact value is produced by our risk model and is not meant to be reverse-engineered. | | `level` | enum | Coarse band of `score`: `low`, `medium`, `high`, `critical`. Convenient when you want buckets instead of a raw number. | | `action` | enum | Our **recommended handling** for the visit: `record_only`, `challenge`, or `flag`. See below. | | `consistency` | object | A cross-signal consistency conclusion. Read `consistency.ok` (boolean): `true` = the visit's signals line up as expected; `false` = something didn't add up and the visit deserves extra scrutiny. The internal breakdown behind this conclusion is not exposed. | | `degraded` | boolean | `true` when the verdict could not be fully computed (service unreachable, error, etc.) and a conservative fallback was returned. Treat degraded verdicts as "unknown", not "clean". | ## `action` — what to do `action` is our recommendation; you stay in control of the final decision. | `action` | Meaning | What to do | | --- | --- | --- | | `record_only` | The visit looks normal. | Proceed as usual. Just log the verdict for reporting and reconciliation. | | `flag` | The visit is suspicious but not conclusively bad. | Keep serving the page, but mark the visit as low quality — exclude it from your metrics, segment it out of downstream flows, and weigh it in your own decisions (e.g. conversion attribution or how much you trust the visit). | | `challenge` | The visit is high-risk. | Ask for one extra verification before treating the visitor as human. With the Web SDK's `escalate: true` this is handled for you (see [Escalation](./web-sdk#escalation)); otherwise apply your own gate. | ## Configurable handling action What `action` reports for a **high-risk** visit is **per-app configuration**, set in the dashboard under your application's details. The verdict is **server-authoritative**: `action` only becomes `challenge` or `flag` when the visit reaches the high-risk band **and** your app is configured with the matching action. Below that band the verdict stays `record_only`. | Setting | `action` returned at high risk | Meaning | | --- | --- | --- | | `record_only` (default) | `record_only` | Record only. The verdict is logged for reporting and reconciliation; nothing is asked of the visitor. | | `challenge` | `challenge` | Trigger a re-verification CAPTCHA. The Web SDK pops a challenge (styling is controlled by the SDK's `challengeConfig`). | | `flag` | `flag` | Mark the visit. The verdict carries `flag`; your integration decides how to act on it (block / segment / handle). | Because the decision is made server-side, your code stays simple: read `verdict.action` in `onVerdict` and act on it — proceed, block, or let the SDK present a challenge. You do not need to re-derive the risk yourself. ## `level` vs `score` `level` is just a banding of `score`, provided for convenience: | `level` | Use it when | | --- | --- | | `low` | Treat as clean traffic. | | `medium` | Borderline — fine to record, consider excluding from high-value funnels. | | `high` | Strongly suspicious — flag and exclude. | | `critical` | Almost certainly invalid — flag/exclude and, ideally, escalate. | ::: tip Pick the field that fits your pipeline - Simple yes/no gate → branch on **`is_bot`**. - Recommendation-driven → branch on **`action`**. - Custom thresholds → branch on **`score`** (or **`level`** for buckets). ::: ## Handling degraded verdicts When `degraded` is `true`, the verdict was not fully computed. The fallback is deliberately conservative (`is_bot: false`, `action: record_only`) so real users are never blocked. For reporting, treat these as **unknown** rather than counting them as confirmed-clean traffic. ## Next steps - [Web SDK](./web-sdk) — receive verdicts on your page - [Data API](./data-api) — pull verdicts and stats server-side