curl -X PATCH \
https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/features/feature_ocr_1/update-status/ \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"new_status": "Approved",
"comment": "Document manually verified by compliance."
}'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.sessions.update_feature_status(
"11111111-2222-3333-4444-555555555555",
"feature_ocr_1",
new_status="Approved",
comment="Document manually verified by compliance.",
)
print(result)import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.sessions.updateFeatureStatus(
"11111111-2222-3333-4444-555555555555",
"feature_ocr_1",
{
new_status: "Approved",
comment: "Document manually verified by compliance.",
},
);
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.Sessions.UpdateFeatureStatus(ctx, "11111111-2222-3333-4444-555555555555", "feature_ocr_1", didit.SessionsUpdateFeatureStatusParams{
NewStatus: "Approved",
Comment: didit.String("Document manually verified by compliance."),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import me.didit.Didit;
import me.didit.types.SessionsUpdateFeatureStatusParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.sessions().updateFeatureStatus("11111111-2222-3333-4444-555555555555", "feature_ocr_1", SessionsUpdateFeatureStatusParams.builder()
.newStatus(SessionsUpdateFeatureStatusParams.NewStatus.of("Approved"))
.comment("Document manually verified by compliance.")
.build());
System.out.println(result);<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->sessions->updateFeatureStatus('11111111-2222-3333-4444-555555555555', 'feature_ocr_1', [
'new_status' => 'Approved',
'comment' => 'Document manually verified by compliance.',
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.sessions.update_feature_status(
"11111111-2222-3333-4444-555555555555",
"feature_ocr_1",
new_status: "Approved",
comment: "Document manually verified by compliance."
)
puts result.to_husing System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.Sessions.UpdateFeatureStatusAsync("11111111-2222-3333-4444-555555555555", "feature_ocr_1", new SessionsUpdateFeatureStatusParams
{
NewStatus = "Approved",
Comment = "Document manually verified by compliance.",
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"node_id": "feature_ocr_1",
"feature_type": "KYC",
"new_status": "Approved",
"override": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"node_id": "feature_ocr_1",
"feature_type": "",
"feature_model": "KYC",
"previous_status": "In Review",
"new_status": "Approved",
"state": "applied",
"forced": false,
"reason": "Document manually verified by compliance.",
"requested_by": {
"email": "reviewer@example.com",
"name": "Alex Reviewer",
"type": "CONSOLE_USER"
},
"requested_at": "2026-10-13T09:15:00Z",
"applied_at": "2026-10-13T09:15:00Z",
"cancelled_at": null,
"cancel_reason": null
}
}更新功能状态 API:通过或拒绝单个验证步骤
Didit 允许你通过 API 将单个验证步骤(OCR、活体检测、人脸比对、AML、地址证明、电话验证等)设为已通过、已拒绝或转入人工审核,可立即生效,也可待用户完成流程后再设置。
curl -X PATCH \
https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/features/feature_ocr_1/update-status/ \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"new_status": "Approved",
"comment": "Document manually verified by compliance."
}'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.sessions.update_feature_status(
"11111111-2222-3333-4444-555555555555",
"feature_ocr_1",
new_status="Approved",
comment="Document manually verified by compliance.",
)
print(result)import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.sessions.updateFeatureStatus(
"11111111-2222-3333-4444-555555555555",
"feature_ocr_1",
{
new_status: "Approved",
comment: "Document manually verified by compliance.",
},
);
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.Sessions.UpdateFeatureStatus(ctx, "11111111-2222-3333-4444-555555555555", "feature_ocr_1", didit.SessionsUpdateFeatureStatusParams{
NewStatus: "Approved",
Comment: didit.String("Document manually verified by compliance."),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import me.didit.Didit;
import me.didit.types.SessionsUpdateFeatureStatusParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.sessions().updateFeatureStatus("11111111-2222-3333-4444-555555555555", "feature_ocr_1", SessionsUpdateFeatureStatusParams.builder()
.newStatus(SessionsUpdateFeatureStatusParams.NewStatus.of("Approved"))
.comment("Document manually verified by compliance.")
.build());
System.out.println(result);<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->sessions->updateFeatureStatus('11111111-2222-3333-4444-555555555555', 'feature_ocr_1', [
'new_status' => 'Approved',
'comment' => 'Document manually verified by compliance.',
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.sessions.update_feature_status(
"11111111-2222-3333-4444-555555555555",
"feature_ocr_1",
new_status: "Approved",
comment: "Document manually verified by compliance."
)
puts result.to_husing System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.Sessions.UpdateFeatureStatusAsync("11111111-2222-3333-4444-555555555555", "feature_ocr_1", new SessionsUpdateFeatureStatusParams
{
NewStatus = "Approved",
Comment = "Document manually verified by compliance.",
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"node_id": "feature_ocr_1",
"feature_type": "KYC",
"new_status": "Approved",
"override": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"node_id": "feature_ocr_1",
"feature_type": "",
"feature_model": "KYC",
"previous_status": "In Review",
"new_status": "Approved",
"state": "applied",
"forced": false,
"reason": "Document manually verified by compliance.",
"requested_by": {
"email": "reviewer@example.com",
"name": "Alex Reviewer",
"type": "CONSOLE_USER"
},
"requested_at": "2026-10-13T09:15:00Z",
"applied_at": "2026-10-13T09:15:00Z",
"cancelled_at": null,
"cancel_reason": null
}
}本接口的作用
一个验证会话由多个独立的功能(步骤)组成:ID/OCR、活体检测、人脸比对、AML、地址证明、电话等。 此接口可将其中一个步骤的状态设置为Approved、Declined 或 In Review。
若要批准、拒绝或重新开启整个会话,请使用 update-status。
若只想记录单个步骤的决定,例如在您自己的审核流程中将人脸比对步骤标记为 Declined,请使用本接口。
已有决定的会话会保留该决定,只有步骤会发生变化。
如果会话尚无决定,且其工作流正在等待这一步,应用覆盖后该步骤会完成,与正常完成该步骤的效果相同。
工作流随后继续运行,后续步骤执行,状态节点可以设置会话决策并触发 status.updated Webhook。
使用 node_id 指定步骤
在基于图的工作流中,每个步骤都有一个 node_id(例如 feature_ocr_1、feature_liveness_1、feature_aml_1)。您可以在会话决策中找到这些 ID,V3 版决策中的每个功能都带有其 node_id。
对于非图(单步骤)工作流,底层功能没有节点 ID。请将字面值 default 作为 nodeId 传入以指定该步骤。
由于此类工作流中没有任何步骤具有节点 ID,还需传入 feature_type(例如 LIVENESS、AML 或 FACE_MATCH)以说明您指的是哪个步骤。
无法识别的 feature_type 会返回 400。
等待用户完成流程
默认情况下,覆盖立即生效。 如果用户仍在完成流程,则会修改仍在运行的流程中的某个步骤,此时覆盖会记录为forced: true。
设置 defer_until_flow_finishes: true 可改为等待。
当会话处于 Not Started、In Progress 或 Resubmitted 状态且用户尚未完成流程时,覆盖会存储为 pending_until_flow_finishes。
它会在用户完成流程后、流程自身做出决定之后生效。
对于流程已经结束的会话,无论如何设置,覆盖都会立即生效。
等待中的覆盖在以下情况下会被取消,而不是生效:
- 用户在完成前重做该步骤(
check_changed), - 同一步骤上更新的覆盖取代了它(
replaced), - 会话在流程未完成时结束:已放弃、已过期或在流程中途已做出决定(
session_closed), - 您通过 取消功能覆盖 取消了它(
cancelled_by_reviewer)。
override 说明了结果:state 为 applied 或 pending_until_flow_finishes,生效后会设置 applied_at。
顶层的 new_status 是该步骤已存储的状态,因此在覆盖等待期间保持不变。
使用 列出功能覆盖 可查看某个会话的所有覆盖,以及用户是否仍在流程中。
KYC 与 KYB 支持
对用户验证(KYC)和企业验证(KYB)会话的处理方式完全相同,Didit 可在这两种会话中解析sessionId。支持的步骤类型包括 ID/OCR、活体检测、人脸比对、NFC、AML、地址证明、电话、邮箱、数据库核验、问卷,以及 KYB 的公司登记、证件和关键人员检查。
session_type = API)无法更改单个功能的状态,接口会返回 400。示例
- 批准一个步骤
- 拒绝人脸比对步骤
- 单步骤工作流(默认节点)
- 等待用户完成流程
curl -X PATCH https://verification.didit.me/v3/session/4c5c7f3a-.../features/feature_ocr_1/update-status/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"new_status": "Approved",
"comment": "Document manually verified by compliance"
}'
curl -X PATCH https://verification.didit.me/v3/session/4c5c7f3a-.../features/feature_face_match/update-status/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"new_status": "Declined"
}'
curl -X PATCH https://verification.didit.me/v3/session/4c5c7f3a-.../features/default/update-status/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"new_status": "In Review",
"feature_type": "LIVENESS"
}'
curl -X PATCH https://verification.didit.me/v3/session/4c5c7f3a-.../features/feature_liveness_1/update-status/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"new_status": "Approved",
"comment": "Liveness retried with a reviewer present",
"defer_until_flow_finishes": true
}'
更新后会发生什么
- Webhook:覆盖生效时(立即生效或流程结束时)会触发
data.updated事件。等待期间或取消时不发送任何内容。 - 活动:每次覆盖都会记录在会话的活动中,类型为
FEATURE_OVERRIDE_PENDING、FEATURE_OVERRIDE_APPLIED或FEATURE_OVERRIDE_CANCELLED,并附带操作者(API 密钥、用户,或等待中的覆盖生效时的系统)。请求对应的记录会将您的comment作为原因。在会话决策的reviews数组中,这些记录显示为new_status: null,请求对应的记录在comment中包含您填写的原因。 - 会话决策:已有决策的会话会保留该决策。若要更改最终决策,请单独调用 update-status。
权限
需要write:sessions 权限,可使用客户端 API 密钥(x-api-key)或用户授权请求头。
限定范围的 API 密钥需要具备决策的写入权限。
相关内容
- 更新会话状态:更改会话的整体决策。
- 更新 AML 命中状态:审核单个 AML 匹配结果。
- 获取会话:获取决策(及每个功能的
node_id)。 - Webhook:订阅
data.updated。 - 列出功能覆盖:查看会话的每项覆盖及其状态。
- 取消功能覆盖:阻止等待中的覆盖生效。
授权
您的应用 API 密钥,可在 Business Console 的“开发者 -> API 密钥”中获取。主密钥拥有完整访问权限。指定名称的密钥可设置作用域:针对每个资源设为无权限、只读或读写,限定于特定工作流或已通过的会话、限定于 IP 地址列表,以及设置到期日期。401 表示密钥错误、已撤销或已过期;403 表示未发送密钥、密钥无权访问该资源或操作,或请求来自其 IP 列表之外的地址;在会话路由上返回 404 表示该会话不在该密钥允许的工作流或状态范围内。没有媒体访问权限的密钥获取到的图片、视频和 PDF URL 将为 null;没有会话写入权限的密钥获取到的会话链接和 token 将为 null。请参阅 https://docs.didit.me/console/api-keys。
路径参数
验证会话的 UUID。支持用户(KYC)和企业(KYB)会话 ID,服务会跨两种会话类型解析该 ID。
"11111111-2222-3333-4444-555555555555"
要更新的功能的工作流图谱节点 ID(例如 feature_ocr_1)。对于功能没有节点 ID 的非图谱(单步骤)工作流,请使用字面值 default。
"feature_ocr_1"
请求体
此功能的目标状态。必须与当前值不同。
Approved, Declined, In Review "Approved"
可选的自由文本备注,记录在此功能变更的会话审核轨迹中。
"Document manually verified by compliance."
要定位哪种类型的步骤。非图谱工作流中需要提供(nodeId = default),此时所有步骤不共享节点;其他情况下可选。未知值将返回 400。
ID_VERIFICATION, OCR, OCR_BACK, NFC, LIVENESS, FACE, AGE_ESTIMATION, AGE_VERIFICATION, FACE_SEARCH, FACE_MATCH, IP_ANALYSIS, AML, PHONE, PHONE_VERIFICATION, EMAIL, EMAIL_VERIFICATION, POA, PROOF_OF_ADDRESS, DATABASE_VALIDATION, DATA_VALIDATION, QUESTIONNAIRE, DOCUMENT_AI, KYB_REGISTRY, KYB_DOCUMENTS, KYB_KEY_PEOPLE, BANK_VERIFICATION, GEOLOCATION "LIVENESS"
当当事人仍在流程中时,将覆盖项存储为 pending_until_flow_finishes 并在流程结束时应用,而不是立即生效。若省略或设为 false,覆盖项将立即生效。对于流程已结束的会话,无论哪种情况均会立即生效。
false
响应
覆盖已记录。new_status 是已存储的核验状态:覆盖生效后为请求的状态,等待流程完成期间为未更改的状态。override 说明了实际发生的情况。
已更新步骤的工作流节点;对于没有节点的步骤(非图谱工作流中的 default 路径),则为 null。
"feature_ocr_1"
已更新功能的模型名称(例如 KYC、Face、FaceMatch、AML、POA)。
"KYC"
该检查的已存储状态:覆盖生效后为所请求的状态,在覆盖等待流程完成期间为未更改的状态。
"Approved"
通过 PATCH /v3/session/{sessionId}/features/{nodeId}/update-status/ 对某项检查(功能)状态进行的一次覆盖:它更改了什么、是否已应用或仍在等待用户完成流程、发起者以及原因。
Show child attributes
Show child attributes