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. Values are illustrative. 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": 99.0, // number 0-100, always. How strongly the evidence indicates automation; see Reading the object
    "detectionClass": {
      // tagged by type: Human | AiAgent | Bot | IncompleteData
      "type": "Bot",
      "botType": "Scraper", // Bot only: Scraper | SearchEngine | HeadlessBrowser | Tool | HighVelocity
      "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": 90.0, // number 0-100. Strength of this piece of evidence
        "weight": 0.5, // number 0-1. How much this evidence counts toward confidence; 0 for recorded context
        "source": "user_agent_pattern", // which detector produced it (see Signal sources)
        "explanation": "User-Agent matched known agent pattern: GPTBot",
      },
      {
        "signalType": "network",
        "confidence": 90.0,
        "weight": 0.5,
        "source": "vendor_ip_feed",
        "explanation": "Vendor IP + User-Agent cross-match: OpenAI GPTBot (training crawler)",
        "metadata": { "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 | high_velocity | ai_agent
    "agentType": "GPTBot", // optional. Matched agent name, vendor id, KYA-OS proof 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.2.0",
    "rulesetHash": "sha256:…", // identifies the bundled detection rules
    "rulesetVersion": "0.2.0",
    // "buildSha": "..."          string, optional
  },

  "trace": [
    // array, always. One entry per engine stage that ran
    {
      "name": "detection",
      "verdict": "pass",
      "latencyMicros": 4,
      "reason": "AiCrawler (99% 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

  • confidence measures how strongly the evidence indicates automation. It runs from 0 to 100 and weighs many independent signals together: network and TLS characteristics, HTTP and header consistency, browser and runtime integrity, behavior, and known-agent intelligence. Verified cryptographic identity takes precedence over heuristic evidence and scores at the top of the range. confidence is a score of the evidence, not a measured probability, a measure of certainty in the class, or a fraud-risk score. confidenceLevel gives its band, and riskScore is a separate, uncalibrated score.
  • No evidence is not proof of a human. Human with an empty signals list means nothing indicated automation, not that a person was confirmed. Weigh low-evidence Human verdicts accordingly in your own risk logic.
  • Identity and heuristics are separate axes. verificationMethod and assurance say what was cryptographically proven. signals say what heuristics observed. A GPTBot User-Agent from an OpenAI IP address is strong heuristic evidence, but its assurance is still anonymous.
  • Scales differ by surface. confidence is 0 to 100 in this object, in /api/v1/enforce and 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

FieldTypePresentDescription
decisionobjectAlwaysThe policy outcome, tagged by kind. See Decision.
detectionDetailobjectAlwaysClassification, score and evidence. See Detection detail.
enforcementModestringAlwaysenforce or observe.
engineInfoobjectAlwaysThe engine build that produced the verdict.
tracearrayAlwaysPer-stage audit entries: name, verdict, latencyMicros, optional reason.
networkobjectWhen network context was availableIP intelligence for the request. See Captured context.

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": "PolicyDenied", "detail": "Automated traffic is not allowed on /checkout", "policyId": "block-automation-on-checkout" } }

// 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.

reason.kindFieldsMeaning
RevokednoneA presented credential is revoked, or its status could not be confirmed.
InvalidSignaturenoneA signature did not verify.
UnauthenticatednoneA proof was missing, unresolvable, replayed, or bound to the wrong holder, audience or session.
ExpirednoneA credential or proof is outside its validity window.
OutOfScoperequested, granted[]The delegation does not grant the scope the request needs.
LowReputationscore, thresholdReputation is below the configured threshold.
PolicyDenieddetail, policyId (optional)A policy rule denied the request, including a delegation that needs a stronger proof.
AgentAttributionvendor, tier, confidenceBlocked on vendor attribution.
ParseErrordetailThe request could not be parsed for verification.
Tier3UAMatchpattern_id, pattern_kind, confidenceBlocked on a User-Agent pattern match. pattern_kind is KnownAiAgent, AiCrawler or HeadlessBrowser.

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

FieldTypePresentDescription
isAgentbooleanAlwaystrue only for the AiAgent class.
isBotbooleanOmitted for IncompleteDataWhether the client is automated.
isAiCrawlerbooleanOmitted for IncompleteDataWhether the client is an AI training or retrieval crawler.
confidencenumberAlwaysHow strongly the evidence indicates automation, 0 to 100.
detectionClassobjectAlwaysClassification, tagged by type. See Classes.
confidenceLevelstringAlwayslow, medium, high or very_high; see Confidence scores.
reasonsstring[]AlwaysHuman-readable explanations of the classifying evidence.
signalsarrayAlways, may be emptyThe evidence behind the verdict. See Signals.
detectedAgentobjectWhen an agent or bot is namedtype (ai_agent or bot), name, and vendor on verified vendor signatures.
botTypestringFor bots and verified agentsai_crawler, search_engine, headless_browser, tool, high_velocity or ai_agent.
agentTypestringWhen an agent or bot is namedMatched agent name, vendor id, KYA-OS proof issuer, or kya-os for the kya-http/2 profile.
verificationMethodstringOmitted when a presented credential was rejectedHow the identity was established. See Enumerations.
assurancestringAlwaysThe strongest identity binding proven: anonymous, attested-bearer, key-bound or delegated.
riskLevelstringAlwayslow, medium or high.
forgeabilityRiskstringAlwaysHow easily the evidence could be forged: low, medium or high.
metadataobjectWhen the evidence path adds keysSee Metadata keys.
timestampintegerAlwaysUnix seconds.
requestIdstringWhen your integration sets oneNot set by the engine.
engineobjectSignature-verified pathsSame shape as engineInfo.
grantedScopesstring[]When a delegation was verifiedThe scopes the delegation grants.

Classes

ClassificationdetectionClassbotTypeisBotisAiCrawlerriskLevel
Human{ "type": "Human" }nonefalsefalselow
Known AI agent (User-Agent){ "type": "AiAgent", "agentType": "ChatGPT" }nonefalsefalsehigh
AI crawlerBot, Scraper, Suspiciousai_crawlertruetruehigh
Search engine crawlerBot, SearchEngine, Legitimatesearch_enginetruefalselow
Headless or automated browserBot, HeadlessBrowser, Suspiciousheadless_browsertruefalsemedium
HTTP client or other botBot, Tool, Legitimatetooltruefalselow
High request rateBot, HighVelocity, Suspicioushigh_velocitytruefalsemedium
Verified vendor signatureAiAgent, with agentType and vendorai_agenttruefalselow
Verified KYA-OS agent (HTTP){ "type": "AiAgent", "agentType": "kya-os" }ai_agenttruefalselow
Verified KYA-OS proofAiAgent, with agentType set to the issuernonefalsefalselow
Incomplete data{ "type": "IncompleteData" }noneomittedomittedmedium

AiAgent may also carry vendor and model. Bot carries botType (Scraper, SearchEngine, HeadlessBrowser, Tool, HighVelocity) and legitimacy (Suspicious, Legitimate).

Signals

Each entry in detectionDetail.signals is one piece of evidence.

FieldTypeDescription
signalTypestringsignature, pattern, behavioral, network or fingerprint.
confidencenumberStrength of this evidence, 0 to 100.
weightnumberHow much this evidence counts toward confidence, 0 to 1. Recorded context has weight 0.
sourcestringThe detector that produced it.
explanationstringHuman-readable description.
metadataobjectSource-specific details. Omitted when empty.

Signal sources

sourcesignalTypeWhat it recordsmetadata keys
user_agent_patternpatternThe User-Agent matched a known agent pattern.none
header_heuristicpatternAgent or vendor headers, or a header set inconsistent with a browser.none
vendor_ip_feednetworkThe request IP belongs to the vendor the User-Agent names.vendor_id
ip_heuristicnetworkAn IP-only heuristic matched.none
ip_intelligencenetworkIP intelligence flagged a proxy, VPN or hosting network.routing_type, proxy_type
ua_tls_mismatchfingerprintA browser User-Agent arrived on a TLS stack used by non-browser tooling.Diagnostic only
transport.ja4fingerprintThe TLS client fingerprint observed at the edge. Recorded context.tls_ja4, tls_version
transport.cloudflare_bot_managementnetworkCloudflare's bot management score, on the DNS gateway.cf_bot_score, cf_verified_bot
scanner_misclassification_hintnetworkCloudflare's score contradicted a human classification.cf_bot_score
client_headless_escalationfingerprintBrowser automation evidence from the Beacon changed the classification.Diagnostic only
client.attributesfingerprintDevice and browser attributes from the Beacon or pixel. Recorded context.attributes
behavioural.interactionbehavioralInteraction counters. Recorded context.mouse_movements, click_count, scroll_depth_percent, time_on_page_ms
session_velocitybehavioralRequest volume for the session. Recorded context.request_count_in_window, window_seconds, requests_per_minute
tier1_rfc9421signatureA vendor's HTTP message signature verified (Web Bot Auth).none
kya_http_bindingsignatureA KYA-OS HTTP signature verified.none
kya_delegation_bearersignatureA KYA-OS delegation credential verified.none
mcp_isignatureA KYA-OS proof verified.none
a2a_agent_cardsignature or patternAn A2A Agent Card was checked; signature when its signature verified.none

Signal metadata keys not listed here are diagnostic and may change.

/api/v1/detect returns this same list on result.signals, unconditionally, on every response. /api/v1/enforce returns it only when you set options.includeDetectionResult.

Metadata keys

KeyPresent onMeaning
verified_protocolVerified signaturesrfc9421 or kya-http.
verified_vendor, key_idVerified vendor signaturesThe vendor and the key that signed.
covered_componentsVerified vendor signaturesThe HTTP message components the signature covers.
tier1_failure_reason, tier1_skipped_reasonVendor signatures that failed or were not checkedWhy verification did not succeed. The request is classified by other evidence.
agent_didKYA-OS agentsThe agent's DID.
kya_session_idKYA-OS delegation credentialsThe delegation session.
kya_error_codeRejected KYA-OS credentialsA kyaos/… error code.
a2a_card_name, a2a_card_providerVerified A2A Agent CardsThe card's name and provider.
a2a_unverified_reasonA2A Agent Cards that did not verifyWhy the card was not verified.

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).

CodeMeaning
detection/tier1-attribution-verifiedA vendor signature verified.
detection/rfc9421-signature-verifiedAn HTTP message signature verified.
detection/signature-verifiedA KYA-OS HTTP signature verified.
detection/delegation-verifiedA KYA-OS HTTP signature and delegation verified.
detection/mcp-i-verifiedA KYA-OS handshake verified.
detection/did-signature-verifiedA DID signature verified.
detection/a2a-verifiedAn A2A Agent Card verified.
detection/verification-errorVerification ended in an error.
detection/ua-pattern-matchThe User-Agent matched a known agent pattern.
detection/header-heuristicA header heuristic fired.
detection/ip-heuristicAn IP heuristic fired.
detection/vendor-ip-corroboratedThe request IP matched the vendor the User-Agent names.
detection/ip-intelligence-proxy-signalIP intelligence flagged a proxy, VPN or hosting network.
detection/ja4-fingerprint-matchA TLS (JA4) fingerprint was recorded for the request.
detection/ua-tls-mismatchA browser User-Agent arrived on a non-browser TLS stack.
detection/client-integrity-failureBrowser integrity checks failed.
detection/client-attribute-signalBrowser or device attributes were recorded.
detection/behavioral-signalInteraction counters were recorded.
detection/mcp-i-signalKYA-OS handshake evidence was present.
detection/kya-http-binding-signalKYA-OS HTTP signature evidence was present.
detection/kya-delegation-bearer-signalKYA-OS delegation credential evidence was present.
detection/tier1-attribution-signalVendor signature evidence was present.
detection/ai-crawler-flagThe client is an AI crawler.
detection/zero-evidence-humanClassified as human with no evidence.
detection/incomplete-data-overrideNot enough evidence to classify.
detection/classified-without-signal-evidenceClassified as automated without a mapped signal.

Risk score

riskScore is an uncalibrated score of the same evidence, from 0 to 1. It is never derived from confidence and never feeds into it, and the two are on different scales, so they can differ widely. Don't convert one into the other.

FieldTypeDescription
riskScorenumber or null0 to 1, rounded to two decimals. null when no uncalibrated score was produced: the request was verified by signature, the score is turned off in your integration's engine configuration, or detection was skipped. After an engine failure it is null or absent.
riskScoreSourcestring or nullWhich score riskScore was taken from. Always uncalibrated today. null exactly when riskScore is null.

They appear in the /api/v1/detect result, in /api/v1/enforce detection when you set options.includeDetectionResult, and in the .NET (RiskScore, RiskScoreSource) and Java (riskScore(), riskScoreSource()) SDK detection results. The engine object on this page, the Next.js and Express SDKs, and response headers do not carry them.

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" },
      "browser.language": { "value": "en-US" },
      "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. Values are illustrative.

"confidence": 1.0,
"detectionClass": { "type": "Human" },
"confidenceLevel": "low",
"reasons": ["No known agent indicators matched"],
"signals": [],
"verificationMethod": "none",
"riskLevel": "low"

What each integration returns

IntegrationWhat you receive today
SDK middleware (Java, .NET, Next.js, Express)Response headers with class, confidence, agent and verification method, and the SDK's typed result in your application. The .NET and Java results also carry riskScore and riskScoreSource.
DNS gatewayKYA-* response headers, including KYA-Detection-Class, KYA-Confidence and KYA-Reason-Codes.
POST /api/v1/detectA result projection with the full signals list, reasonCodes, confidenceLevel, isAiCrawler, riskScore and riskScoreSource.
POST /api/v1/enforceThe decision; with options.includeDetectionResult, the full signals list, reasonCodes, confidenceLevel, isAiCrawler, riskScore and riskScoreSource.
PixelA detection projection in the response and in the checkpoint:detection browser event.
BeaconA receipt with the consolidated session id and a signed browser posture token.
Read-back APIThe stored record, including signals, network, geo, decision and reasonCodes, with ?view=extended.
Webhooksdetection.created and enforcement.decided summaries.
Full response deliveryThe complete object on this page. Enabled by Vouched per project or organization.

Enumerations

FieldValues
decision.kindPermit, Block, Challenge, Redirect, Instruct
detectionClass.typeHuman, AiAgent, Bot, IncompleteData
detectionClass.botTypeScraper, SearchEngine, HeadlessBrowser, Tool, HighVelocity
detectionClass.legitimacySuspicious, Legitimate
botTypeai_crawler, search_engine, headless_browser, tool, high_velocity, ai_agent
verificationMethodnone, pattern, signature, kya-http, kya-http-delegated, a2a, mcp_i_handshake, tier1_rfc9421, error
assuranceanonymous, attested-bearer, key-bound, delegated, from weakest to strongest
confidenceLevellow, medium, high, very_high
riskLevel, forgeabilityRisklow, medium, high
signals[].signalTypesignature, pattern, behavioral, network, fingerprint
enforcementModeenforce, observe
trace[].namedetection, identity, signature, revocation, expiration, scope, reputation, policy
trace[].verdictpass, fail, skip
params.challengeTypedelegation (default, omitted), browser_integrity, human_step_up
network.routingTyperesidential, mobile, datacenter, hosting, unknown
network.proxy.proxyTypevpn, tor, datacenter, residential_proxy, unknown
engineInfo.namecheckpoint-engine-wasm, checkpoint-engine-wasi, checkpoint-engine-native

Values that contain mcp_i or mcp-i, such as mcp_i_handshake and detection/mcp-i-verified, keep the former name of KYA-OS, MCP-I.