curl -X POST 'https://verification.didit.me/v3/session/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"workflow_id": "11111111-2222-3333-4444-555555555555",
"vendor_data": "user-123",
"callback": "https://example.com/verification/callback",
"callback_method": "both",
"metadata": {"user_type": "premium", "account_id": "ABC123"},
"language": "en",
"contact_details": {
"email": "john.doe@example.com",
"send_notification_emails": true,
"email_lang": "en",
"phone": "+14155552671"
},
"expected_details": {
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15",
"id_country": "USA",
"expected_document_types": ["P", "ID"]
}
}'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.sessions.create(
workflow_id="11111111-2222-3333-4444-555555555555",
vendor_data="user-123",
callback="https://example.com/verification/callback",
callback_method="both",
metadata={"user_type": "premium", "account_id": "ABC123"},
language="en",
contact_details={
"email": "john.doe@example.com",
"send_notification_emails": True,
"email_lang": "en",
"phone": "+14155552671",
},
expected_details={
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15",
"nationality": "USA",
"id_country": "USA",
"expected_document_types": ["P", "ID"],
},
)
print(result)import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.sessions.create({
workflow_id: "11111111-2222-3333-4444-555555555555",
vendor_data: "user-123",
callback: "https://example.com/verification/callback",
callback_method: "both",
metadata: { user_type: "premium", account_id: "ABC123" },
language: "en",
contact_details: {
email: "john.doe@example.com",
send_notification_emails: true,
email_lang: "en",
phone: "+14155552671",
},
expected_details: {
first_name: "John",
last_name: "Doe",
date_of_birth: "1990-05-15",
nationality: "USA",
id_country: "USA",
expected_document_types: ["P", "ID"],
},
});
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.Sessions.Create(ctx, didit.SessionsCreateParams{
WorkflowID: "11111111-2222-3333-4444-555555555555",
VendorData: didit.String("user-123"),
Callback: didit.String("https://example.com/verification/callback"),
CallbackMethod: didit.Some(didit.SessionsCreateParamsCallbackMethod("both")),
Metadata: didit.Some[any](map[string]any{"user_type": "premium", "account_id": "ABC123"}),
Language: didit.Some(didit.SessionsCreateParamsLanguage("en")),
ContactDetails: didit.Some(didit.SessionsCreateParamsContactDetails{
Email: didit.String("john.doe@example.com"),
SendNotificationEmails: didit.Bool(true),
EmailLang: didit.Some(didit.SessionsCreateParamsContactDetailsEmailLang("en")),
Phone: didit.String("+14155552671"),
}),
ExpectedDetails: didit.Some(didit.SessionsCreateParamsExpectedDetails{
FirstName: didit.String("John"),
LastName: didit.String("Doe"),
DateOfBirth: didit.String("1990-05-15"),
Nationality: didit.String("USA"),
IDCountry: didit.String("USA"),
ExpectedDocumentTypes: didit.Some([]didit.SessionsCreateParamsExpectedDetailsExpectedDocumentTypes{"P", "ID"}),
}),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import me.didit.Didit;
import me.didit.types.SessionsCreateParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.sessions().create(SessionsCreateParams.builder()
.workflowId("11111111-2222-3333-4444-555555555555")
.vendorData("user-123")
.callback("https://example.com/verification/callback")
.callbackMethod(SessionsCreateParams.CallbackMethod.of("both"))
.metadata(Map.of("user_type", "premium", "account_id", "ABC123"))
.language(SessionsCreateParams.Language.of("en"))
.contactDetails(SessionsCreateParams.ContactDetails.builder()
.email("john.doe@example.com")
.sendNotificationEmails(true)
.emailLang(SessionsCreateParams.ContactDetails.EmailLang.of("en"))
.phone("+14155552671")
.build())
.expectedDetails(SessionsCreateParams.ExpectedDetails.builder()
.firstName("John")
.lastName("Doe")
.dateOfBirth(LocalDate.parse("1990-05-15"))
.nationality("USA")
.idCountry("USA")
.expectedDocumentTypes(List.of(SessionsCreateParams.ExpectedDetails.ExpectedDocumentTypes.of("P"), SessionsCreateParams.ExpectedDetails.ExpectedDocumentTypes.of("ID")))
.build())
.build());
System.out.println(result);<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->sessions->create([
'workflow_id' => '11111111-2222-3333-4444-555555555555',
'vendor_data' => 'user-123',
'callback' => 'https://example.com/verification/callback',
'callback_method' => 'both',
'metadata' => ['user_type' => 'premium', 'account_id' => 'ABC123'],
'language' => 'en',
'contact_details' => [
'email' => 'john.doe@example.com',
'send_notification_emails' => true,
'email_lang' => 'en',
'phone' => '+14155552671',
],
'expected_details' => [
'first_name' => 'John',
'last_name' => 'Doe',
'date_of_birth' => '1990-05-15',
'nationality' => 'USA',
'id_country' => 'USA',
'expected_document_types' => ['P', 'ID'],
],
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.sessions.create(
workflow_id: "11111111-2222-3333-4444-555555555555",
vendor_data: "user-123",
callback: "https://example.com/verification/callback",
callback_method: "both",
metadata: { user_type: "premium", account_id: "ABC123" },
language: "en",
contact_details: {
email: "john.doe@example.com",
send_notification_emails: true,
email_lang: "en",
phone: "+14155552671",
},
expected_details: {
first_name: "John",
last_name: "Doe",
date_of_birth: "1990-05-15",
nationality: "USA",
id_country: "USA",
expected_document_types: ["P", "ID"],
}
)
puts result.to_husing System;
using System.Collections.Generic;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.Sessions.CreateAsync(new SessionsCreateParams
{
WorkflowId = "11111111-2222-3333-4444-555555555555",
VendorData = "user-123",
Callback = "https://example.com/verification/callback",
CallbackMethod = new SessionsCreateParamsCallbackMethod("both"),
Metadata = new Dictionary<string, object> { ["user_type"] = "premium", ["account_id"] = "ABC123" },
Language = new SessionsCreateParamsLanguage("en"),
ContactDetails = new SessionsCreateParamsContactDetails
{
Email = "john.doe@example.com",
SendNotificationEmails = true,
EmailLang = new SessionsCreateParamsContactDetailsEmailLang("en"),
Phone = "+14155552671",
},
ExpectedDetails = new SessionsCreateParamsExpectedDetails
{
FirstName = "John",
LastName = "Doe",
DateOfBirth = "1990-05-15",
Nationality = "USA",
IdCountry = "USA",
ExpectedDocumentTypes = new SessionsCreateParamsExpectedDetailsExpectedDocumentTypes[] { "P", "ID" },
},
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"session_id": "11111111-2222-3333-4444-555555555555",
"session_number": 43762,
"session_token": "3FaJ9wLqX2Mz",
"url": "https://verify.didit.me/en/session/3FaJ9wLqX2Mz",
"vendor_data": "user-123",
"metadata": {
"user_type": "premium",
"account_id": "ABC123"
},
"status": "Not Started",
"workflow_id": "11111111-2222-3333-4444-555555555555",
"workflow_version": 3,
"callback": "https://example.com/verification/callback"
}创建会话 API:启动 KYC 或 KYB 验证
Didit 的 POST /v3/session/ 端点可启动验证会话,统一支持 KYC 与 KYB,按量计费,推理耗时低于 2 秒,每月赠送 $10 免费额度。
curl -X POST 'https://verification.didit.me/v3/session/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"workflow_id": "11111111-2222-3333-4444-555555555555",
"vendor_data": "user-123",
"callback": "https://example.com/verification/callback",
"callback_method": "both",
"metadata": {"user_type": "premium", "account_id": "ABC123"},
"language": "en",
"contact_details": {
"email": "john.doe@example.com",
"send_notification_emails": true,
"email_lang": "en",
"phone": "+14155552671"
},
"expected_details": {
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15",
"id_country": "USA",
"expected_document_types": ["P", "ID"]
}
}'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.sessions.create(
workflow_id="11111111-2222-3333-4444-555555555555",
vendor_data="user-123",
callback="https://example.com/verification/callback",
callback_method="both",
metadata={"user_type": "premium", "account_id": "ABC123"},
language="en",
contact_details={
"email": "john.doe@example.com",
"send_notification_emails": True,
"email_lang": "en",
"phone": "+14155552671",
},
expected_details={
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15",
"nationality": "USA",
"id_country": "USA",
"expected_document_types": ["P", "ID"],
},
)
print(result)import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.sessions.create({
workflow_id: "11111111-2222-3333-4444-555555555555",
vendor_data: "user-123",
callback: "https://example.com/verification/callback",
callback_method: "both",
metadata: { user_type: "premium", account_id: "ABC123" },
language: "en",
contact_details: {
email: "john.doe@example.com",
send_notification_emails: true,
email_lang: "en",
phone: "+14155552671",
},
expected_details: {
first_name: "John",
last_name: "Doe",
date_of_birth: "1990-05-15",
nationality: "USA",
id_country: "USA",
expected_document_types: ["P", "ID"],
},
});
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.Sessions.Create(ctx, didit.SessionsCreateParams{
WorkflowID: "11111111-2222-3333-4444-555555555555",
VendorData: didit.String("user-123"),
Callback: didit.String("https://example.com/verification/callback"),
CallbackMethod: didit.Some(didit.SessionsCreateParamsCallbackMethod("both")),
Metadata: didit.Some[any](map[string]any{"user_type": "premium", "account_id": "ABC123"}),
Language: didit.Some(didit.SessionsCreateParamsLanguage("en")),
ContactDetails: didit.Some(didit.SessionsCreateParamsContactDetails{
Email: didit.String("john.doe@example.com"),
SendNotificationEmails: didit.Bool(true),
EmailLang: didit.Some(didit.SessionsCreateParamsContactDetailsEmailLang("en")),
Phone: didit.String("+14155552671"),
}),
ExpectedDetails: didit.Some(didit.SessionsCreateParamsExpectedDetails{
FirstName: didit.String("John"),
LastName: didit.String("Doe"),
DateOfBirth: didit.String("1990-05-15"),
Nationality: didit.String("USA"),
IDCountry: didit.String("USA"),
ExpectedDocumentTypes: didit.Some([]didit.SessionsCreateParamsExpectedDetailsExpectedDocumentTypes{"P", "ID"}),
}),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import me.didit.Didit;
import me.didit.types.SessionsCreateParams;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.sessions().create(SessionsCreateParams.builder()
.workflowId("11111111-2222-3333-4444-555555555555")
.vendorData("user-123")
.callback("https://example.com/verification/callback")
.callbackMethod(SessionsCreateParams.CallbackMethod.of("both"))
.metadata(Map.of("user_type", "premium", "account_id", "ABC123"))
.language(SessionsCreateParams.Language.of("en"))
.contactDetails(SessionsCreateParams.ContactDetails.builder()
.email("john.doe@example.com")
.sendNotificationEmails(true)
.emailLang(SessionsCreateParams.ContactDetails.EmailLang.of("en"))
.phone("+14155552671")
.build())
.expectedDetails(SessionsCreateParams.ExpectedDetails.builder()
.firstName("John")
.lastName("Doe")
.dateOfBirth(LocalDate.parse("1990-05-15"))
.nationality("USA")
.idCountry("USA")
.expectedDocumentTypes(List.of(SessionsCreateParams.ExpectedDetails.ExpectedDocumentTypes.of("P"), SessionsCreateParams.ExpectedDetails.ExpectedDocumentTypes.of("ID")))
.build())
.build());
System.out.println(result);<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->sessions->create([
'workflow_id' => '11111111-2222-3333-4444-555555555555',
'vendor_data' => 'user-123',
'callback' => 'https://example.com/verification/callback',
'callback_method' => 'both',
'metadata' => ['user_type' => 'premium', 'account_id' => 'ABC123'],
'language' => 'en',
'contact_details' => [
'email' => 'john.doe@example.com',
'send_notification_emails' => true,
'email_lang' => 'en',
'phone' => '+14155552671',
],
'expected_details' => [
'first_name' => 'John',
'last_name' => 'Doe',
'date_of_birth' => '1990-05-15',
'nationality' => 'USA',
'id_country' => 'USA',
'expected_document_types' => ['P', 'ID'],
],
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.sessions.create(
workflow_id: "11111111-2222-3333-4444-555555555555",
vendor_data: "user-123",
callback: "https://example.com/verification/callback",
callback_method: "both",
metadata: { user_type: "premium", account_id: "ABC123" },
language: "en",
contact_details: {
email: "john.doe@example.com",
send_notification_emails: true,
email_lang: "en",
phone: "+14155552671",
},
expected_details: {
first_name: "John",
last_name: "Doe",
date_of_birth: "1990-05-15",
nationality: "USA",
id_country: "USA",
expected_document_types: ["P", "ID"],
}
)
puts result.to_husing System;
using System.Collections.Generic;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.Sessions.CreateAsync(new SessionsCreateParams
{
WorkflowId = "11111111-2222-3333-4444-555555555555",
VendorData = "user-123",
Callback = "https://example.com/verification/callback",
CallbackMethod = new SessionsCreateParamsCallbackMethod("both"),
Metadata = new Dictionary<string, object> { ["user_type"] = "premium", ["account_id"] = "ABC123" },
Language = new SessionsCreateParamsLanguage("en"),
ContactDetails = new SessionsCreateParamsContactDetails
{
Email = "john.doe@example.com",
SendNotificationEmails = true,
EmailLang = new SessionsCreateParamsContactDetailsEmailLang("en"),
Phone = "+14155552671",
},
ExpectedDetails = new SessionsCreateParamsExpectedDetails
{
FirstName = "John",
LastName = "Doe",
DateOfBirth = "1990-05-15",
Nationality = "USA",
IdCountry = "USA",
ExpectedDocumentTypes = new SessionsCreateParamsExpectedDetailsExpectedDocumentTypes[] { "P", "ID" },
},
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"session_id": "11111111-2222-3333-4444-555555555555",
"session_number": 43762,
"session_token": "3FaJ9wLqX2Mz",
"url": "https://verify.didit.me/en/session/3FaJ9wLqX2Mz",
"vendor_data": "user-123",
"metadata": {
"user_type": "premium",
"account_id": "ABC123"
},
"status": "Not Started",
"workflow_id": "11111111-2222-3333-4444-555555555555",
"workflow_version": 3,
"callback": "https://example.com/verification/callback"
}KYC 与 KYB 支持
同一个 endpoint 既可以创建用户验证会话,也可以创建企业验证会话。工作流的类型决定会话种类:- 传入 KYC 工作流的
workflow_id,将创建用户验证(KYC)会话。响应中的session_kind: "user"。 - 传入 KYB 工作流的
workflow_id,将创建企业验证(KYB)会话。响应中的session_kind: "business"。
示例
- 用户验证(KYC)
- 企业验证(KYB)
curl -X POST https://verification.didit.me/v3/session/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "YOUR_KYC_WORKFLOW_ID",
"vendor_data": "user-42",
"callback": "https://yourapp.com/callback"
}'
{
"session_id": "4c5c7f3a-1f82-4f3b-8d8e-1a8d2d2f9b7a",
"session_kind": "user",
"session_number": 1024,
"session_token": "...",
"url": "https://verify.didit.me/session/...",
"status": "Not Started",
"workflow_id": "YOUR_KYC_WORKFLOW_ID",
"vendor_data": "user-42"
}
curl -X POST https://verification.didit.me/v3/session/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "YOUR_KYB_WORKFLOW_ID",
"vendor_data": "biz-acme-001",
"callback": "https://yourapp.com/callback"
}'
{
"session_id": "bs-01HJX1...",
"session_kind": "business",
"session_number": 89,
"session_token": "...",
"url": "https://verify.didit.me/session/...",
"status": "Not Started",
"workflow_id": "YOUR_KYB_WORKFLOW_ID",
"vendor_data": "biz-acme-001"
}
电子签名文档
当工作流包含从会话获取文档的电子签名步骤(即signature_documents_source 设为 session 或 both)时,请在 sign.documents 中发送这些文档。每个文档均为 base64 编码的文件,因此 Didit 无需再从 URL 获取文件。
{
"workflow_id": "YOUR_WORKFLOW_ID",
"vendor_data": "user-42",
"sign": {
"documents": [
{
"title": "Loan agreement",
"file_name": "loan-agreement.pdf",
"content_base64": "JVBERi0xLjcKJc...",
"fields": [
{ "key": "borrower_signature", "type": "signature", "label": "Borrower signature", "page": 3, "x": 0.1, "y": 0.78, "width": 0.32, "height": 0.06 },
{ "key": "date_signed", "type": "date_signed", "label": "Date", "page": 3, "x": 0.6, "y": 0.8, "width": 0.2, "height": 0.03, "date_format": "DD/MM/YYYY" },
{ "key": "loan_amount", "type": "data", "label": "Loan amount", "page": 1, "x": 0.34, "y": 0.31, "width": 0.3, "height": 0.03, "prefill": "api.loan_amount" },
{ "key": "initials", "type": "initials", "anchor": { "text": "[[initials]]", "occurrence": "all", "offset_x": 0, "offset_y": -0.005, "width": 0.12, "height": 0.04 } }
]
}
],
"field_values": { "loan_amount": "12,000 EUR" }
}
}
| 字段 | 规则 |
|---|---|
title | 向签署人显示。1 至 255 个字符。默认为 file_name。 |
file_name | 必填。以 .pdf 或 .docx 结尾。1 至 255 个字符。 |
content_base64 | 必填。PDF 最多 20 MB、100 页,不得有密码、脚本或附件。Word 文件最多 20 MB,请求执行期间会转换为 PDF,转换时间最多 25 秒;转换后的 PDF 受相同限制。每个会话最多 5 个 Word 文件。 |
fields | 可选。最多 200 个字段,放置在文档上,采用不含 id 的字段结构。每个字段需要 key 和 type,并且需指定位置(page、x、y、width 和 height)或 anchor。role 默认为该步骤的签署人,required 和 label 根据类型取默认值。Didit 会根据字段所在位置设置 position。页码和位置指的是 PDF;对于 Word 文件,指的是转换后的 PDF。 |
fields,签署人只需阅读文档并表示同意。
按锚点文本放置字段
字段可以不使用位置,而是带有anchor:即文档中标记字段放置位置的一段文本。锚点适用于为每个会话生成的文档,例如基于 Word 模板生成的文档。对于工作流文档,请在控制台中放置字段。
anchor 属性 | 规则 |
|---|---|
text | 1 至 64 个字符,在文档的文本中搜索。对于 Word 文件,在转换后的 PDF 中搜索。 |
occurrence | first(默认)仅在第一处匹配处放置一个字段。all 在每处匹配处各放置一个字段,第一个之后的字段 key 依次加上 _2、_3 等后缀。 |
offset_x、offset_y | 页面的比例值。字段的左上角为锚点文本左上角加上这些偏移量。 |
width、height | 字段的尺寸,为页面的比例值。 |
400 以及 field_anchor_not_found 和该字段的 key。Didit 不会从 PDF 中删除锚点文本,因此请将其设置为与页面背景相同的颜色。
字段值
sign.field_values 用于设置所有 prefill 为 api.<key> 的字段的值,适用于工作流文档和会话文档。它是一个以这些 <key> 名称为键的对象。text 和 data 字段的值为 1 至 500 个字符的字符串,checkbox 字段的值为布尔值。
{
"workflow_id": "YOUR_WORKFLOW_ID",
"vendor_data": "user-42",
"sign": {
"field_values": { "credit_limit": "3,000 EUR", "monthly_fee": "4.90 EUR" }
}
}
错误(400) | 触发条件 |
|---|---|
field_value_unknown | 提供的 key 不属于任何字段。 |
field_value_missing | 必填字段的 api.<key> 没有提供值。 |
field_value_invalid | 值未通过其字段的校验。 |
错误与重复调用
一个会话最多包含 20 个文档,总大小不超过 50 MB。在以下情况下,调用将返回400 以及 sign 错误:
- 工作流不包含电子签名步骤。
- 您发送了
sign.documents,但该步骤只接受工作流文档。 - 该步骤只接受会话文档,而您未发送任何文档;或该步骤没有工作流文档,且您也未发送任何文档。
- 某个文档过大、不是有效的 base64,或不是受支持的文件类型。
- Word 文件被
signature_document_not_supported拒绝,或无法转换并返回signature_document_conversion_failed,两者均附带支持的文件中列出的reason。 - 某个字段无效,其锚点未找到(
field_anchor_not_found),或字段值被拒绝。
workflow_id 和 vendor_data 再次调用创建接口,将返回待处理的会话。如果该调用包含 sign,其文档、字段和字段值必须与第一次完全一致(顺序、标题、文件名、内容、字段和值均相同)。任何不同之处都会返回 400 以及 {"sign": "signature_document_changed"}:请使用其他 vendor_data,或等待待处理的会话完成。
沙盒场景测试
在沙盒模式的应用中,传入sandbox_scenario 可以预设确定的结果(通过、特定的拒绝结果,或审核中场景),且不会调用真实服务商,也不会消耗您的余额:
{
"workflow_id": "YOUR_SANDBOX_WORKFLOW_ID",
"sandbox_scenario": "decline_document_expired"
}
sandbox_scenario 会被拒绝,返回 400。如果创建时尚不确定结果,可以在会话仍处于 Not Started 状态时,稍后通过 POST /v3/session/{session_id}/sandbox/arm/ 设置(或重新设置)场景。托管流程中的预流程场景选择器也使用同一个端点。完整的场景目录、魔法值注册表以及 arm endpoint 的请求和响应结构,请参阅沙盒与测试数据。
vendor_data 将会话绑定到实体
更多信息请参阅供应商数据关联。
伊利诺伊州、得克萨斯州和科罗拉多州的生物识别同意
托管流程以及 4.10.0 或更高版本的原生 SDK 可以在首次人脸采集之前显示明确的生物识别同意步骤,具体取决于应用的同意模式以及用户所在位置。以下两个可选字段会影响该判断:user_state:用户居住的地区(如果您知道)。可填写US-IL、IL或Illinois。在自动模式下,如果用户位于涵盖的州,流程会请求同意。biometric_consent:包含given_at和text_version的对象,用于记录您已收集的同意。流程不会再次请求同意。
重要提示:披露与同意仍需在您的产品中完成
Create Session 会生成验证 URL 和会话令牌。它本身并不能证明您已向用户展示了披露信息,或已获得您具体使用场景所需的同意。
如果您从自己的应用、网站、SDK 封装或白标流程发起 Didit 会话,应当在用户开始采集之前,先在自己的用户体验中处理法律层面的事项。
建议的验证前检查清单
- 告知用户您的公司正在请求进行验证,并且 Didit 是为该流程提供支持的验证服务提供商/处理者。
- 链接到您的隐私声明以及适用于该流程的数据控制者一方适用的法律条款。
- 链接到 Didit 的验证隐私声明和身份验证最终用户条款。
- 如果您的流程包括证件采集、自拍采集、活体检测或生物识别,在适用法律或您的法律立场要求的情况下,收集明确的肯定性同意。
- 如果您使用自定义 UI、自定义域名或仅 API 的流程,请在将用户引导至 Didit 流程之前,先在您自己的产品中展示这些披露信息。
- 如果您的法务团队要求审计追踪,请保留您自己的通知或同意文本、时间戳及相关元数据记录。
授权
您的应用 API 密钥,可在 Business Console 的“开发者 -> API 密钥”中获取。主密钥拥有完整访问权限。指定名称的密钥可设置作用域:针对每个资源设为无权限、只读或读写,限定于特定工作流或已通过的会话、限定于 IP 地址列表,以及设置到期日期。401 表示密钥错误、已撤销或已过期;403 表示未发送密钥、密钥无权访问该资源或操作,或请求来自其 IP 列表之外的地址;在会话路由上返回 404 表示该会话不在该密钥允许的工作流或状态范围内。没有媒体访问权限的密钥获取到的图片、视频和 PDF URL 将为 null;没有会话写入权限的密钥获取到的会话链接和 token 将为 null。请参阅 https://docs.didit.me/console/api-keys。
请求体
正在接受验证的用户的唯一标识符,例如 UUID、邮箱或内部用户 ID。此字段用于:(1) 用户分组:具有相同 vendor_data 的会话将关联到“用户”选项卡中的同一个用户资料。(2) 跨会话重复检测:在检查重复的人脸、证件、电话号码、邮箱、IP 地址或设备指纹时,具有相同 vendor_data 的会话将被视为同一用户并从匹配项中排除。若不提供 vendor_data,每个会话都将被视为独立用户,且所有潜在重复项都会被显示。我们强烈建议始终提供 vendor_data,以减少重复检测中的干扰。
"user-123"
您组织内部可选的重复检测领域(realm)。重复人脸检查仅会将当前会话与带有相同 segment 的其他会话进行比对,因此独立的账户体系(个人账户和企业账户,或每个 B2B 子客户对应一个账户体系)不会将合法在两边各持有一个账户的用户误标记。省略此项将使用单一的默认领域,这也是目前所有会话所使用的模式。黑名单和白名单匹配会忽略此字段。
64"business-accounts"
验证完成后重定向用户的 URL。Didit 会自动将 verificationSessionId 和 status(Approved、Declined、In Review)作为查询参数附加。支持自定义 URL 方案(例如 myapp://)用于移动端回调。如果省略,将使用工作流的默认 callback_url。当应用配置了允许的域名(PATCH /v3/webhook/ 上的 allowed_domains)时,http 或 https 回调必须位于这些源之一上(相同的方案、主机和端口),否则请求将在 callback 上失败并返回 400:callback must be on one of the application's allowed domains: https://app.example.com。自定义 URL 方案始终会被接受。
"https://example.com/verification/callback"
决定哪个设备应处理重定向到提供的回调 URL。使用 initiator 仅重定向启动流程的设备,使用 completer 重定向完成流程的设备,或使用 both 允许任一设备触发回调。如果您发现回调无法可靠触发,我们建议将此值设置为 both。
initiator, completer, both "both"
随会话一起存储并在响应和 Webhook 中原样回显的任意 JSON。接受任何 JSON 值(对象、字符串、数字、数组),但建议使用键/值对形式的 JSON 对象。不对终端用户显示。可用于传递您自己的关联 ID、A/B 测试变体或业务上下文。
{
"user_type": "premium",
"account_id": "ABC123"
}
创建会话时按名称添加到该会话的标签。最多 10 个,每个最多 50 个字符。名称不区分大小写,并以大写形式存储。应用中尚不存在的名称将作为新标签创建。这些标签会显示在控制台的会话中,您可以在控制台中按标签进行过滤。
1050["VIP", "ONBOARDING Q4"]
验证流程界面的语言代码(ISO 639-1)。控制验证期间向终端用户显示的语言。如果未提供,将自动检测并使用浏览器的语言。请在此处查看所有支持的语言。
en, ar, bg, bn, bs, ca, cnr, cs, da, de, el, es, et, fa, fi, fr, he, hi, hr, hu, hy, id, it, ja, ka, kk, ko, ky, lt, lv, mk, mn, ms, nl, no, pl, pt-BR, pt, ro, ru, sk, sl, so, sq, sr, sv, th, tr, uk, uz, vi, zh-CN, zh-TW, zh "en"
可用于通知、预填验证表单以及电话验证的用户联系信息。包括电子邮箱地址、首选沟通语言和电话号码。
Show child attributes
Show child attributes
{
"email": "john.doe@example.com",
"send_notification_emails": true,
"email_lang": "en",
"phone": "+14155552671"
}
预期的用户详细信息,用于与从用户身份证件、地址证明和其他验证步骤中提取的数据进行交叉比对。不匹配项将在决策中作为警告呈现;某些字段(例如 id_country、expected_document_types)还会改变面向用户的流程。对于企业验证(KYB)工作流,仅使用企业字段(company_name、registry_country、registration_number),它们会为用户预填充公司登记搜索,所有人员级字段均被忽略。
Show child attributes
Show child attributes
{
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15",
"nationality": "USA",
"id_country": "USA",
"expected_document_types": ["P", "ID"]
}
终端用户人脸的 Base64 编码肖像图像(最大 2MB;JPEG、PNG、WebP 或 TIFF)。当工作流是启用了人脸比对的 Biometric Authentication 工作流,或人脸比对在身份证件验证(OCR)之前运行的任何图谱工作流时,用作与活体采集进行比对的参考图像。当 vendor_data 用户已有存储的人脸图像时为可选:Didit 会按以下优先级自动复用:已通过的活体人脸、电子护照芯片照片、身份证件肖像、手动录入的个人资料人脸(仅复用来自已通过会话的人脸或您自行录入的人脸)。提供时,portrait_image 始终优先于存储的人脸。如果省略且不存在已存储的人脸(或未发送 vendor_data),会话创建将失败并返回 400。对于其他工作流类型将被忽略。
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
仅限沙盒的场景 slug。仅在 API 密钥属于沙盒模式应用时被接受;在生产环境应用上会被拒绝。设置后,创建流程会将场景绑定的魔法值展开到会话的输入字段(contact_details、expected_details)中,以便模拟的供应商通过真实的工作流管道复现该场景的结果。请参阅 GET /v1/sandbox/scenarios/ 中的场景目录或沙盒与测试数据。只要会话仍处于 Not Started 状态,您也可以在创建后通过 POST /v3/session/{sessionId}/sandbox/arm/ 预设(或重新预设)场景。对于非证件查询,使用 lookup_partial_match、lookup_no_match 或 lookup_provider_error 来测试配置的尝试预算和回退机制。对于身份钱包,使用 wallet_cancelled、wallet_timeout 或 wallet_provider_error;approve 模拟已验证的钱包。所有目录中的钱包均可在沙盒中进行测试,包括生产环境应用中不可用的方案。模拟的尝试不会被计费。
"decline_document_expired"
此会话的电子签名输入。documents 为待签署的文件,适用于电子签名步骤从会话中获取文件(signature_documents_source 为 session 或 both)的工作流:总计最多 20 个文件和 50 MB。field_values 用于填充工作流文件和会话文件中 prefill 为 api.<key> 的字段。针对相同的 workflow_id 和 vendor_data 再次创建会话将返回待处理的会话;如果该调用发送了 sign,其文件、字段和值必须与首次调用完全一致,若有任何不同,将返回 400 以及 {"sign": "signature_document_changed"}。请参阅 电子签名文件。
Show child attributes
Show child attributes
响应
会话已创建(如果工作流最新发布的版本上已存在具有相同 vendor_data 的未完成会话,则直接返回)。响应为序列化的会话,包括用于将用户重定向至托管验证页面的 url。
验证会话的唯一标识符。调用 GET /v3/session/{sessionId}/decision/ 时使用此 ID。
"11111111-2222-3333-4444-555555555555"
在您的应用内分配给该会话的便于人类阅读的序号。便于客服支持和在仪表板中使用。
43762
12 个字符的 URL 安全 token,用于授权终端用户通过 url 访问托管验证流程。在会话过期前一直有效。请将其视为机密信息 — 任何持有该 token 的人都可以打开此会话的验证流程。
"3FaJ9wLqX2Mz"
用于重定向终端用户的托管验证 URL。该 URL 内嵌了 session_token,若已配置,还会使用您的白标域名。当请求包含 language 时,URL 会包含语言路径段:https://verify.didit.me/{language}/session/{session_token}(例如 /es/session/...);若未提供 language,则省略该路径段。
"https://verify.didit.me/session/3FaJ9wLqX2Mz"
您在请求中传递的标识符,用于将该会话链接到您自身系统中的用户或企业。逐字回传。未提供时为 null。
"user-123"
在创建会话时随其一起存储的任意 JSON payload。原样回显:无论您发送的是何种 JSON 值(对象、字符串、数字、数组),都将按原样返回,但建议使用 JSON 对象。不对终端用户显示。始终在响应中提供;创建时未提供则为 null。
{
"user_type": "premium",
"account_id": "ABC123"
}
会话的当前状态。新创建的会话返回 Not Started。如果工作流最新发布的版本上已存在具有相同 vendor_data 的未完成会话,则返回的状态反映该现有会话。
Not Started, In Progress, Approved, Declined, In Review, Expired, Abandoned, Kyc Expired, Resubmitted, Awaiting User "Not Started"
用户完成流程后被重定向到的最终重定向 URL。Didit 会在此 URL 后追加 ?verificationSessionId={session_id}&status={status}。若请求中未提供,则回退到工作流配置的回调 URL;若两者均未设置则为 null。当应用配置了允许的域名且此 URL 是域名列表之外的 Web URL 时(例如在更改列表前设置的工作流默认值),托管流程不会将用户重定向至该 URL。
"https://example.com/verification/callback"
此会话运行所在工作流的稳定标识符。始终为工作流的稳定分组标识符。即使您在请求中引用了特定工作流版本的 UUID(向后兼容的查找方式),响应中也会包含稳定的 workflow_id。使用它可将会话与您在控制台中配置的工作流进行关联。
"11111111-2222-3333-4444-555555555555"
会话在创建时所绑定的已发布工作流版本号。在创建会话时,Didit 会将 workflow_id 解析为该工作流最新发布的版本,即使之后重新发布工作流,该会话也会继续运行该版本。
3
会话中的标签,按名称列出。
["VIP", "ONBOARDING Q4"]