> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# 验证状态：会话生命周期与状态码

> Didit 各会话状态详解：已通过、已拒绝、审核中、已过期、重新提交、已放弃、KYC 已过期。涵盖决策处理、重试与 Webhook。

Every verification session moves through a series of statuses. Understanding them helps you monitor user progress, automate compliance decisions, and optimize conversion.

This enum is the single source of truth for the strings returned by `GET /v3/session/<id>/decision/` and every Didit webhook.

***

## 所有状态值

> [!NOTE]
>
> 每个状态都是 Didit API 和 Webhook 返回的精确字符串。在代码中请始终使用严格的字符串匹配（例如 `=== "In Review"`）。这些值区分大小写，并且包含空格。`Kyc Expired` 的值中 `K` 为单个大写字母（而不是 `KYC`）。

| 状态 | 字符串值 | 说明 |
| - | - | - |
| 未开始 | `"Not Started"` | 会话已创建，用户尚未打开链接 |
| 进行中 | `"In Progress"` | 用户正在完成验证 |
| 已通过 | `"Approved"` | 所有检查均已通过，身份已验证 |
| 已拒绝 | `"Declined"` | 一项或多项检查未通过 |
| 审核中 | `"In Review"` | 已标记为需要人工合规审核 |
| 等待用户 | `"Awaiting User"` | 正在等待一方或多方完成其验证（KYB） |
| 已重新提交 | `"Resubmitted"` | 用户被要求重新执行特定步骤 |
| 已过期 | `"Expired"` | 会话在用户打开链接之前已超时 |
| 已放弃 | `"Abandoned"` | 用户已开始但未能在规定时间内完成 |
| KYC 已过期 | `"Kyc Expired"` | 此前已通过的会话，其已验证证件已超过有效期 |

***

## 会话状态

> [accordion] 未开始（"Not Started"）
>
> **API 值：** `"Not Started"`
>
> 会话已通过 API 创建，但用户**尚未打开验证链接**。
>
> * **建议操作：** 等待用户开始；如果等待时间过长，可发送提醒。
> * **可转换为：** `"In Progress"`、`"Expired"`

> [accordion] 进行中（"In Progress"）
>
> **API 值：** `"In Progress"`
>
> 用户已打开链接，并且**正在完成验证步骤**（证件拍摄、活体检测等）。
>
> * **建议操作：** 无需操作，用户正在完成流程。
> * **可转换为：** `"Approved"`、`"Declined"`、`"In Review"`、`"Abandoned"`

> [accordion] 已通过（"Approved"）
>
> **API 值：** `"Approved"`
>
> 所有验证检查**均已成功通过**。用户的身份已完成验证。
>
> * **建议操作：** 为用户开通访问权限、更新其资料，并存储决策数据。
> * **Webhook 包含：** 完整的 `decision` 对象，其中包含所有功能的结果。
> * **可转换为：** `"Kyc Expired"`（当已验证证件的到期日期已过时；除非该国家/地区和证件类型的 **Expiration mode** 设为 **Allow expired**，否则默认如此）。审核员或更新状态接口也可以将其设为 `"Declined"` 或 `"Resubmitted"`。

> [accordion] 已拒绝（"Declined"）
>
> **API 值：** `"Declined"`
>
> 一项或多项验证检查**失败**。用户未通过验证。
>
> * **建议操作：** 通知用户。如果问题可以修复，可选择请求重新提交。
> * **Webhook 包含：** 完整的 `decision` 对象，其中包含说明失败原因的警告。
> * **可转换为：** `"Resubmitted"`（如果审核员请求重新提交）。审核员或更新状态接口也可以将其设为 `"Approved"`。

> [accordion] 审核中（"In Review"）
>
> **API 值：** `"In Review"`
>
> 自动检查标记了**需要人工审核的警告**。最终决定须由合规审核员做出。
>
> * **建议操作：** 审核员应在控制台中打开该会话，然后选择通过、拒绝或请求重新提交。
> * **Webhook 包含：** 完整的 `decision` 对象，其中包含警告。
> * **可转换为：** `"Approved"`、`"Declined"`、`"Resubmitted"`

> [accordion] 等待用户（"Awaiting User"）
>
> **API 值：** `"Awaiting User"`
>
> 用于**企业验证（KYB）会话**。当关键人员步骤提交了相关方列表并生成了子 KYC / KYB 会话后，会使用此状态。父会话会等待**所有必需相关方都完成各自的验证**。
>
> * **建议操作：** 监控子 KYC 会话的状态。当所有必需相关方都完成（已通过、已拒绝或已过期）后，父会话会自动重新汇总，得出最终状态。
> * **Webhook 包含：** 当前的相关方列表及其子会话状态。
> * **可转换为：** `"Approved"`、`"Declined"`、`"In Review"`（当所有子会话都进入终态后）
> * **来源状态：** `"In Progress"`（关键人员步骤提交后）
> * **注意：** 如果某个子 KYC 会话被重新提交，父会话会回到 `"Awaiting User"`，直到重新提交的会话完成。`"Declined"` 的 KYB 公司登记检查优先于 `"Awaiting User"`。

> [accordion] 重新提交（"Resubmitted"）
>
> **API 值：** `"Resubmitted"`
>
> 审核员请求用户**重新完成特定的验证步骤**（例如重新拍摄模糊的证件照片）。
>
> * **建议操作：** 等待用户完成重新提交的步骤。系统将自动重新评估。
> * **Webhook 包含：** `resubmit_info` 对象，其中列出需要重做的功能及原因。
> * **可转换为：** `"Approved"`、`"Declined"`、`"In Review"`；如果会话时间窗口在用户重做步骤之前结束，则转换为 `"Abandoned"`。

> [accordion] 已过期（"Expired"）
>
> **API 值：** `"Expired"`
>
> 会话在用户打开验证链接**之前**就已超时。
>
> * **建议操作：** 创建新会话，并向用户发送新的链接。
> * **终态**：不会再发生任何转换。

> [accordion] 已放弃（"Abandoned"）
>
> **API 值：** `"Abandoned"`
>
> 用户**已开始但未在允许的时间内完成**验证。
>
> * **建议操作：** 发送提醒，或创建新会话。
> * **没有自动转换。** 审核员或 `PATCH /v3/session/{sessionId}/update-status/` 仍可将其设为 `"Approved"`、`"Declined"` 或 `"Resubmitted"`。

> [accordion] KYC 已过期（"Kyc Expired"）
>
> **API 值：** `"Kyc Expired"`
>
> 会话中验证的证件已**超过其自身的到期日期**。触发条件是该到期日期本身，而不是从通过时起算的时间窗口，并且不会提前发送任何警告。
>
> * **建议操作：** 请用户通过新会话重新验证。`status.updated` 会推送此次转换，身份证件验证结果会包含 `DOCUMENT_EXPIRED` 警告。
> * **由以下设置控制：** *身份证件验证 → 按国家/地区和证件类型的附加设置* 中该国家/地区和证件类型的 **Expiration mode**。**Reject expired**（默认）会对证件进行监控，**Allow expired** 则表示会话永远不会转到此状态。
> * **没有自动转换。** 审核员或 `PATCH /v3/session/{sessionId}/update-status/` 仍可将其设为 `"Approved"`、`"Declined"` 或 `"Resubmitted"`。

***

## 状态转换

| 起始状态 | 目标状态 | 触发条件 |
| - | - | - |
| `"Not Started"` | `"In Progress"` | 用户打开验证链接 |
| `"Not Started"` | `"Expired"` | 用户打开链接前，会话 TTL 已到期 |
| `"In Progress"` | `"Approved"` | 所有自动检查通过 |
| `"In Progress"` | `"Declined"` | 一项或多项检查失败 |
| `"In Progress"` | `"In Review"` | 检查标记了需要人工审核的警告 |
| `"In Progress"` | `"Awaiting User"` | 提交 KYB 关键人员步骤；父级会话等待子级 KYC 当事方 |
| `"In Progress"` | `"Abandoned"` | 用户未在时限内完成 |
| `"Awaiting User"` | `"Approved"` | 所有必需的 KYB 当事方均已完成，且汇总检查通过 |
| `"Awaiting User"` | `"Declined"` | 必需当事方被拒绝，或 KYB 公司登记检查失败 |
| `"Awaiting User"` | `"In Review"` | KYB 汇总结果需要人工审核 |
| `"In Review"` | `"Approved"` | 审核员手动通过 |
| `"In Review"` | `"Declined"` | 审核员手动拒绝 |
| `"In Review"` | `"Resubmitted"` | 审核员要求重做特定步骤 |
| `"Declined"` | `"Resubmitted"` | 审核员要求重做特定步骤 |
| `"Approved"` | `"Resubmitted"` | 审核员要求重做特定步骤 |
| `"Approved"` | `"Declined"` | 审核员或 API 设置另一决策 |
| `"Declined"` | `"Approved"` | 审核员或 API 设置另一决策 |
| `"Abandoned"`, `"Kyc Expired"` | `"Approved"`, `"Declined"`, `"Resubmitted"` | 审核员或 API 对已结束但未作出决策的会话作出决策 |
| `"Resubmitted"` | `"Abandoned"` | 会话时限在用户重做步骤前结束 |
| `"Resubmitted"` | `"Approved"` | 重新提交的步骤通过所有检查 |
| `"Resubmitted"` | `"Declined"` | 重新提交的步骤未通过 |
| `"Resubmitted"` | `"In Review"` | 重新提交的步骤标记了新的警告 |
| `"Resubmitted"`（KYB 子级） | `"Awaiting User"`（KYB 父级） | 父级重新进入等待状态，直至子级完成 |
| `"Approved"` | `"Kyc Expired"` | 已验证证件的到期日期已过（过期模式为 **Reject expired**） |

### 生命周期图

```mermaid theme={null}
flowchart LR
    NS["Not Started"] --> IP["In Progress"]
    NS --> EX["Expired"]
    IP --> AP["Approved"]
    IP --> DC["Declined"]
    IP --> IR["In Review"]
    IP --> AU["Awaiting User<br/>(KYB only)"]
    IP --> AB["Abandoned"]
    AU --> AP
    AU --> DC
    AU --> IR
    IR --> AP
    IR --> DC
    IR --> RS["Resubmitted"]
    DC --> RS
    AP --> RS
    AP <--> DC
    AB --> AP
    AB --> DC
    AB --> RS
    KE --> AP
    KE --> DC
    KE --> RS
    RS --> AB
    RS --> AP
    RS --> DC
    RS --> IR
    AP --> KE["Kyc Expired"]
```

***

## 终态与非终态

| 类别 | 状态 | 含义 |
| - | - | - |
| **已确定** | `"Approved"`、`"Declined"`、`"Kyc Expired"` | 检查已作出决策，且决策不会自行改变，但当 **已验证证件的到期日期已过** 时，`"Approved"` 会变为 `"Kyc Expired"`。审核员或更新状态的 endpoint 仍可更改该决策。 |
| **非终态** | `"Not Started"`、`"In Progress"`、`"Resubmitted"`、`"Awaiting User"` | 仍处于活动状态：等待用户操作、等待子会话或正在处理。 |
| **需采取行动的** | `"In Review"` | 需要您的团队进行人工干预。 |
| **非活动** | `"Expired"`、`"Abandoned"` | 已结束，但未作出验证决策。`"Expired"` 永远不会改变；审核员仍可对 `"Abandoned"` 会话作出决策。 |

***

## 在代码中处理状态

使用 Webhook 或 [检索会话 API](https://docs.didit.me/zh/sessions-api/retrieve-session.md) 对状态变化作出响应。

> [!WARNING]
>
> 状态是**精确的、区分大小写且包含空格的字符串**。例如，`"In Review"`（而非 `"in_review"` 或 `"IN_REVIEW"`）。匹配时请始终使用严格相等（`===`）。

```javascript theme={null}
// All ten possible status string values (StatusChoices, source of truth):
// "Not Started"  | "In Progress" | "Approved"     | "Declined" |
// "In Review"    | "Resubmitted" | "Awaiting User"|
// "Expired"      | "Abandoned"   | "Kyc Expired"

async function handleWebhook(webhook) {
  const { status, vendor_data: vendorData } = webhook;

  switch (status) {
    case "Not Started":
      // Session created but user hasn't opened the link yet
      break;

    case "In Progress":
      // User is actively completing verification steps
      break;

    case "Approved":
      // All checks passed — grant access
      await db.users.update(vendorData, {
        verified: true,
        verifiedAt: new Date(),
        decision: webhook.decision,
      });
      break;

    case "Declined":
      // Verification failed — notify user
      await db.users.update(vendorData, {
        verificationStatus: "declined",
        declineReasons: webhook.decision?.warnings,
      });
      break;

    case "In Review":
      // Needs manual review by compliance team
      await db.users.update(vendorData, {
        verificationStatus: "pending_review",
      });
      break;

    case "Awaiting User":
      // KYB parent waiting for all child KYC parties to finish
      await db.users.update(vendorData, {
        verificationStatus: "awaiting_kyb_parties",
      });
      break;

    case "Resubmitted":
      // User will redo specific steps
      await db.users.update(vendorData, {
        verificationStatus: "resubmission_pending",
        resubmitInfo: webhook.resubmit_info,
      });
      break;

    case "Abandoned":
      // User started but didn't finish — send reminder
      await sendReminderEmail(vendorData);
      break;

    case "Expired":
    case "Kyc Expired":
      // Session expired — create a new one
      await createNewSession(vendorData);
      break;
  }
}
```

***

## 重新提交

**Resubmitted**状态让您的合规团队无需创建新会话，即可再给用户一次机会。

**1. 审核员发起重新提交**

在控制台中打开 `In Review` 或 `Declined` 会话，然后点击 **Request Resubmission**。选择需要重做的步骤。

**2. 归档先前数据**

系统会重置所选功能，并将先前数据标记为 `previous_attempt`，保留完整的审计追踪。

**3. 通知用户**

如果有可用的邮箱，用户会收到一封本地化邮件，其中包含可直接继续验证的链接。

**4. 用户重做特定步骤**

用户只需重复被标记的步骤，而不必完成整个验证。

**5. 系统重新评估**

完成后，会话将自动转换为 `"Approved"`、`"Declined"` 或 `"In Review"`。

### 重新提交 Webhook payload

```json theme={null}
{
  "session_id": "uuid-of-the-session",
  "status": "Resubmitted",
  "resubmit_info": {
    "nodes_to_resubmit": [
      { "node_id": "feature_ocr", "feature": "OCR" },
      { "node_id": "feature_liveness", "feature": "LIVENESS" }
    ],
    "reasons": {
      "feature_ocr": "DOCUMENT_EXPIRED",
      "feature_liveness": "LOW_LIVENESS_SCORE"
    }
  }
}
```

`reasons` 将每个重新提交的 `node_id` 映射到该步骤上最相关日志的警告代码（与[决策](https://docs.didit.me/zh/reference/data-models.md)中报告的代码相同），方便您映射到自己的文案。托管流程的重新提交页面和重新提交邮件也会使用该代码为用户进行本地化展示，但涉及筛查或欺诈信号的警告除外（例如重复、AML、黑名单、跨组织检查、位置完整性等类似情况）：对于这些警告，用户看到的是通用原因，而 Webhook 中的 `resubmit_info.reasons` 始终包含真实代码。没有记录任何警告的步骤不会出现在该字段中。

### 哪些功能可以重新提交

任何状态不是已通过的功能均可重新提交：**Declined**、**In Review**、**Not Finished**、**Not Started** 或 **Expired**。

> [!TIP]
>
> 同一会话可多次请求重新提交。每个周期都会归档先前的尝试数据，让您完整查看用户的验证历史。

***

## 最佳实践

> [card] 监控审核中的会话
>
> 在 Didit Console 中设置警报（电子邮件或 Slack），以便会话需要人工审核时收到通知。

> [card] 优先重新提交
>
> 如果问题可以修正（照片模糊、证件正反面放错），请要求重新提交，而不是直接拒绝。这样可以提高转化率。

> [card] 跟踪流失情况
>
> 已放弃或已过期的比例较高，可能说明用户体验存在阻碍。可以考虑调整会话 TTL，或改进用户引导。

> [card] 幂等处理程序
>
> Webhook 可能会被重试。请使用 `session_id` 作为唯一键，确保每次状态变更只处理一次。

> [!WARNING]
>
> 在处理 payload 之前，请务必验证 Webhook 签名。Didit 提供三种方法：`X-Signature`、`X-Signature-V2`（推荐），以及已弃用的 `X-Signature-Simple`。该方法仅验证外层信封，绝不验证 `decision` 主体。详情请参阅 [Webhooks](https://docs.didit.me/zh/integration/webhooks.md#签名验证)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.