跳转到主要内容

KYC · 客户准入

用于个人客户准入的异步工作流:注册客户、安全恢复或发起执行、查询状态与审核结果,并为每个等待节点提交数据。

流程概览

标准 KYC 工作流:

  1. 注册客户。
  2. 查询现有执行记录,以安全恢复流程并防止重复提交。
  3. 没有现有执行记录时,发起工作流。
  4. 查询状态,直到节点等待输入、案件进入人工审核或执行到达终止状态。
  5. 提交节点数据(OCR / 客户资料 / 活体检测 / OTP / 表单)。
  6. 工作流完成或转入人工审核。

1. 注册客户

Endpoint: workflow.applicant.register (POST).

{
  "customerId": "C_abc123",
  "email": "john@example.com"
}

At least one of customerId or email is required. This API is idempotent.

2. 恢复或发起工作流

2.1 查询现有执行记录

接口:workflow.apply.query(POST)。创建执行前应按 customerId 查询。这样可以防止重复提交,并在请求超时或未收到发起响应时恢复 executionId

{ "customerId": "C_abc123" }

如返回现有执行记录,请保留其 executionId 并继续查询状态。如没有执行记录,则发起新的工作流。

2.2 发起工作流

接口:workflow.apply.submit(POST)。请求应使用 apiVersion=2.0.0

{
  "eventType": "KYC",
  "source": "API",
  "data": {
    "customerId": "C_abc123",
    "referenceId": "onboarding-uuid-001"
  }
}

workflowId 为可选字段。当集成需要明确选择已发布的工作流时提供该字段。否则,WIDTH 会根据事件类型及租户配置匹配适用的已发布工作流。

响应包含创建的 executionIdsync 处理标识及响应 code200 表示正常处理。403 表示额度不足;额度恢复前请勿重复创建执行。

3. 查询执行状态与审核结果

接口:workflow.execution.status(POST)。

{ "executionId": "exec-abc123def456" }
字段说明
status当前工作流执行状态
caseNo此执行在 WIDTH 中创建的案件编号
caseStatus当前案件审核状态:UNASSIGNEDUNDER_REVIEWRETURNEDOTHER_GROUPAPPROVEDREJECTEDCLOSED
riskScore计算得出的风险评分(如适用)
resolvedAt案件达到最终处理结果的时间
状态含义Action
RUNNINGExecuting, no node waitingContinue polling (2–5 sec)
WAITINGNode waiting for inputRead currentNode, submit data
COMPLETEDWorkflow finishedStop polling, read result
FAILEDExecution failedStop polling, contact support
TIMEOUTExceeded time limitStop polling, contact support
CANCELLEDExecution cancelledStop polling
人工审核属于正常工作流状态,并非 API 失败。自动处理期间每 3–5 秒查询一次。当 caseStatusUNASSIGNEDUNDER_REVIEWRETURNED 时,将查询间隔放宽至 30–60 秒。执行达到终止状态后停止查询。

4. 提交节点数据

When status is WAITING, dispatch on currentNode.nodeType:

nodeTypeAPIPurpose
flow_action_identity_documentworkflow.kyc.ocrUpload ID, get OCR result
flow_action_individual_particularworkflow.kyc.particular.dataSubmit personal info
flow_action_liveness_testworkflow.kyc.liveness.dataSubmit liveness status
flow_action_validate_emailworkflow.kyc.otp.send/verifyEmail OTP
flow_action_validate_phoneworkflow.kyc.otp.send/verifyPhone OTP
flow_action_individual_required_documentworkflow.kyc.required.docSupporting documents
flow_action_individual_required_formsworkflow.kyc.required.formForms / questionnaires
flow_action_screen_check(automatic)AML / sanctions screening

身份证件(OCR)

Submit: workflow.kyc.ocr (POST). Poll for OCR results at workflow.kyc.ocr.data after 2–5 seconds — OCR usually completes in 5–15 seconds.

{
  "provider": "WIDTH",
  "frontImage": "s3://workflow-kyc/.../front.jpg",
  "backImage":  "s3://workflow-kyc/.../back.jpg",
  "documentType": "INTERNATIONAL_PASSPORT",
  "region": "SG",
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:ocr:exec-abc123def456:...",
  "referenceId": "onboarding-uuid-001"
}

客户信息提交

Endpoint: workflow.kyc.particular.data.

{
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:particular:exec-abc123def456:...",
  "referenceId": "onboarding-uuid-001",
  "personData": "{\"name\":\"John Smith\",\"dateOfBirth\":\"1990-01-15\",\"nationality\":\"SG\",\"sex\":\"MALE\",\"countryOfResidence\":\"SG\",\"address\":\"123 Main St\"}"
}
personData is a JSON-encoded string, not a nested object. Call JSON.stringify() on the data before placing it in the request body.

活体检测

Endpoint: workflow.kyc.liveness.data.

{
  "provider": "SELF",
  "status": "PASS",
  "scores": "{\"qualityScore\":1.0,\"brightnessScore\":100,\"brightnessStatus\":\"normal\"}",
  "images": "{\"faceFull\":\"s3://workflow-kyc/.../selfie.jpg\"}",
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:liveness:exec-abc123def456:...",
  "referenceId": "onboarding-uuid-001"
}

邮箱 / 手机 OTP

Two steps: workflow.kyc.otp.send then workflow.kyc.otp.verify.

// send
{
  "type": "email",
  "identity": "john@example.com",
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:email:exec-abc123def456:...",
  "referenceId": "onboarding-uuid-001"
}

// verify
{
  "type": "email",
  "identity": "john@example.com",
  "code": "985024",
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:email:exec-abc123def456:...",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "referenceId": "onboarding-uuid-001"
}

必需证件

Endpoint: workflow.kyc.required.doc. After all docs are uploaded, call workflow.kyc.required.doc.submit to advance.

{
  "doc": "{\"front\":{\"url\":\"s3://workflow-kyc/.../bill.pdf\",\"filename\":\"bill.pdf\",\"content_type\":\"application/pdf\",\"size\":85618}}",
  "isRequired": true,
  "docType": "UTILITY_TELEPHONE_BILL",
  "extraData": "{\"issueDate\":\"2026-03-01\"}",
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:required_doc:exec-abc123def456:...",
  "referenceId": "onboarding-uuid-001"
}

必需表单

Endpoint: workflow.kyc.required.form.

{
  "formId": "IndividualForm",
  "formData": "{\"field_source_of_funds\":\"EMPLOYMENT\",\"field_annual_income\":\"50000-100000\"}",
  "executionId": "exec-abc123def456",
  "callbackKey": "kyc:required_form:exec-abc123def456:...",
  "referenceId": "onboarding-uuid-001"
}