> ## 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.

# Verification Statuses

> Every Didit session status explained: Approved, Declined, In Review, Expired, Resubmitted, Abandoned, KYC Expired. Handle decisions, retries, and webhooks.

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.

***

## All Status Values

<Note>
  Every status is an **exact string** returned by the Didit API and webhooks. Always use strict string matching (e.g., `=== "In Review"`) in your code — these values are case-sensitive and include spaces. The `Kyc Expired` value also uses a single capital `K` (not `KYC`).
</Note>

| Status        | String Value      | Description                                                          |
| ------------- | ----------------- | -------------------------------------------------------------------- |
| Not Started   | `"Not Started"`   | Session created, user hasn't opened the link                         |
| In Progress   | `"In Progress"`   | User is actively completing verification                             |
| Approved      | `"Approved"`      | All checks passed — identity verified                                |
| Declined      | `"Declined"`      | One or more checks failed                                            |
| In Review     | `"In Review"`     | Flagged for manual compliance review                                 |
| Awaiting User | `"Awaiting User"` | Waiting for one or more parties to complete their verification (KYB) |
| Resubmitted   | `"Resubmitted"`   | User asked to redo specific steps                                    |
| Expired       | `"Expired"`       | Session timed out before user opened the link                        |
| Abandoned     | `"Abandoned"`     | User started but didn't finish in time                               |
| KYC Expired   | `"Kyc Expired"`   | Previously approved session exceeded KYC expiration                  |

***

## Session Statuses

<AccordionGroup>
  <Accordion title="Not Started — &#x22;Not Started&#x22;" icon="circle-dot">
    **API value:** `"Not Started"`

    The session has been created via the API but the user **has not opened the verification link yet**.

    * **What to do:** Wait for the user to begin, or send a reminder if too much time passes.
    * **Transitions to:** `"In Progress"`, `"Expired"`
  </Accordion>

  <Accordion title="In Progress — &#x22;In Progress&#x22;" icon="spinner">
    **API value:** `"In Progress"`

    The user has opened the link and is **actively completing verification steps** (document capture, liveness, etc.).

    * **What to do:** No action needed — the user is working through the flow.
    * **Transitions to:** `"Approved"`, `"Declined"`, `"In Review"`, `"Abandoned"`
  </Accordion>

  <Accordion title="Approved — &#x22;Approved&#x22;" icon="circle-check">
    **API value:** `"Approved"`

    All verification checks **passed successfully**. The user's identity has been verified.

    * **What to do:** Grant the user access, update their profile, and store the decision data.
    * **Webhook includes:** Full `decision` object with all feature results.
    * **Transitions to:** `"Kyc Expired"` (if a KYC expiration policy is configured)
  </Accordion>

  <Accordion title="Declined — &#x22;Declined&#x22;" icon="circle-xmark">
    **API value:** `"Declined"`

    One or more verification checks **failed**. The user did not pass verification.

    * **What to do:** Notify the user. Optionally request a resubmission if the issue is fixable.
    * **Webhook includes:** Full `decision` object with warnings explaining the failure.
    * **Transitions to:** `"Resubmitted"` (if a reviewer requests it)
  </Accordion>

  <Accordion title="In Review — &#x22;In Review&#x22;" icon="magnifying-glass">
    **API value:** `"In Review"`

    Automated checks flagged **warnings that need human review**. A compliance reviewer must make the final decision.

    * **What to do:** A reviewer should open the session in the Console and approve, decline, or request resubmission.
    * **Webhook includes:** Full `decision` object with warnings.
    * **Transitions to:** `"Approved"`, `"Declined"`, `"Resubmitted"`
  </Accordion>

  <Accordion title="Awaiting User — &#x22;Awaiting User&#x22;" icon="users">
    **API value:** `"Awaiting User"`

    Used in **KYB (business verification) sessions** when the Key People step has submitted the list of parties and spawned child KYC / KYB sessions. The parent session waits until **all required parties complete their individual verification**.

    * **What to do:** Monitor the child KYC session statuses. Once all required parties finish (approved, declined, or expired), the parent session automatically re-aggregates to its final status.
    * **Webhook includes:** The current list of parties and their child session statuses.
    * **Transitions to:** `"Approved"`, `"Declined"`, `"In Review"` (once all child sessions are terminal)
    * **Transitions from:** `"In Progress"` (after the Key People step is submitted)
    * **Note:** If a child KYC session is resubmitted, the parent returns to `"Awaiting User"` until the resubmitted session completes. A `"Declined"` KYB Registry Check takes precedence over `"Awaiting User"`.
  </Accordion>

  <Accordion title="Resubmitted — &#x22;Resubmitted&#x22;" icon="rotate">
    **API value:** `"Resubmitted"`

    A reviewer has requested that the user **redo specific verification steps** (e.g., retake a blurry document photo).

    * **What to do:** Wait for the user to complete the resubmitted steps. The system will automatically re-evaluate.
    * **Webhook includes:** `resubmit_info` object with the list of features to redo and reasons.
    * **Transitions to:** `"Approved"`, `"Declined"`, `"In Review"`
  </Accordion>

  <Accordion title="Expired — &#x22;Expired&#x22;" icon="clock">
    **API value:** `"Expired"`

    The session **timed out before the user opened the verification link**.

    * **What to do:** Create a new session and send the user a fresh link.
    * **Terminal status** — no further transitions.
  </Accordion>

  <Accordion title="Abandoned — &#x22;Abandoned&#x22;" icon="person-walking-arrow-right">
    **API value:** `"Abandoned"`

    The user **started but did not finish** the verification within the allowed timeframe.

    * **What to do:** Send a reminder or create a new session.
    * **Terminal status** — no further transitions.
  </Accordion>

  <Accordion title="KYC Expired — &#x22;Kyc Expired&#x22;" icon="hourglass-end">
    **API value:** `"Kyc Expired"`

    A previously approved session has **exceeded the configured KYC expiration period** (e.g., 12 months).

    * **What to do:** Request the user to re-verify by creating a new session.
    * **Terminal status** — no further transitions.
  </Accordion>
</AccordionGroup>

***

## Status Transitions

| From                        | To                             | Trigger                                                           |
| --------------------------- | ------------------------------ | ----------------------------------------------------------------- |
| `"Not Started"`             | `"In Progress"`                | User opens the verification link                                  |
| `"Not Started"`             | `"Expired"`                    | Session TTL elapses before the user opens the link                |
| `"In Progress"`             | `"Approved"`                   | All automated checks pass                                         |
| `"In Progress"`             | `"Declined"`                   | One or more checks fail                                           |
| `"In Progress"`             | `"In Review"`                  | Checks flag warnings requiring human review                       |
| `"In Progress"`             | `"Awaiting User"`              | KYB Key People step submitted; parent waits for child KYC parties |
| `"In Progress"`             | `"Abandoned"`                  | User doesn't finish within the timeframe                          |
| `"Awaiting User"`           | `"Approved"`                   | All required KYB parties finish and aggregated checks pass        |
| `"Awaiting User"`           | `"Declined"`                   | A required party is declined or the KYB registry check fails      |
| `"Awaiting User"`           | `"In Review"`                  | Aggregated KYB result requires manual review                      |
| `"In Review"`               | `"Approved"`                   | Reviewer manually approves                                        |
| `"In Review"`               | `"Declined"`                   | Reviewer manually declines                                        |
| `"In Review"`               | `"Resubmitted"`                | Reviewer requests specific steps to be redone                     |
| `"Declined"`                | `"Resubmitted"`                | Reviewer requests specific steps to be redone                     |
| `"Resubmitted"`             | `"Approved"`                   | Resubmitted steps pass all checks                                 |
| `"Resubmitted"`             | `"Declined"`                   | Resubmitted steps fail                                            |
| `"Resubmitted"`             | `"In Review"`                  | Resubmitted steps flag new warnings                               |
| `"Resubmitted"` (KYB child) | `"Awaiting User"` (KYB parent) | Parent re-enters waiting state until child completes              |
| `"Approved"`                | `"Kyc Expired"`                | KYC expiration policy triggers                                    |

### Lifecycle diagram

```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
    RS --> AP
    RS --> DC
    RS --> IR
    AP --> KE["Kyc Expired"]
```

***

## Terminal vs Non-Terminal

| Category         | Statuses                                                             | Meaning                                                                                                                  |
| ---------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| **Terminal**     | `"Approved"`, `"Declined"`, `"Kyc Expired"`                          | Final decision — session won't change again, except `"Approved"` → `"Kyc Expired"` when a KYC expiration policy applies. |
| **Non-Terminal** | `"Not Started"`, `"In Progress"`, `"Resubmitted"`, `"Awaiting User"` | Still active — awaiting user action, child sessions, or processing.                                                      |
| **Actionable**   | `"In Review"`                                                        | Requires manual intervention from your team.                                                                             |
| **Inactive**     | `"Expired"`, `"Abandoned"`                                           | Ended without a verification decision.                                                                                   |

***

## Handling Statuses in Your Code

Use webhooks or the [Retrieve Session API](/sessions-api/retrieve-session) to react to status changes.

<Warning>
  Statuses are **exact, case-sensitive strings with spaces**. For example, `"In Review"` (not `"in_review"` or `"IN_REVIEW"`). Always use strict equality (`===`) when matching.
</Warning>

```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;
  }
}
```

***

## Resubmission

The **Resubmitted** status lets your compliance team give users a second chance without creating a new session.

<Steps>
  <Step title="Reviewer initiates resubmission">
    From the Console, open an `In Review` or `Declined` session and click **Request Resubmission**. Select which steps need to be redone.
  </Step>

  <Step title="Previous data is archived">
    The system resets the selected features and marks prior data as `previous_attempt` — preserving the full audit trail.
  </Step>

  <Step title="User is notified">
    If an email is available, the user receives a localized email with a direct link to resume.
  </Step>

  <Step title="User redoes specific steps">
    The user only repeats the steps that were flagged — not the entire verification.
  </Step>

  <Step title="System re-evaluates">
    Once complete, the session automatically transitions to `"Approved"`, `"Declined"`, or `"In Review"`.
  </Step>
</Steps>

### Resubmission 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 image is blurry or unreadable",
      "feature_liveness": "Liveness check score below threshold"
    }
  }
}
```

### Which Features Can Be Resubmitted?

Any feature with a non-approved status: **Declined**, **In Review**, **Not Finished**, **Not Started**, or **Expired**.

<Tip>
  You can request resubmission multiple times on the same session. Each cycle archives the previous attempt data, giving you complete visibility into the user's verification history.
</Tip>

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Monitor In Review" icon="bell">
    Set up alerts (email or Slack) in your Didit Console to get notified when sessions need manual review.
  </Card>

  <Card title="Prefer Resubmission" icon="rotate">
    If the issue is fixable (blurry photo, wrong document side), request a resubmission instead of declining. This improves conversion.
  </Card>

  <Card title="Track Drop-offs" icon="chart-line">
    High Abandoned or Expired rates may indicate UX friction. Consider adjusting session TTL or improving user guidance.
  </Card>

  <Card title="Idempotent Handlers" icon="shield">
    Webhooks may be retried. Use `session_id` as a unique key to ensure you process each status change only once.
  </Card>
</CardGroup>

<Warning>
  Always verify webhook signatures before processing payloads. Didit provides three methods: `X-Signature`, `X-Signature-V2` (recommended), and `X-Signature-Simple`. See [Webhooks](/integration/webhooks) for details.
</Warning>
