> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shieldlabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# identification.scored

> Read a finalized identification, its Risk Score, detection flags and account-event results.

Emitted when an identification is finalized. Match `data.identification_id` to your browser result and deduplicate deliveries by `event_id`.

The example uses `schema_version: "2026-10-13"`. Use the received `event_type` and `schema_version` when parsing a delivery. See [Webhook reference](https://docs.shieldlabs.ai/api/webhooks.md) for the envelope, signature and retry behavior.

## Example payload

The shortened example below shows VPN and Anti-Detect Browser: **30 + 60 = 90**. Unshown flags and traffic fields are omitted for readability.

```json theme={null}
{
  "event_id": "6ea4623fe1d9acdbf229d6b9cb247a7e3e51d440",
  "site_id": 101,
  "event_type": "identification.scored",
  "schema_version": "2026-10-13",
  "created_at": "2026-10-13T09:00:03Z",
  "data": {
    "identification_id": "13f84f05-7c2a-4e9b-9f1d-2a6b8c0e4d11",
    "user_hid": "a91f3c7e5b2d4086",
    "visitor_id": "161dfbad-8e7f-4a6b-9c5d-0e1f2a3b4c5d",
    "device_id": "5eb7fd5c-2a1b-4c3d-9e8f-7a6b5c4d3e2f",
    "domain": "example.com",
    "public_ip": { "ip": "203.0.113.42", "country": "NL" },
    "local_ip": { "ip": "", "country": "" },
    "connection_type": "vpn",
    "risk_score": 90,
    "signals": [
      { "name": "vpn", "weight": 30 },
      { "name": "antidetect_browser", "weight": 60 }
    ],
    "detection_flags": { "vpn": true, "anti_detect_browser": true },
    "hre": {
      "account_sharing": { "status": "evaluated", "level": null, "reason": "", "cluster_id": null },
      "account_takeover": { "status": "evaluated", "level": null, "reason": "", "cluster_id": null },
      "impossible_travel": { "status": "evaluated", "level": null, "reason": "", "cluster_id": null }
    },
    "observed_at": "2026-10-13T09:00:00Z"
  }
}
```

## Identity and context fields

| Field inside `data` | Type | Meaning |
| - | - | - |
| `identification_id` | string | Identification UUID; joins browser callback and History |
| `visitor_id`, `device_id` | string | [Visitor and device identifiers](https://docs.shieldlabs.ai/features/identification.md) |
| `session_id`, `cookie_id` | string | Browser session and storage identifiers |
| `user_hid` | string or null | Your pseudonymous account ID; `anonymous` for anonymous checks, null for an empty value |
| `domain` | string | Registered site domain |
| `public_ip`, `local_ip` | object | `{ ip, country }`; unavailable values are empty strings |
| `os`, `browser`, `device_type` | string | Detected OS, browser family and device class |
| `connection_type` | string | Network classification; see [connection types](https://docs.shieldlabs.ai/features/risk-signals.md#connection-type) |
| `traffic_source` | object | `channel`, `referrer_domain`, `landing_url`, `click_id_type`, `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term` |
| `observed_at` | string (RFC 3339) | Original observation time, distinct from event creation time |

Local IP is an address exposed by the browser network check, not a promise to return a private LAN address.

## Signals and flags

* `risk_score`: authoritative 0–100 result, or 999 for Banned IP.
* `signals`: named score contributions. Contributions can be consolidated or corrected; do not reconstruct the final score by summing them.
* `detection_flags`: 20 boolean decisions in the `2026-10-13` schema, including zero-weight detections. The example omits most false keys for readability; a full delivery includes them. [Risk signals](https://docs.shieldlabs.ai/features/risk-signals.md#source-signals) lists every key and its nominal weight.

For this schema, `os_mismatch` covers either operating-system mismatch check.

## Bot ownership

ShieldLabs identifies the provider of a recognized search bot, AI bot or AI browser. The provider name is returned in `search_bot_owner`, `ai_bot_owner` or `ai_browser_owner` when available. Optional `client_identity` contains additional client attribution.

## HRE

`data.hre` contains three separate account evaluations:

| Field | Evaluates |
| - | - |
| `account_sharing` | Whether one tracked account is used across multiple devices |
| `account_takeover` | Whether changes in the account's environment indicate possible unauthorized use |
| `impossible_travel` | Whether the account's locations are inconsistent with the time between observations |
| `rules_version` | Optional version identifier attached to these evaluations; store it as returned |

Multi-accounting uses [its own group-change event](https://docs.shieldlabs.ai/api/webhook-multi-account.md). It is not a fourth result inside this object. Event confidence and the identification's numeric Risk Score are separate measurements.

### Result fields

Each account evaluation has the following fields:

| Field | Type | Meaning |
| - | - | - |
| `status` | string | Whether the evaluation completed, could not be evaluated, or did not apply; read this before `level` |
| `level` | string or null | `medium` or `high` for an active detection; otherwise null |
| `reason` | string | Context for the result. It can be empty; preserve values you do not recognize |
| `cluster_id` | string or null | Identifier of the published evidence cluster, when available. It is separate from the Identification ID and Device ID |

### Status and confidence

| Status | Meaning | How to read a null `level` |
| - | - | - |
| `evaluated` | The calculation completed | No active detection was returned for this event |
| `not_evaluated` | There was insufficient history or the applicable evaluation was skipped | No completed verdict is available; it is not a negative detection |
| `not_applicable` | There is no tracked account for this check | Account-level detection does not apply |

For example, `reason: "no_history"` or `"skipped"` accompanies an evaluation that was not completed. Anonymous checks use `not_applicable` with `reason: "anonymous_user"`. These are result-context examples, not a closed list of reason values.

A null `cluster_id` means no published cluster reference was supplied. It does not override a non-null detection level, and it is not an identifier to synthesize from the account or device.

### Account-sharing counts

Account sharing can include these additional fields:

| Field | Type | Meaning |
| - | - | - |
| `devices` | integer, optional | Device count reported for this account-sharing result |
| `min_devices` | integer, optional | Minimum device count applied to this evaluation; use the returned value |
| `devices_at_least` | boolean, optional | When true, `devices` is a lower bound. For example, 4 means at least four, not exactly four. The field can be omitted when false |

An illustrative `account_sharing` result:

```json theme={null}
{
  "status": "evaluated",
  "level": "medium",
  "reason": "",
  "cluster_id": "11111111-1111-4111-8111-111111111111",
  "devices": 4,
  "min_devices": 4,
  "devices_at_least": true
}
```

This example reports a detection and a lower-bound count. It does not make four devices a universal confidence threshold. A current account risk category is also separate from the event's confidence and the score of this check. See [High-Risk Events](https://docs.shieldlabs.ai/features/high-risk-events.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.