The Risk Snapshot
Every call to analyze (or analyze-sync) returns one object: the IdentityDecisionSnapshot. It is a flat, explainable record — a canonical verdict, four top-line scores, per-family signal fields, and a finding surface that tells you why the verdict came out the way it did. Identity is a standalone evidence provider: the snapshot describes risk, it does not act on it.
The snapshot carries a single verdict field — identityRiskLevel. It is identity's own evidence-grade assessment of the session, not a fraud or payment action. There is no block/allow field: you read the level, the scores and the findings, and you decide. Feed it into your own rules, your Fraud Detection logic, or your checkout.
The response envelope
Gateway responses share one envelope — { success, message, code, data, meta }. The snapshot is always in data:
{
"success": true,
"message": "Analysis complete",
"code": "IDENTITY_ANALYZED",
"data": { /* IdentityDecisionSnapshot — everything below */ },
"meta": { "traceId": "trc_01HV3K9X..." }
}The canonical verdict
identityRiskLevel is the one enum that summarises the session. It is graded from identity's own evidence — do not read it as an instruction to approve or decline.
| Field | Type | Meaning |
|---|---|---|
identityRiskLevel | clean | low | medium | high | critical | Identity's evidence-grade risk band for the session |
identityRiskPolicyVersion | string | The policy version that produced the level — pin it so grading changes are auditable |
identityRiskLevel is the only verdict enum in the snapshot. Everything else is a signal, a score, or a finding. There is no separate "decision" or "action" field — that surface belongs to your own logic.
The scores
Four normalised scores sit at the top of the snapshot. Treat them as continuous signals, not thresholds — you choose where your own cut-offs fall.
| Field | Range | What it tells you |
|---|---|---|
riskScore | 0–100 | Overall risk magnitude for the session |
confidenceScore | 0–1 | How much evidence backs the assessment |
similarityScore | 0–1 | How closely this session matches known good history for the subject |
stabilityScore | 0–1 | How stable the device/identity signal is across sessions |
Signal families
Below the scores, the snapshot groups signals by family. Each family is documented in depth on its own page; the tables here are the field reference.
Device & continuity
Whether this device/actor has been seen before and how stable the match is. Full detail: Device & Continuity.
| Field | Type | Meaning |
|---|---|---|
knownDevice | boolean | The device has been seen before for this merchant |
stableDevice | boolean | The fingerprint is stable across recent sessions |
sameDeviceProbability | 0–1 | Likelihood this is the same physical device as prior sessions |
sameBrowserProbability | 0–1 | Likelihood this is the same browser instance |
sameActorProbability | 0–1 | Likelihood the same person is behind this and prior sessions |
matchedClusterId | string | null | The device cluster this session was matched into |
clusterStabilityScore | 0–1 | How stable that cluster has been over time |
clusterRiskScore | 0–100 | Aggregate risk of the matched cluster |
continuityDriftReasons | string[] | Why continuity confidence dropped (e.g. new hardware attributes) |
continuityEvidence | object[] | Evidence records behind the continuity match |
Network intelligence
VPN/proxy/Tor/hosting posture plus geo, ASN and ISP. Full detail: Network Intelligence.
| Field | Type | Meaning |
|---|---|---|
networkCategory | string | Network type (e.g. residential, hosting, vpn, proxy) |
networkRiskScore | 0–100 | Risk magnitude of the network path |
networkPosture | string | Summary posture label for the network |
ipCountry / ipRegion / ipCity | string | IP geolocation |
geoConfidence | 0–1 | Confidence in the geolocation |
asn | number | Autonomous system number |
isp | string | Internet service provider |
provider | string | Network/hosting provider label |
hostingRisk | string | Hosting/datacenter risk level |
geoConflictDetected | boolean | Geo signals disagree (e.g. IP vs declared) |
networkMatchedSources | string[] | Which intelligence sources matched |
networkMatchedArtifacts | string[] | Which network artifacts matched |
Bot & automation
Bot classification, automation/abuse signals and declared/verified-bot trust. Full detail: Bot & Automation.
| Field | Type | Meaning |
|---|---|---|
botClassification | string | Bot verdict (e.g. human, automation_likely, verified_bot) |
botConfidence | 0–1 | Confidence in the bot classification |
botSignals | string[] | The individual automation/abuse signals observed |
botTrustOutcome | string | Outcome of declared/verified-bot evaluation |
botTrustTier | string | Trust tier assigned to a recognised bot |
botTrustDeclared | boolean | The client declared itself as an automated agent |
botIssuerId / botKeyId / botActorId | string | Identifiers of a registered, verified bot |
Mobile integrity
Present only for native-mobile sessions. Full detail: Mobile Threat.
| Field | Type | Meaning |
|---|---|---|
mobileIntegrityClassification | string | Attested device/app integrity verdict |
mobileIntegrityConfidence | 0–1 | Confidence in the integrity verdict |
mobilePolicyStatus | string | Result against your mobile app policy |
mobileAppTrusted | boolean | The app matched a trusted registry entry |
mobilePlatform | string | ios / android |
mobileAppId / mobileAppVersion | string | Reported app identity |
Tamper & privacy
Browser-integrity/tamper posture and privacy-tooling posture.
| Field | Type | Meaning |
|---|---|---|
tamperClassification | string | Browser-integrity/tamper verdict (e.g. clean, tampered) |
tamperConfidence | 0–1 | Confidence in the tamper verdict |
privacyPosture | string | Privacy-tooling posture (e.g. hardened, anti-detect) |
privacyConfidence | 0–1 | Confidence in the privacy posture |
Boolean flags
Fast, top-level booleans for the highest-signal conditions.
| Field | Meaning |
|---|---|
vpnDetected | Session arrived over a commercial VPN |
proxyDetected | Session arrived over a proxy/relay |
torDetected | Session arrived from a Tor exit node |
ipBlacklisted | The IP is on a block list |
fingerprintBlacklisted | The device fingerprint is on a block list |
deviceTokenBlacklisted | The device token is on a block list |
The verdict surface
The snapshot is explainable: alongside the scores and signals, it carries the reasons behind them.
| Field | Type | What it carries |
|---|---|---|
reasonCodes | string[] | Machine-readable codes summarising the drivers |
tags | string[] | Descriptive labels attached to the session |
riskFlags | string[] | The risk conditions that fired |
findings | object[] | The explained drivers — one entry per contributing signal |
features | object | A map of raw feature values used in the assessment |
Each entry in findings breaks down a single contributing signal:
| Finding field | Meaning |
|---|---|
code | The finding's stable code |
severity | low | medium | high (relative weight of this driver) |
scoreDelta | How much this finding moved the risk score |
source | Which signal family it came from (device, network, bot, …) |
description | Human-readable explanation |
Every signal family also exposes an evidence and method breakdown — each signal carries the evidence and the method that produced it, so a verdict is never a black box. Read findings for the explained drivers and the per-family evidence for the raw provenance.
A full snapshot
A complete data payload, with the real field names:
{
"identityRiskLevel": "high",
"identityRiskPolicyVersion": "2026-07-01",
"riskScore": 72,
"confidenceScore": 0.91,
"similarityScore": 0.38,
"stabilityScore": 0.55,
"knownDevice": true,
"stableDevice": true,
"sameDeviceProbability": 0.97,
"sameBrowserProbability": 0.88,
"sameActorProbability": 0.74,
"matchedClusterId": "clu_3b1d",
"clusterStabilityScore": 0.62,
"clusterRiskScore": 66,
"continuityDriftReasons": ["timezone_shift"],
"networkCategory": "vpn",
"networkRiskScore": 61,
"networkPosture": "anonymizing",
"ipCountry": "NL",
"ipRegion": "North Holland",
"ipCity": "Amsterdam",
"geoConfidence": 0.84,
"asn": 60068,
"isp": "Example ISP",
"provider": "Example Network",
"hostingRisk": "high",
"geoConflictDetected": true,
"networkMatchedArtifacts": ["vpn_range"],
"botClassification": "automation_likely",
"botConfidence": 0.70,
"botSignals": ["headless_hints", "input_cadence_synthetic"],
"botTrustOutcome": "unverified",
"botTrustDeclared": false,
"tamperClassification": "tampered",
"tamperConfidence": 0.81,
"privacyPosture": "anti_detect",
"privacyConfidence": 0.66,
"vpnDetected": true,
"proxyDetected": false,
"torDetected": false,
"ipBlacklisted": false,
"fingerprintBlacklisted": false,
"deviceTokenBlacklisted": false,
"reasonCodes": ["vpn_detected", "automation_likely", "browser_tampered"],
"tags": ["anonymizing_network"],
"riskFlags": ["network", "bot", "tamper"],
"findings": [
{ "code": "vpn_detected", "severity": "medium", "scoreDelta": 18, "source": "network", "description": "Commercial VPN range" },
{ "code": "automation_likely", "severity": "high", "scoreDelta": 26, "source": "bot", "description": "Synthetic input cadence" },
{ "code": "browser_tampered", "severity": "high", "scoreDelta": 22, "source": "tamper", "description": "Impossible feature combination" }
],
"features": { "input_entropy": 0.12, "canvas_delta": 0.44 }
}Fields appear only when the relevant signal is present. Mobile-integrity fields, for example, are absent on browser sessions, and matchedClusterId is null when a session matches no cluster. Always read defensively.
Next steps
- Device & Continuity — the device and continuity fields in depth
- Network Intelligence — VPN/proxy/Tor and geo/ASN/ISP
- Bot & Automation — bot classification and verified-bot trust
- Server-side API — querying and investigating stored analyses
- Assertions & JWKS — verifying a signed identity assertion