关于 didit-kyc-onboarding
用于通过 Didit 配置工作流、创建用户验证会话并获取审核结果的 KYC 接入技能,面向需要在注册流程中加入身份核验的开发者。
主要功能
- 01配置可复用的 KYC 工作流
- 02创建用户验证会话
- 03向用户提供验证 URL
- 04通过轮询或 Webhook 获取结果
- 05执行证件与自拍核验
适用场景
- 01在用户注册中加入身份验证
- 02向用户发送验证链接
- 03收集已完成核验的结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ didit-protocol/ skills --skill didit-kyc-onboarding安装后在 Claude Code 中输入/didit-kyc-onboarding确认已加载。
附带文件scripts/run_kyc.py
详细介绍
使用 Didit 进行 KYC
端到端的客户身份识别(KYC)验证。此技能会创建 KYC 工作流,生成一个会话 URL,供真实用户完成身份证件扫描 + 自拍 + 人脸匹配,并获取验证结果。
用户体验:
- 收到验证链接(或在你的应用中打开该链接)
- 扫描身份证件(护照、身份证、驾驶证、居留许可)
- 拍摄实时自拍照
- 将自拍照与证件照片进行匹配
- 获批、被拒或标记为待审核
**定价:**在一个工作流中,你只需为已完成的功能付费:身份证件验证(证件采集)$0.15、被动活体检测 $0.10、人脸匹配 $0.05;每个组织每月各有 500 次免费检查;主动活体检测(ACTIVE_3D 或 FLASHING)$0.15、NFC $0.15、AML 筛查 $0.20、电子邮件验证 $0.03、电话验证 $0.04 + 运营商费用。这些是截至 2026 年 11 月 1 日的标价,届时 Didit 将调整定价,每月 500 次免费检查将改为每月 $10 的免费额度。请查看 didit.me/pricing 了解当前价格。
API 参考:
- 工作流:https://docs.didit.me/management-api/workflows/create
- 工作流功能配置:https://docs.didit.me/management-api/workflows/feature-configs
- 会话:https://docs.didit.me/sessions-api/create-session
- 验证结果:https://docs.didit.me/sessions-api/retrieve-session
- 状态:https://docs.didit.me/integration/verification-statuses
- 程序化注册:https://docs.didit.me/integration/programmatic-registration
相关技能:didit-sdk-integration(将会话嵌入 Web 或移动应用,而不是发送链接)、didit-case-management(审核 In Review 会话的队列)、didit-verification-management(Webhook、用户、账单)。
身份验证
每个请求都需要 x-api-key 标头。使用你在 Didit Business Console 的 Developers > API keys 下找到的应用 API 密钥,或者通过程序化方式创建账户和密钥(参见“开始使用”)。具有自定义访问权限的命名密钥需要 Workflows 写入权限才能创建工作流,需要 Sessions 写入权限才能创建会话(否则 url 和 session_token 会返回 null),需要 Decisions 读取权限来获取结果,以及 Media 读取权限来获取图片 URL 和 PDF 报告。
开始使用(还没有账户?)
如果你没有 Didit API 密钥,只需通过 2 次 API 调用即可创建:
- **注册:**使用
{"email": "[email protected]", "password": "MyStr0ng!Pass"}调用POST https://apx.didit.me/auth/v2/programmatic/register/ - 检查电子邮件,获取 6 位验证码
- **验证:**使用
{"email": "[email protected]", "code": "A3K9F2"}调用POST https://apx.didit.me/auth/v2/programmatic/verify-email/。密钥位于响应的application.api_key中。
**添加额度:**调用 GET /v3/billing/balance/ 进行查询,调用 POST /v3/billing/top-up/ 并传入 {"amount_in_dollars": 50} 获取 Stripe 结账链接。
如需了解完整的平台管理功能(工作流、会话、用户、账单),请参阅 didit-verification-management 技能。
快速开始:通过 3 次 API 调用完成 KYC
import requests, time
API_KEY = "your_api_key"
headers = {"x-api-key": API_KEY, "Content-Type": "application/json"}
BASE = "https://verification.didit.me/v3"
TERMINAL = {"Approved", "Declined", "In Review", "Expired", "Kyc Expired", "Abandoned"}
# 1. Create a KYC workflow (one-time setup: reuse the workflow id for all users)
workflow = requests.post(f"{BASE}/workflows/", headers=headers, json={
"workflow_label": "KYC Onboarding",
"max_retry_attempts": 3,
"features": [
{"feature": "OCR"},
{"feature": "LIVENESS", "config": {"face_liveness_method": "PASSIVE"}},
{"feature": "FACE_MATCH", "config": {"face_match_score_decline_threshold": 50}},
],
}).json()
workflow_id = workflow["uuid"]
# 2. Create a session for a specific user
session = requests.post(f"{BASE}/session/", headers=headers, json={
"workflow_id": workflow_id,
"vendor_data": "user-abc-123",
"callback": "https://yourapp.com/verification-done",
"language": "en",
}).json()
print(f"Send user to: {session['url']}")
# User opens this URL, scans their ID, takes a selfie
# 3. Poll for the decision (or use webhooks)
while True:
decision = requests.get(
f"{BASE}/session/{session['session_id']}/decision/",
headers={"x-api-key": API_KEY},
).json()
status = decision["status"]
if status in TERMINAL:
break
time.sleep(15)
print(f"Result: {status}")
if status == "Approved":
id_data = decision["id_verifications"][0]
print(f"Name: {id_data['first_name']} {id_data['last_name']}")
print(f"DOB: {id_data['date_of_birth']}")
print(f"Document: {id_data['document_type']} ({id_data['issuing_state']})")
第 1 步:创建 KYC 工作流
工作流定义了要运行哪些检查。每种用例创建一个工作流,并供所有用户重复使用。每个应用最多可创建 50 个工作流;每次调用都会创建一个新工作流。
POST https://verification.didit.me/v3/workflows/
**API 参考:**https://docs.didit.me/management-api/workflows/create
请求正文
请求正文仅接受以下键;任何其他键(包括 workflow_type)都会返回 400。
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
features | array | 必填 | 按执行顺序排列的步骤:{"feature": "...", "config": {...}, "label": "..."} |
workflow_label | string | "ID Verification" | 显示名称,最多 50 个字符 |
max_retry_attempts | integer 0-10 | 3 | 拒绝后允许重试的次数;0 表示首次拒绝后即停止 |
retry_window_days | integer 1-365 or null | 7 | 计算重试次数的滚动时间窗口;null = 计算所有历史记录 |
session_expiration_time | integer 3600-2419200 | 604800(7 天) | 未完成的会话过期前的秒数 |
face_liveness_max_attempts | integer 1-3 | 3 | 每个会话的活体检测提交次数 |
face_match_max_attempts | integer 1-3 | 3 | 每个会话的人脸匹配提交次数 |
is_default | boolean | - | 将其设为应用程序的默认工作流 |
status | draft 或 published | published | 省略时立即发布 |
is_white_label_enabled | boolean | false | 应用你的白标自定义设置 |
is_desktop_allowed | boolean | false | 允许在桌面浏览器中运行此流程 |
KYC 功能及其主要配置
feature | 配置 | 备注 |
|---|---|---|
OCR | documents_allowed、methods、duplicated_user_action、年龄和风险操作 | 身份证件采集。将其放在第一步,以便后续步骤使用其数据 |
LIVENESS | face_liveness_method:PASSIVE、ACTIVE_3D(3D 动作和闪光)或 FLASHING(3D 闪光) | 主动方式按 Active Liveness 计费($0.15) |
FACE_MATCH | face_match_score_decline_threshold、face_match_score_review_threshold(0-100) | 必须位于 OCR 之后 |
NFC | allow_nfc_skip、skip_nfc_action、unverified_chip_action | 必须位于 OCR 之后;通过原生 iOS/Android SDK 读取芯片,在 Web 浏览器中会跳过 |
AML | aml_score_review_threshold、aml_score_approve_threshold | 需要在其前面配置 OCR |
PHONE_VERIFICATION、EMAIL_VERIFICATION | 参见功能配置 | 联系方式验证 |
配置中的操作可设为 DECLINE、REVIEW 或 NO_ACTION。其他功能(IP_ANALYSIS、PROOF_OF_ADDRESS、DATABASE_VALIDATION、QUESTIONNAIRE、AGE_ESTIMATION、DOCUMENT_AI)以及所有配置键,详见功能配置参考。
响应(201)
响应是完整的工作流配置(约 190 个字段)。主要字段:
{
"uuid": "c3d4e5f6-7890-12cd-ef34-333333333333",
"workflow_id": "c3d4e5f6-7890-12cd-ef34-333333333333",
"workflow_label": "KYC Onboarding",
"features": "OCR + LIVENESS + FACE_MATCH",
"total_price": 0.3,
"min_price": 0.3,
"max_price": 0.3,
"workflow_url": "https://verify.didit.me/u/w9TkPOx8RWG3UAz5ZRQGVQ",
"max_retry_attempts": 3,
"retry_window_days": 7,
"session_expiration_time": 604800,
"status": "published",
"version": 1
}
保存 uuid(与 workflow_id 的值相同)。features 是由 " + " 拼接而成的字符串;价格是以美元计的 JSON 数字(按你的费率计算已启用功能的总和)。
第 2 步:为每位用户创建会话
每位用户都会获得自己的会话,其中包含唯一的验证 URL。
POST https://verification.didit.me/v3/session/
API 参考: https://docs.didit.me/sessions-api/create-session
关键参数
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
workflow_id | uuid | 是 | 来自第 1 步 |
vendor_data | string | 建议填写 | 您的用户 ID:用于按用户分组会话并支持重复检测。同一工作流版本中,如果存在 vendor_data 相同的未完成会话,系统会返回该会话,而不是新建会话 |
callback | url | 建议填写 | 验证后重定向到的地址。Didit 会将 verificationSessionId 和 status 作为查询参数附加 |
callback_method | string | 否 | initiator、completer 或 both(跟随回调的设备) |
language | string | 否 | UI 语言(ISO 639-1)。省略时会自动检测 |
contact_details | object | 否 | email、send_notification_emails、email_lang、phone(E.164) |
expected_details | object | 否 | first_name、last_name、date_of_birth(YYYY-MM-DD)、gender、nationality、id_country、identification_number、expected_document_types 等。不匹配会添加 *_MISMATCH_WITH_PROVIDED 警告 |
metadata | any JSON | 否 | 与会话一同存储,并在响应和 Webhook 中回传。接受任意 JSON 值;建议使用对象 |
响应(201)
{
"session_id": "11111111-2222-3333-4444-555555555555",
"session_number": 43762,
"session_token": "3FaJ9wLqX2Mz",
"url": "https://verify.didit.me/session/3FaJ9wLqX2Mz",
"vendor_data": "user-abc-123",
"metadata": null,
"status": "Not Started",
"workflow_id": "c3d4e5f6-7890-12cd-ef34-333333333333",
"workflow_version": 1,
"callback": "https://yourapp.com/verification-done"
}
将用户发送到 url(网页或移动端),或使用 SDK 嵌入会话(didit-sdk-integration 技能)。请将 session_token 视为机密:持有该令牌的任何人都可以完成验证。
第 3 步:获取判定结果
GET https://verification.didit.me/v3/session/{sessionId}/decision/
API 参考: https://docs.didit.me/sessions-api/retrieve-session
获取就绪状态的两种方式
方式 A:Webhook(生产环境推荐)
在 Business Console(Webhooks)中添加目标地址,或使用 POST /v3/webhook/destinations/(label、url、webhook_version: "v3"、subscribed_events: ["status.updated"])。Didit 会发送包含 session_id、status 的签名 POST;当状态为 Approved、Declined、In Review 或 Abandoned 时,还会发送完整的 decision。请验证签名(参见 didit-verification-management),并确保处理程序根据 event_id 实现幂等。
方式 B:轮询
每隔 10 到 30 秒轮询一次 GET /v3/session/{sessionId}/decision/。遇到终态时停止:Approved、Declined、In Review、Expired、Kyc Expired 或 Abandoned。人工审核后,In Review 状态仍可能变化,因此请保留 Webhook。
判定响应字段
每个功能都有各自的数组,其中包含各自的 status、node_id 和 warnings。顶层没有 warnings 键。
{
"session_id": "11111111-2222-3333-4444-555555555555",
"session_number": 43762,
"status": "Approved",
"workflow_id": "c3d4e5f6-7890-12cd-ef34-333333333333",
"features": ["ID_VERIFICATION", "LIVENESS", "FACE_MATCH"],
"vendor_data": "user-abc-123",
"metadata": null,
"id_verifications": [{
"node_id": "ocr",
"verification_method": "document",
"status": "Approved",
"document_type": "Passport",
"document_number": "ABC123456",
"issuing_state": "USA",
"issuing_state_name": "United States",
"first_name": "Alex",
"last_name": "Sample",
"full_name": "Alex Sample",
"date_of_birth": "1990-01-15",
"age": 36,
"expiration_date": "2030-06-01",
"gender": "M",
"nationality": "USA",
"mrz": {"surname": "SAMPLE", "name": "ALEX", "document_type": "P", "document_number": "ABC123456", "birth_date": "900115", "expiry_date": "300601", "sex": "M"},
"portrait_image": "https://<media-host>/...",
"warnings": []
}],
"liveness_checks": [{
"node_id": "liveness",
"status": "Approved",
"method": "PASSIVE",
"score": 92.5,
"warnings": []
}],
"face_matches": [{
"node_id": "face_match",
"status": "Approved",
"score": 97.3,
"warnings": []
}],
"aml_screenings": [],
"created_at": "2026-05-17T10:30:00Z"
}
字段说明:
document_type是显示名称:Passport、Identity Card、Driver's License、Residence Permit等。issuing_state和nationality使用 ISO 3166-1 alpha-3。日期格式为YYYY-MM-DD;MRZ 日期为原始的YYMMDD。mrz是一个对象;未读取到 MRZ 时为null。- 功能状态(
Approved、Declined、In Review、Not Finished等)与会话status相互独立。 id_verifications中的verification_method为document、id_lookup或wallet。- 警告:
{feature, risk, additional_data, log_type, short_description, long_description, node_id}。请参阅 didit-id-document-verification 技能和 https://docs.didit.me/core-technology/id-verification/warnings-id-verification。
会话状态
| 状态 | 含义 | 操作 |
|---|---|---|
Not Started | 会话已创建,但尚未打开链接 | 等待或提醒用户 |
In Progress | 用户正在完成步骤 | 等待 |
Awaiting User | 企业(KYB)会话正在等待相关人员完成 KYC 会话 | 等待 |
Resubmitted | 已要求用户重新完成特定步骤 | 等待新结果 |
Approved | 所有检查均已通过 | 用户已验证 |
Declined | 一项或多项检查未通过 | 查看每项功能的 warnings |
In Review | 需要人工审核 | 在控制台中审核,或通过 API 决定(见下文) |
Expired | 会话在完成前已过期(默认为 7 天,session_expiration_time) | 创建新会话 |
Abandoned | 用户已开始,但未在规定时间内完成 | 创建新会话 |
Kyc Expired | 先前已批准的会话已超过其 KYC 过期政策规定的期限 | 重新验证用户 |
这些值是精确区分大小写的字符串(Kyc Expired 中只有 K 是大写)。
可选:决策后的操作
手动批准或拒绝
PATCH https://verification.didit.me/v3/session/{sessionId}/update-status/
API 参考: https://docs.didit.me/sessions-api/update-status
会话必须处于 Approved、Declined、In Review、Kyc Expired、Abandoned 或 Resubmitted 状态,且新状态必须与当前状态不同(否则返回 400)。
requests.patch(f"{BASE}/session/{session_id}/update-status/",
headers=headers,
json={"new_status": "Approved", "comment": "Manual review passed"})
要求重新提交
如果证件照片模糊,可要求用户仅重新完成该步骤。从决策中获取 node_id:通过此 API 创建的工作流使用 ocr、liveness、face_match 等 ID;通过控制台创建的工作流使用 feature_ocr 等 ID。
decision = requests.get(f"{BASE}/session/{session_id}/decision/", headers=headers).json()
ocr_node = decision["id_verifications"][0]["node_id"]
requests.patch(f"{BASE}/session/{session_id}/update-status/",
headers=headers,
json={
"new_status": "Resubmitted",
"nodes_to_resubmit": [{"node_id": ocr_node, "feature": "OCR"}],
"send_email": True,
"email_address": "[email protected]",
})
省略 nodes_to_resubmit,即可重新提交所有已尝试且状态为 Declined、In Review、Not Finished 或 Expired 的步骤(NFC 和 IP 分析不会自动选中)。这些步骤采集的数据将被删除,过期时间窗口将重新开始,原验证 URL 也将恢复可用。
屏蔽欺诈用户
通过 Lists API 将会话中的人脸或证件添加到系统屏蔽列表(每个应用针对每种条目类型都有一个屏蔽列表):
lists = requests.get(f"{BASE}/lists/", headers=headers,
params={"list_type": "blocklist", "entry_type": "face"}).json()
list_uuid = lists["results"][0]["uuid"]
requests.post(f"{BASE}/lists/{list_uuid}/entries/",
headers=headers,
json={"reference_session_id": session_id})
API 参考: https://docs.didit.me/management-api/lists/create-entry
生成 PDF 报告
适用于状态为 Approved、Declined、In Review 或 Kyc Expired 的会话。返回 application/pdf 字节数据。
response = requests.get(f"{BASE}/session/{session_id}/generate-pdf/",
headers={"x-api-key": API_KEY})
with open("report.pdf", "wb") as f:
f.write(response.content)
API 参考: https://docs.didit.me/sessions-api/generate-pdf
错误响应
| 代码 | 含义 | 操作 |
|---|---|---|
400 | 请求无效 | 查看响应正文中的字段错误 |
401 | API 密钥已过期 | 轮换密钥,或在 Developers > API keys 中创建新密钥 |
403 | API 密钥缺失、错误或已撤销;受限密钥无权访问此端点;请求来自密钥 IP 允许列表之外;或额度不足 | 查看 detail 或 error 中的消息:修复 x-api-key 请求头或密钥权限,或充值 |
404 | 未找到会话(或该会话不属于受限密钥的工作流) | 检查 sessionId |
429 | 超出速率限制:每个密钥每分钟 300 个 POST/PATCH/DELETE 请求和 600 个 GET 请求 | 等待 Retry-After 指定的秒数,然后重试 |
KYC 工作流变体
KYC + AML 筛查
requests.post(f"{BASE}/workflows/", headers=headers, json={
"workflow_label": "KYC + AML",
"features": [
{"feature": "OCR"},
{"feature": "LIVENESS", "config": {"face_liveness_method": "PASSIVE"}},
{"feature": "FACE_MATCH"},
{"feature": "AML"},
],
})
KYC + 电话 + 电子邮件
requests.post(f"{BASE}/workflows/", headers=headers, json={
"workflow_label": "KYC + Contact",
"features": [
{"feature": "OCR"},
{"feature": "LIVENESS", "config": {"face_liveness_method": "PASSIVE"}},
{"feature": "FACE_MATCH"},
{"feature": "PHONE_VERIFICATION"},
{"feature": "EMAIL_VERIFICATION"},
],
})
KYC + NFC(芯片读取)
为带芯片的护照和电子身份证提供最高级别的保障。需要使用原生 iOS/Android SDK;网页流程会跳过 NFC。
requests.post(f"{BASE}/workflows/", headers=headers, json={
"workflow_label": "KYC + NFC",
"features": [
{"feature": "OCR"},
{"feature": "NFC"},
{"feature": "LIVENESS", "config": {"face_liveness_method": "PASSIVE"}},
{"feature": "FACE_MATCH"},
],
})
更严格的活体检测和会话设置
requests.post(f"{BASE}/workflows/", headers=headers, json={
"workflow_label": "KYC High Assurance",
"max_retry_attempts": 1,
"retry_window_days": 30,
"session_expiration_time": 86400,
"face_liveness_max_attempts": 2,
"features": [
{"feature": "OCR"},
{"feature": "LIVENESS", "config": {"face_liveness_method": "FLASHING"}},
{"feature": "FACE_MATCH", "config": {"face_match_score_decline_threshold": 60}},
],
})
各国家的非文档查询与数字 ID 钱包
OCR 功能的 config.methods 按 ISO 3166-1 alpha-3 国家代码选择用户可使用的 ID Verification 方法:文档采集、查询政府登记册或其他权威来源(用户输入其国家 ID 号码),以及数字 ID 钱包。未指定的国家仍仅支持文档采集。每种方法和钱包都必须在该国家的能力目录(控制台 Countries 标签页)中标记为可用,否则整个保存操作都会被拒绝。
requests.post(f"{BASE}/workflows/", headers=headers, json={
"workflow_label": "KYC with lookup",
"features": [
{"feature": "OCR", "config": {"methods": {
"ZAF": {
"document": {"enabled": True},
"id_lookup": {"enabled": True, "max_attempts": 2,
"on_no_match": "fallback_to_document"},
},
}}},
{"feature": "LIVENESS", "config": {"face_liveness_method": "PASSIVE"}},
{"feature": "FACE_MATCH"},
],
})
| 键 | 默认值 | 取值 |
|---|---|---|
<ISO3>.document.enabled | true | 接受拍摄的文档 |
<ISO3>.id_lookup.enabled | false | 提供查询选项 |
<ISO3>.id_lookup.max_attempts | 1 | 已回答查询次数,范围为 1 到 5 |
<ISO3>.id_lookup.skip_liveness_and_face_match | true | 若来源返回了肖像且肖像与自拍照匹配,则跳过后续活体检测/人脸匹配 |
<ISO3>.id_lookup.on_partial_match / on_no_match / on_provider_error | fallback_to_document | 或 decline |
<ISO3>.wallet.enabled | false | 提供钱包登录选项 |
<ISO3>.wallet.providers | [] | 该国家接受的目录钱包 ID,例如 ["mitid"](接受列表,不是排序列表) |
<ISO3>.wallet.on_failure | fallback_to_document | 或 decline |
查询按国家计费,钱包按完成的验证次数计费,不包含在 500 次免费文档检查中。请参阅 https://docs.didit.me/core-technology/id-verification/non-doc-lookup 和 https://docs.didit.me/core-technology/id-verification/digital-id-wallets。
实用脚本
run_kyc.py:通过命令行完成完整的 KYC 设置
# Requires: pip install requests
export DIDIT_API_KEY="your_api_key"
# Create a KYC workflow (one-time)
python scripts/run_kyc.py setup --label "My KYC" --liveness --face-match
python scripts/run_kyc.py setup --label "KYC + AML" --aml --liveness-method FLASHING
# Create a session for a user
python scripts/run_kyc.py session --workflow-id <uuid> --vendor-data user-123
# Get the decision (or poll until a terminal status)
python scripts/run_kyc.py decision <session_id>
python scripts/run_kyc.py decision <session_id> --poll --interval 15
# Full flow: create workflow + session in one command
python scripts/run_kyc.py full --vendor-data user-123 --callback https://myapp.com/done
也可以将其导入:
from scripts.run_kyc import setup_kyc_workflow, create_kyc_session, get_decision, poll_decision