跳转到主要内容
身份认证活动及其随版本发布而变化的 Webhook 投递,记录在 认证事件与 Webhook 中。请勿使用当前目标 API 注册未列出的认证事件类型。

概览

Webhook 是 Didit 在验证会话、企业会话、供应商用户、供应商企业或交易状态发生变化时,向您的后端推送实时更新的方式。为一个或多个 Webhook 目标订阅您关心的事件,您就能在结果生成的那一刻做出响应,通常在用户完成验证流程后的几秒内。 Webhook 是推荐的集成方式。虽然支持将 GET /v3/session/{id}/decision/ 作为备用方案进行轮询,但轮询速度更慢、请求成本更高,并且会漏掉 data.updated、transaction.status.updated 以及仅通过 Webhook 发出的实体级变更等事件。请将 Webhook 投递视为事实来源,仅在冷启动或进行对账时才使用轮询。 本章是 Didit Academy 集成课程的这一部分,承接 Webhook 概览。 Academy 集成课程从 3:12 开始讲解 Webhook:添加目标、选择事件,以及您将在下文中用于验证的签名密钥。
Cloudflare / WAF 用户。 Didit 从静态 IP 18.203.201.92 投递 Webhook,其请求头为 User-Agent: DiditWebhook/2.0 +https://didit.me。如果您的边缘节点会拦截未知客户端,请在 Security > WAF > Tools > IP Access Rules 中允许此 IP,并为接收主机名选择 允许。

事件类型

在 Webhook 目标的 subscribed_events 数组中使用准确的值。没有通配符,请逐一列出您想接收的每一类事件,并且可以把事件分散到多个 Webhook 目标中。 本表中的值即为可订阅事件的完整集合,不存在 session.status.updated、kyc.completed 或类似事件。Didit 唯一的其他投递是未签名的 kyb.registry_search.resolved 回调,它会发送到您在调用 POST /v3/kyb/search/ 时传入的每次请求的 webhook_url,而不会发送到任何 Webhook 目标。
Business Console > API & Webhooks > Try Webhook 菜单会为以下每一种事件发送结构完整的 payload:已通过、已拒绝、审核中、Unicode 名称、KYC/KYB、实体、活动和交易。请在正式上线前使用它验证您的 endpoint。

Payload 结构

信封结构

每个 Webhook 共用同一种信封结构。字段始终使用 sort_keys=True 和紧凑分隔符(, / :)进行序列化,这样相同的 payload 在两端都能生成相同的签名。 对于会话事件(status.updated,以及常规会话和企业会话上的 data.updated),信封还包含以下字段:

会话信封示例

decision 对象与 GET /v3/session/{id}/decision/ 返回的结构相同。关于每个功能的规范字段参考(id_verifications[]、aml_screenings[] 等上的每个属性),请参阅数据模型。我们有意不在此重复各功能的字段表,以便该结构只保存在一处。

V3 复数形式的数组(重要)

在 decision 内部,每个功能的结果都以数组(复数形式)表示,因此单个工作流可以包含同一功能的多个实例(例如跨多份证件进行多次身份证件验证):
每一项都包含与工作流图谱匹配的 node_id,以及每个功能的 status。请勿读取旧版 V2 单数形式的字段(id_verification、nfc、liveness、face_match、phone、email、poa、aml、ip_analysis、database_validation);这些字段仅在 Webhook 目标被明确固定为 webhook_version: "v2" 时才会出现。 电子签名结果位于 signatures[] 中,仅当工作流包含电子签名步骤时才存在:每位签署人一项,包含签署人、验证码确认、证书、时间戳、每份文档的哈希值和下载路径,以及证据 PDF。没有单独的签名事件:status.updated 会告诉你何时读取这些结果。参见电子签名报告。 银行验证结果位于 bank_verifications[] 中,每个银行验证步骤对应一项。每项的 method 说明账户是如何被验证的:open_banking(银行登录)、account_lookup(账户核查),或 statement 或 microdeposits 备用方式;在评估账户之前为 null。当用户选择Continue without your bank时,continued_without_bank 为 true,continuation 说明原因。此时 method 为 none,除非之前已评估过某次尝试:参见用户无法验证银行账户时。通过账户核查验证的账户不会读取任何财务数据,因此 financial_data.not_collected 列出该步骤所要求但未收集的余额、交易或收入信息。参见银行验证方式。

Investigator 数据块

对于用户或企业会话的 V3 decision,还会包含 investigator 字段:该会话最近一次的 Investigator 审核;若会话从未进行过审核,则为 null。 证件收集功能(KYB 证件和 Document AI)没有专用的复数数组,它们会出现在决策的 features[] 列表中,格式为 { "feature": "DOCUMENT_AI", "node_id": "…" }(每个节点一条记录)。参见 Document AI。 用户验证决策还包含一个 biometric_consent 对象:说明会话是否要求明确的生物识别同意、trigger、回答的 status 及其证据。status: "pending" 且 reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK" 表示低于 4.10.0 的原生 SDK 在未执行同意步骤的情况下采集了人脸。参见生物识别同意。

身份证件验证方法键

每个 id_verifications[] 项都会说明它由哪种身份证件验证方法生成,因此处理程序可以根据实际获得的证据进行分支处理: 现有处理程序无需修改即可继续工作:证件会话会将 verification_method 设为 document,其余字段保持为 null。各字段的详细类型见数据模型。

已通过的钱包会话 (status.updated)

实体事件 payload

实体状态为 ACTIVE、FLAGGED 或 BLOCKED。user.data.updated 和 business.data.updated 保留 status 字段,并新增 changed_fields 数组以及 changes 映射,其格式为 { field: { previous, current } }。business.* 事件使用 vendor_business_id,而不是 vendor_user_id。

交易事件 payload

交易 Webhook 使用相同的分发基础设施和相同的信封结构,但用交易标识替代会话标识:
action_required 为 null,或为待处理的用户操作(type 为 wallet_ownership 或 verification_session,并附带其 url),详见所需用户操作。 新交易默认为 APPROVED。如果规则、黑名单或工作流在创建过程中更改了状态,则初始的 transaction.created payload 会反映该最终状态。transaction.status.updated 的结构相同,但 status 为更新后的值。交易状态包括 APPROVED、IN_REVIEW、DECLINED 或 AWAITING_USER;severity 取值为 UNKNOWN、LOW、MEDIUM、HIGH 或 CRITICAL,direction 取值为 INBOUND 或 OUTBOUND。transaction.created 和 transaction.status.updated 仅投递到生产环境应用。沙盒中的 Travel Rule 交换确实会发出 travel_rule.status.updated,其中 environment: sandbox。

KYB 注册库搜索回调

异步的 POST /v3/kyb/search/ 流程还会投递一个额外的 payload,它不是目标事件:当你在搜索请求中传入 webhook_url 时,注册库完成解析后,Didit 会以 POST 方式向该 URL 发送 kyb.registry_search.resolved 回调。它与目标 Webhook 有三点不同:
  • 它是未签名的:不包含 X-Signature* 请求头。Didit 改用 X-Didit-Unsigned-Callback: true 进行标记;请将 request_id 与搜索请求返回的 ID 进行比对,以验证该回调。
  • 事件名称位于 event_type 中(而不是 webhook_type),且不包含 application_id 或 environment。
  • timestamp 和 created_at 为 epoch 整数,与其他 Webhook 相同,但与搜索端点中 ISO 格式的 created_at 不同。
该回调遵循与目标 Webhook 相同的重试策略(重试会更新时间戳 timestamp,并保持未签名状态)。完整的候选列表结构请参见 KYB Registry API。

签名验证

每个 Webhook 都使用目标的 secret_shared_key 进行 HMAC-SHA256 签名。我们会发送三个签名请求头,您可以选择最适合自己技术栈的一个: Didit 始终发送的请求头: 在目标的签名密钥轮换后的 24 小时内,投递还会携带 X-Signature-Previous、X-Signature-V2-Previous 和 X-Signature-Simple-Previous(参见签名密钥轮换)。

签名密钥轮换

您可以在 Business Console 中轮换目标的签名密钥。 轮换后的 24 小时内,发往该目标的每次投递都会额外携带三个请求头,它们使用被替换的密钥生成: 只要处理程序接受普通签名请求头或其 -Previous 请求头中的任一匹配结果,在部署新密钥期间就能持续完成验证:旧密钥与 -Previous 请求头匹配,新密钥与普通请求头匹配。下方的代码示例即采用这种做法。 请在 24 小时内部署新密钥,因为此后只有新密钥能通过验证。GET /v3/webhook/destinations/{destination_uuid}/ 上的 previous_secret_expires_at 会告诉您这 24 小时何时结束。 重试和重发在发送时会使用目标当前的密钥重新签名,并且只在这 24 小时内携带 -Previous 请求头。 在 24 小时内再次轮换,会立即让最旧的密钥失效:只有在新一轮轮换前处于当前状态的密钥,才会在新一轮轮换后的 24 小时内继续通过 -Previous 请求头验证。 -Previous 请求头仅适用于 Webhook 目标。用于签名旧版 webhook_url 的应用级 secret_shared_key 没有重叠期:使用 PATCH /v3/webhook/ 上的 rotate_secret_key 轮换它后,旧密钥会立即失效。

X-Signature-Simple 已弃用

X-Signature-Simple 验证的是信封,而不是 payload。 其规范字符串只包含 timestamp、session_id、status 和 webhook_type。它不包含 decision,也不包含 resubmit_info、metadata、vendor_data 或 event_id。如果 decision 被改写,而这四个字段保持不变,请求仍会通过 X-Signature-Simple 验证。对于完全不包含 session_id 的事件,它的保护更弱。交易事件(transaction_id、txn_id、amount、score)和实体事件(vendor_user_id、vendor_business_id)的签名内容为 "{timestamp}::{status}:{webhook_type}",它无法标识事件涉及的是哪一笔交易或哪个实体。同一秒内以相同状态上报的两笔不同交易,会得到相同的 X-Signature-Simple。 travel_rule.status.updated、workflow.compliance_changed 和 transaction_rule_suggestions.created 事件也不包含 status,因此它们的签名内容为 "{timestamp}:::{webhook_type}",例如 "{timestamp}:::travel_rule.status.updated"。如果 X-Signature-Simple 是您唯一检查的请求头,请将这四个字段之外的所有内容视为不可信,并通过 API 重新获取记录:会话请使用 GET /v3/session/{session_id}/decision/,交易请使用 GET /v3/transactions/{transaction_id}/。这些 API 才是权威记录的来源。
这是兼容性约束,而不是我们可以原地修补的问题。四字段规范字符串是一份线上协议:每个验证 X-Signature-Simple 的接收方都会精确地重新计算这四个字段,因此改变该请求头的签名内容,会让所有接收方在签名验证环节同时失效。要让签名覆盖请求体,还需要一种双方都能逐字节复现的规范 JSON 格式,而 Didit 已经以 X-Signature-V2 的形式提供了这种格式。与其再增加一个带有独立规范化规则的、覆盖请求体的变体,我们保持该请求头不变,并将其标记为已弃用,转而推荐现有的完整 payload 变体。 这对您意味着:
  • 线上行为不变。 X-Signature-Simple 会在每次投递中继续发送,计算方式保持不变。现有验证程序将继续正常工作。如需移除,我们会提前充分通知。
  • 新集成必须使用 X-Signature-V2。 它兼容中间件,并且覆盖整个 payload。
  • 如果您无法停止使用 X-Signature-Simple,请先验证它,然后通过 API 获取记录,而不是从 Webhook 的请求体中读取数据。

为什么有三种变体?

一些 Web 框架(Express 请求体解析器、Django 中间件、API 网关)会在您的处理程序读取请求体之前,悄悄地重新编码 JSON。如果原始请求体包含 "José",而您的中间件将其改写为 "José",那么即使数据相同,字节也变了,X-Signature 就会验证失败。X-Signature-V2 基于规范 JSON 形式计算(键排序、紧凑分隔符、不转义 Unicode),几乎所有中间件都能确定性地复现它。而已弃用的 X-Signature-Simple 在连这一步也失败时,会退而只对一个简短、与解析器无关的字符串签名。由于它只签名这个短字符串,从不签名请求体,因此无法验证请求体的内容。

推荐的验证顺序

  1. 首先尝试 X-Signature-V2。将 JSON.parse(body) 按排序后的键重新编码,并保留 Unicode 字符,然后计算 HMAC-SHA256(secret, canonical),并使用 timingSafeEqual 与请求头进行比较。
  2. 如果 V2 验证失败,且你可以读取原始字节,则尝试用 HMAC-SHA256(secret, rawBody) 验证 X-Signature。
  3. 仅当两者都失败时,才回退到已弃用的 X-Signature-Simple,即验证 HMAC-SHA256(secret, "{timestamp}:{session_id}:{status}:{webhook_type}")。这种方式只能验证外层信封。请将正文中的 decision 视为不可信,并在据此采取行动之前,通过 GET /v3/session/{session_id}/decision/ 重新获取。
每一步中,如果存在对应的 -Previous 请求头,则两个请求头中任意一个匹配即可接受(参见 签名密钥轮换)。 在所有情况下,对于时间戳距当前时间超过 5 分钟 的任何请求(abs(now - X-Timestamp) > 300),都应 拒绝,以防御重放攻击。

重试策略

如果你的 endpoint 返回 5xx 或 404,Didit 会以指数退避方式最多重试 2 次:
  • 第 1 次重试:约在首次失败后 1 分钟。
  • 第 2 次重试:约在第 1 次重试后 4 分钟。
第二次重试之后,该次投递将被丢弃。每次投递尝试(首次投递及重试)都会在 Business Console 中该目标的 投递 标签页下记录为单独的条目,因此你可以重放或检查任何一次尝试。 投递日志中的每次尝试都带有 attempt 编号:事件的首次投递为 1,之后每次重试或重新发送,编号比其所重复的那次尝试多 1。 自动重试会发送到首次尝试所使用的 URL,即使之后你已修改了目标的 url。 手动重新发送会发送到目标当前的 URL,因此修正 URL 也会修正重新发送的结果。 需要了解的其他投递规则:
  • 出站 HTTP 请求在 5 秒 后超时。
  • 出于 SSRF 防护的考虑,Didit 会阻止向私有地址或 localhost URL 投递,并且从不跟随重定向。请使用可直接响应的公共 HTTPS endpoint。
  • 目标 url 中如果包含原始反斜杠、控制字符,或 URL 的权限部分中出现多个 @,将被视为格式错误而拒绝。此类 URL 无法创建,已有的 URL 也无法重新投递或重放。请使用普通的 https://host/path 格式 URL,并且最多只包含一个用户信息段(用于基本认证风格的 Webhook URL)。
  • 2xx 视为成功。超时和连接失败可以重试(在投递日志中显示为 504/503);除 404 以外的 3xx 和 4xx 响应不会重试。
  • 重试时,Didit 会使用新的 X-Timestamp 重新计算签名,因此时间戳与签名始终保持一致。
  • 重试和重新发送均使用目标在发送时的当前签名密钥进行签名。

投递顺序

Didit 不保证 Webhook 到达你这里的顺序。 每次投递都是独立排队的,且重试会在首次尝试之后数分钟才到达,因此,针对 Approved 的 status.updated 可能会在针对 In Progress 的较早事件之前到达。 据此构建你的接收端:
  • 将 Webhook 视为某些内容已发生变化的信号。当顺序很重要时,调用 GET /v3/session/{session_id}/decision/ 并根据当前的 status 采取行动。
  • 决不允许较旧的事件覆盖较新的状态:将事件的 created_at 与你为该记录存储的上一个事件的时间戳进行比较,忽略较旧的事件。
  • 以 event_id 作为重复事件的键,该值在重试时保持不变。
Didit 会按固定顺序对 Travel Rule 转账的事件进行排队,具体描述见 Travel Rule 交换状态变更,但重试仍可能改变事件到达的顺序。

设置目标

你可以在 Business Console > API & Webhooks 中管理目标,也可以通过 Management API 进行管理。
1

创建目标

调用 POST /v3/webhook/destinations/(或在控制台中点击 添加目标),并提供 label、公共 url、webhook_version("v3"),以及一个 subscribed_events 数组,其中包含该 endpoint 应接收的每个事件类别。至少需要一个事件,且不存在通配符。
2

保存 secret_shared_key

创建响应会返回该目标的 secret_shared_key。请将其与其他服务器密钥一起保存:它只属于此目标,并且是所有三种 HMAC-SHA256 签名变体的输入。GET /v3/webhook/destinations/{destination_uuid}/ 会再次将其返回给 API 密钥调用方,以及有权读取 Webhook 的控制台用户。
3

实现 endpoint

公开一个 HTTPS POST 路由,读取原始请求体,验证签名(优先使用 X-Signature-V2),检查时间戳窗口,然后根据 webhook_type 进行分派。一旦工作已加入队列,即返回 2xx,繁重的处理请异步进行。
4

确认接收

在该目标的 投递 标签页中查看状态。正常的 Webhook 会在一两秒内返回 200。5xx/404 会触发 Didit 的重试策略;持续失败的投递在第二次重试后被丢弃。
5

使用 Try Webhook 进行迭代

使用 Try Webhook 控制台场景,驱动你的 endpoint 依次处理已通过、已拒绝、审核中、KYB、实体、活动和交易的 payload,然后再开启生产流量。
Business Console 中的 Didit Webhook 测试功能

直接从 Business Console 发送测试 Webhook,在正式上线前验证你的 endpoint。

你可以根据需要创建任意数量的目标。常见的做法是每个使用方一个目标:例如,KYC 事件发送到你的认证服务,KYB 事件发送到你的合规运营服务,交易事件发送到你的欺诈处理队列。每个目标都有自己的密钥、版本和订阅列表,因此一个使用方的密钥轮换或错误部署,不会影响其他使用方。

代码示例

为确保您的 Webhook endpoint 安全,请使用目标的 secret_shared_key 验证传入请求的真实性。
请使用 X-Signature-V2。 它最能抵御中间件重新编码带来的影响,并且能够完整验证请求体(包括 decision)。

Node.js / Express (推荐使用 X-Signature-V2)

如果您能够在任何解析器处理原始字节之前读取它们,原始的 X-Signature 变体同样可以使用,但它对原始请求体进行签名。为完整起见,我们将其保留在下方的旧版章节中。

Python / FastAPI (推荐使用 X-Signature-V2)

PHP / Laravel (推荐使用 X-Signature-V2)

PHP 的 JSON 默认设置无法生成规范形式。其中有四项需要覆盖,缺少任何一项都会改变被签名的字节,导致摘要永远无法匹配: 空对象陷阱是其中最棘手的一项。Didit 的 payload 中经常包含空映射,例如 risk_view.countries.risk_scores、risk_view.crimes.risk_scores 和 risk_view.custom_list,因此关联数组的往返转换会在普通的已通过会话上破坏签名,而不只是在少数罕见的边缘情况下出错。
另外两点需要注意:
  • 在 PHP 中,整数值的浮点数无需特殊处理。 Didit 将它们序列化为整数(100.0 → 100),PHP 的 json_encode 对整数值浮点数的输出方式相同,因此不需要像上面的 Node.js 示例那样执行 shortenFloats 步骤。
  • 请保持 serialize_precision 为 -1(自 PHP 7.1 起的默认值)。如果您的主机将其覆盖为 17,json_encode 会将 87.42 输出为 87.420000000000002,每次 X-Signature-V2 校验都会失败。
如果您无法使规范形式匹配,上文中的 verifySignatureRaw 是更简单的备选方案:Laravel 的 $request->getContent() 会返回未经修改的原始字节,因此只要 PHP 前面的任何环节都没有重新编码请求体,X-Signature 就能正常工作。这正是 X-Signature-V2 设计用来应对的情况,也是 V2 优先尝试的原因。

测试

您无需运行完整的验证流程,即可测试您的 endpoint。
  • 在 Business Console > API & Webhooks > Try Webhook 中选择一个场景(例如 approved_full_features、declined_face_mismatch、in_review_aml_hit、business_session_approved、transaction_created、activity_created、user_status_updated),然后将一个完整构造的 Webhook 发送到您的 Webhook 目标 URL。
  • 每个场景都使用与生产流量相同的三个签名请求头和规范编码进行签名,包括用于测试 Unicode 数据的 approved_kyc_with_unicode,以便您确认 X-Signature-V2 能够通过您的中间件正常工作。测试投递包含示例数据,并带有额外的 X-Didit-Test-Webhook: true 请求头(同时 User-Agent 中带有 (Test) 后缀),以便您将其排除在生产状态之外。
  • 如需调试回归问题,可以从 Webhook 目标的 Deliveries 标签页重放任何历史投递。
对于端到端的冒烟测试,请在您自己的应用中通过测试工作流运行一次真实验证。由此产生的 Webhook 与 Try Webhook 场景使用相同的信封、请求头和重试策略。

Examples

已通过的 KYC 会话 (status.updated)

已拒绝且带警告的会话 (status.updated)

已通过的企业会话 (status.updated, KYB)

已创建的交易 (transaction.created)

Travel Rule 交换状态变更 (travel_rule.status.updated)

travel_rule_status 的值为 Travel Rule 中记录的 13 种交换状态之一。 rail 的值为 INTERNAL、TRP、GTR、TRUST、VERIFYVASP、SYGNA 或 EMAIL 之一(在选定通道之前为空字符串;如果无法确定通道,或在 sunrise 注册中,始终为空字符串),或者当 Didit Test VASP 响应沙盒转账时为 TEST_VASP。direction 的值为 INBOUND 或 OUTBOUND。 沙盒事件包含 "environment": "sandbox"。TEST_VASP 事件还包含 test_vasp: true 和 test_vasp_scenario(即做出响应的场景)。 当 Didit 为 Travel Rule 转账创建交易时(包括调用 POST /v3/transactions/、存款后 sunrise 注册、入站 TRP 查询,或 INTERNAL 通道的入站环节),会先发送该交易的 transaction.created 事件,随后再发送该转账的 travel_rule.status.updated 事件。 如果某条规则在此步骤中更改了交易状态,transaction.status.updated 可能会在 transaction.created 之前发送。如果 sunrise 注册关联到您已创建的存款交易,则不会发送 transaction.created。 每个 Webhook 都是独立投递和重试的,因此,重试的事件仍可能晚于后续事件到达。请以 transaction_id 为键处理事件;需要了解交易当前状态时,请重新读取该交易。 通过 TRUST 发送的转账永远不会收到 COMPLETED 事件,因为 TRUST 不会返回 Didit 能够读取的任何内容。该转账会保持在 AWAITING_COUNTERPARTY 状态,直到确认截止时间,然后以 EXPIRED 结束。通过 GTR、VerifyVASP 和 Sygna Bridge 发送的转账,Didit 会从网络中读取交易对手的答复,事件随之发出(参见 Travel Rule 网络)。

工作流合规状态变更 (workflow.compliance_changed)

transition.from 和 transition.to 的值为 compliant、gaps_detected、pending_change、unknown_coverage 或 not_evaluated 之一。 检测到缺口时,severity 为 actionable;待变更时为 indicative;缺口已解决时为 informative。 Didit 会为每个发生变化的工作流发送一个事件。

已创建的交易规则建议 (transaction_rule_suggestions.created)

新增规则时 kind 为 ADD,修改现有规则时为 TWEAK,关闭规则时为 DISABLE。ADD 时 rule_id 为 null。 open_count 是本次运行后仍处于待处理状态的建议数量,包括新增的建议。 规则建议设置用于开启或关闭此 Webhook,参见 交易 Webhook。

Investigator 事件 (investigator.*)

十二个 investigator.* 事件使用与其他所有事件相同的通用字段(event_id、webhook_type、timestamp、created_at、application_id、environment)以及相同的签名请求头。它们只包含 ID 和数值:绝不包含姓名、审核员输入的理由、叙述内容或终端用户填写的任何内容。它们没有 session_id,所涉及的项目在 item 中指明。
provenance 说明编写报告的 Investigator 版本:
  • engine 是 Investigator 引擎的版本,为一个不透明的八个字符 ID。每当引擎变化时它都会改变,因此 engine 相同的两份报告由同一引擎编写。
  • agent_version 是代理的版本。
  • policy_version 是报告所遵循的您自己的策略版本。
  • model_id 是已弃用的别名,其值与 engine 相同。请改读 engine。
  • 不再发送 prompt_hash。
item.kind 说明项目的类型(会话、企业会话、交易或案件),item.id 为其 ID。以 _at 结尾的时间戳为 ISO 8601 字符串。与订阅其他事件一样,请在 subscribed_events 中列出确切的字符串来订阅这些事件。

用户实体状态变更 (user.status.updated)

重新提交的会话

旧版 X-Signature 与原始请求体

每次投递仍会发送 X-Signature。它是对 Didit 传输的完全一致的字节计算的 HMAC-SHA256(json.dumps(..., sort_keys=True, separators=(",", ":")))。仅当你能在任何中间件修改请求体之前读取原始请求体时才使用它。

旧版 V2 Webhook 格式

下列字段仅在 Webhook 目标固定为 webhook_version: "v2" 时适用。还存在更早的 "v1" 固定版本(第三种单数形式的决策结构),适用于 V2 之前创建的目标,依赖它之前请先联系支持团队。新集成应使用 V3(默认版本),其文档见上文,且使用复数数组。
两个版本中的按功能对象完全相同:V2 目标接收的单条命中的 match_score、risk_score、score_breakdown、risk_view 和 review_status,以及汇总的 score,与 V3 完全一致(参见 AML 报告)。固定为 V2 只会改变 AML 报告在 decision 中的位置,不会改变其包含的内容。 如果下游使用方仍需要 V2 结构,请创建一个单独的、固定为 webhook_version: "v2" 的目标,并让新的使用方继续使用 V3。

相关内容

  • Webhook 目标 API:列出、创建、更新、删除目标,并查看投递日志。
  • 创建 Webhook 目标:请求与响应结构,包括目标的 secret_shared_key。
  • 数据模型:嵌入 decision 中每个按功能对象的标准结构。
  • 决策结构:会话 Webhook 中嵌入的 decision 对象的完整字段列表。
  • 验证状态:上文提到的确切 status 值及其状态流转。
  • 速率限制:将轮询 GET /v3/session/{id}/decision/ 作为备用方案时适用的限制。
最后修改于 2026年11月7日