Response Object
Every field Checkpoint returns for a request: the verdict, the evidence behind it, and the engine that produced it
Every Checkpoint integration runs the same detection engine, and every verdict it produces is a single object, the VerifyResult.
This page documents that object in full: every field, when it is present, and what its values mean.
What your integration receives from the object depends on the surface you installed and on whether full response delivery is enabled for your project.
Full response delivery
By default, each integration returns a projection of this object: headers from the SDKs and the
DNS gateway, the result of /api/v1/detect, and the stored record through the read-back API.
With full response delivery enabled, Checkpoint sends the complete object documented here,
including every signal, reason code and captured attribute. Vouched enables full response delivery
per project or per organization. Contact your account team to turn it on.
The response object, fully expanded
The example below is a GPTBot crawler request from an OpenAI IP address, evaluated in observe mode against a policy that allows it. Comments give each field's type and when it appears.
{
"decision": { "kind": "Permit", "policyId": "allow-search-and-ai-crawlers" }, // Permit | Block | Challenge | Redirect | Instruct (tag = kind)
"detectionDetail": {
"isAgent": false, // boolean, always. true only for the AiAgent class; route on detectionClass instead
"isBot": true, // boolean, optional. Omitted when the class is IncompleteData
"isAiCrawler": true, // boolean, optional. Omitted when the class is IncompleteData
"confidence": 93.0, // number 0-100, always. Detection score, not a calibrated probability
"detectionClass": {
// tagged by type: Human | AiAgent | Bot | IncompleteData
"type": "Bot",
"botType": "Scraper", // Bot only: Scraper | SearchEngine | Tool
"legitimacy": "Suspicious", // Bot only: Suspicious | Legitimate
},
"confidenceLevel": "very_high", // low | medium | high | very_high; bands at /docs/detect#confidence-scores
"reasons": [
// string[], always. Human-readable, one per piece of classifying evidence
"User-Agent matched known agent pattern: GPTBot",
"Vendor IP + User-Agent cross-match: OpenAI GPTBot (training crawler)",
],
"signals": [
// array, always (may be empty). The evidence behind the verdict
{
"signalType": "pattern", // signature | pattern | behavioral | network | fingerprint
"confidence": 95.0, // number 0-100. Strength of this piece of evidence
"weight": 1.0, // number 0-1. 1.0 identity evidence, 0.4 heuristics, 0 recorded context
"source": "user_agent_pattern", // which detector produced it (see Signal sources)
"explanation": "User-Agent matched known agent pattern: GPTBot",
},
{
"signalType": "network",
"confidence": 93.0,
"weight": 1.0,
"source": "vendor_ip_feed",
"explanation": "Vendor IP + User-Agent cross-match: OpenAI GPTBot (training crawler)",
"metadata": { "tier": 2, "vendor_id": "openai_gptbot" }, // object, optional. Omitted when empty
},
],
"detectedAgent": { "type": "bot", "name": "GPTBot" }, // optional. type: ai_agent | bot; vendor set on verified vendor signatures
"botType": "ai_crawler", // optional. ai_crawler | search_engine | headless_browser | tool | ai_agent
"agentType": "GPTBot", // optional. Matched agent name, vendor id, MCP-I issuer, or "kya-os"
"verificationMethod": "pattern", // optional. none | pattern | signature | kya-http | kya-http-delegated | a2a | mcp_i_handshake | tier1_rfc9421 | error
"assurance": "anonymous", // always. anonymous | attested-bearer | key-bound | delegated
"riskLevel": "high", // low | medium | high
"forgeabilityRisk": "medium", // low (cryptographically verified) | medium (pattern) | high (engine error)
"timestamp": 1789500000, // integer, always. Unix seconds
// "metadata": { ... } object, optional. Path-specific keys (see Metadata keys)
// "requestId": "..." string, optional. Added by some integrations; never set by the engine
// "engine": { ... } object, optional. Copy of engineInfo on signature-verified paths
// "grantedScopes": [ ... ] string[], optional. Present when a delegation was verified
},
"enforcementMode": "observe", // enforce | observe. In observe mode your integration records the decision without acting on it
"engineInfo": {
"name": "checkpoint-engine-wasm", // checkpoint-engine-wasm | checkpoint-engine-wasi | checkpoint-engine-native
"version": "0.1.1",
"rulesetHash": "sha256:t1:f23d9a07…:t2:2e6a63de…:t3:fba4ef9a…:t4:unset", // hash of the bundled rules, per tier
"rulesetVersion": "0.1.1",
// "buildSha": "..." string, optional
},
"trace": [
// array, always. One entry per engine stage that ran
{
"name": "detection",
"verdict": "pass",
"latencyMicros": 4,
"reason": "AiCrawler (93% confidence)",
},
{ "name": "reputation", "verdict": "pass", "latencyMicros": 0 },
{ "name": "policy", "verdict": "pass", "latencyMicros": 0 },
],
// "network": { "trueIp", "asn", "isp", "routingType", "proxy" } object, optional. Present when network context was available
}Route on detectionClass, not isAgent
isAgent is true only for the AiAgent class. Crawlers such as GPTBot are Bot, so isAgent
is false for them. Other surfaces use a broader meaning: the /api/v1/detect result and stored
detection records treat any non-human class as an agent. Use detectionClass and botType to
decide what to do with a request.
Reading the object
confidenceis a detection score. It comes from fixed values per rule: 10 when nothing matched, 40 for suspicious headers or weak automation evidence, 55 to 60 for HTTP client libraries, 65 for a browser User-Agent on a non-browser TLS stack, 80 for headless or self-disclosed automation, 93 to 95 for a named or vendor-attributed agent, and 99 to 100 for a cryptographically verified agent. It is not a calibrated probability and not a fraud-risk score.- No evidence is not proof of a human.
Humanat confidence 10 means no agent indicator matched. A script that copies a browser's User-Agent and sends nothing else also lands there, so treat low-evidenceHumanverdicts accordingly in your own risk logic. - Identity and heuristics are separate axes.
verificationMethodandassurancesay what was cryptographically proven.signalssay what heuristics observed. A GPTBot User-Agent from an OpenAI IP address is strong heuristic evidence, but itsassuranceis stillanonymous. - Scales differ by surface.
confidenceis 0 to 100 in this object, in/api/v1/enforceand in the extended read-back. The legacy detections list and webhook payloads use 0 to 1. - Expect additions. New signal sources, metadata keys and reason codes are added over time. Ignore values you don't recognize rather than rejecting the response.
Top-level fields
Decision
decision is tagged by kind. Each kind carries its own payload.
// Permit: the request may proceed. policyId names the deciding policy when there is one
{ "kind": "Permit", "policyId": "allow-search-and-ai-crawlers" }
// Block: the request is refused. reason is tagged by kind (see the table below)
{ "kind": "Block", "reason": { "kind": "Tier3UAMatch", "pattern_id": "Automation Tools", "pattern_kind": "HeadlessBrowser", "confidence": 80 } }
// Challenge: the client must step up before retrying
{
"kind": "Challenge",
"params": {
"nonce": "c2f1…",
"audience": "https://app.example.com",
"expiresAt": 1789500300,
"algorithmsAccepted": ["EdDSA", "ES256"],
"minAssurance": "delegated", // optional
"policyId": "require-delegation", // optional
"challengeType": "human_step_up", // optional. Omitted for delegation; browser_integrity | human_step_up
},
}
// Redirect: send the client elsewhere
{ "kind": "Redirect", "target": { "url": "https://app.example.com/verify", "reason": "…", "state": "…", "policyId": "…" } }
// Instruct: tell an agent how to make an acceptable request
{
"kind": "Instruct",
"payload": {
"problem": "…",
"title": "…",
"suggestedActions": [{ "kind": "UseDifferentScope", "scope": "read:documents" }],
"policyId": "…", // optional
},
}suggestedActions[].kind is one of UseDifferentScope (scope), UpdateRequestField (field, acceptedValues), UpgradeProtocolVersion (version) or Other (code, detail).
Block reasons
Block reason fields are written in snake_case, unlike the rest of the object.
The table is in order of severity. When more than one outcome applies, Redirect wins, then Challenge, then Instruct, then the most severe Block reason.
Detection detail
Classes
AiAgent may also carry vendor and model. Bot carries botType (Scraper, SearchEngine, Tool) and legitimacy (Suspicious, Legitimate).
Signals
Each entry in detectionDetail.signals is one piece of evidence.
Signal sources
/api/v1/detect returns a single summary signal with source kya_os_engine instead of this list. /api/v1/enforce returns the full list when you set options.includeDetectionResult.
Metadata keys
Keys not listed here are diagnostic and may change.
Reason codes
Reason codes are the machine-readable form of reasons: an ordered list of detection/* codes, most significant evidence first and never empty.
They appear in /api/v1/enforce (detection.reasonCodes), in the extended read-back (reasonCodes), and in the DNS gateway's KYA-Reason-Codes header (up to five).
Captured context
Alongside the verdict, Checkpoint stores the context it observed for the request: TLS details from the DNS gateway, device and browser attributes from the Beacon or pixel, interaction counters, and IP intelligence. It is part of the stored detection record and of full response delivery.
{
"transport": {
// DNS gateway only
"tlsJa4": "t13d1516h2_8daaf6152771_02713d6af862",
"tlsVersion": "TLSv1.3",
"cfBotScore": 2, // when Cloudflare Bot Management is available
"cfVerifiedBot": false,
"asn": 16509,
"asOrganization": "Amazon.com, Inc.",
},
"client": {
// Beacon, pixel and native collectors. Each attribute is { "value": "<string>" }
"attributes": {
"device.platform": { "value": "MacIntel" },
"browser.timezone": { "value": "America/Chicago" },
"screen.resolution": { "value": "1512x982" },
"client.webdriver": { "value": "false" },
"platform.hardwareConcurrency": { "value": "10" },
},
},
"behavioural": {
"mouseMovements": 42,
"clickCount": 3,
"scrollDepthPercent": 60,
"timeOnPageMs": 18450,
},
"network": {
"trueIp": "3.19.44.10",
"asn": 16509,
"isp": "Amazon.com, Inc.",
"routingType": "hosting", // residential | mobile | datacenter | hosting | unknown
"proxy": { "isProxy": true, "proxyType": "datacenter", "confidence": 95 }, // vpn | tor | datacenter | residential_proxy | unknown
},
}A missing network field means no data was available for that address, not that the address is clean.
Examples by evidence path
Each example shows only the fields that differ from the fully expanded object.
"confidence": 10.0,
"detectionClass": { "type": "Human" },
"confidenceLevel": "low",
"reasons": ["No known agent indicators matched"],
"signals": [],
"verificationMethod": "none",
"riskLevel": "low"