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

# Stati di verifica: ciclo di vita della sessione e codici

> Stati delle sessioni Didit: approvata, rifiutata, in revisione, scaduta, ripresentata, abbandonata, KYC scaduto. Gestisci decisioni e webhook.

Ogni sessione di verifica attraversa una serie di stati. Comprenderli ti aiuta a monitorare i progressi dell'utente, automatizzare le decisioni di compliance e ottimizzare il tasso di conversione.

Questo enum è l'unica fonte di verità per le stringhe restituite da `GET /v3/session/<id>/decision/` e da ogni webhook di Didit.

***

## Tutti i valori di stato

> [!NOTE]
>
> Ogni stato è una **stringa esatta** restituita dall'API e dai webhook di Didit. Nel tuo codice usa sempre il confronto stretto tra stringhe (ad esempio `=== "In Review"`): questi valori distinguono maiuscole e minuscole e contengono spazi. Anche il valore `Kyc Expired` usa una sola `K` maiuscola (non `KYC`).

| Stato | Valore stringa | Descrizione |
| - | - | - |
| Non avviata | `"Not Started"` | Sessione creata, l'utente non ha ancora aperto il link |
| In corso | `"In Progress"` | L'utente sta completando la verifica |
| Approvata | `"Approved"` | Tutti i controlli superati: identità verificata |
| Rifiutata | `"Declined"` | Uno o più controlli non superati |
| In revisione | `"In Review"` | Segnalata per la revisione manuale di compliance |
| In attesa dell'utente | `"Awaiting User"` | In attesa che una o più parti completino la propria verifica (KYB) |
| Ripresentata | `"Resubmitted"` | È stato chiesto all'utente di ripetere passaggi specifici |
| Scaduta | `"Expired"` | Sessione scaduta prima che l'utente aprisse il link |
| Abbandonata | `"Abandoned"` | L'utente ha iniziato ma non ha completato in tempo |
| KYC scaduto | `"Kyc Expired"` | Sessione precedentemente approvata il cui documento verificato ha superato la data di scadenza |

***

## Stati della sessione

> [accordion] Non avviata: "Not Started"
>
> **Valore API:** `"Not Started"`
>
> La sessione è stata creata tramite API, ma l'utente **non ha ancora aperto il link di verifica**.
>
> * **Cosa fare:** Attendere che l'utente inizi oppure inviare un promemoria se trascorre troppo tempo.
> * **Passa a:** `"In Progress"`, `"Expired"`

> [accordion] In corso: "In Progress"
>
> **Valore API:** `"In Progress"`
>
> L'utente ha aperto il link e sta **completando attivamente i passaggi di verifica** (acquisizione del documento, rilevamento della vitalità, ecc.).
>
> * **Cosa fare:** Nessuna azione necessaria: l'utente sta procedendo nel flusso.
> * **Passa a:** `"Approved"`, `"Declined"`, `"In Review"`, `"Abandoned"`

> [accordion] Approvata: "Approved"
>
> **Valore API:** `"Approved"`
>
> Tutti i controlli di verifica sono stati **superati con successo**. L'identità dell'utente è stata verificata.
>
> * **Cosa fare:** Concedere all'utente l'accesso, aggiornare il suo profilo e archiviare i dati della decisione.
> * **Il webhook include:** L'oggetto `decision` completo con tutti i risultati delle funzionalità.
> * **Passa a:** `"Kyc Expired"` (quando la data di scadenza del documento verificato viene superata: è il comportamento predefinito, a meno che per quel paese e quel tipo di documento **Expiration mode** non sia impostato su **Allow expired**). Un revisore o l'endpoint di aggiornamento dello stato può anche impostarla su `"Declined"` o `"Resubmitted"`.

> [accordion] Rifiutata: "Declined"
>
> **Valore API:** `"Declined"`
>
> Uno o più controlli di verifica **non hanno avuto esito positivo**. L'utente non ha superato la verifica.
>
> * **Cosa fare:** Informare l'utente. Facoltativamente, richiedere un nuovo invio se il problema è risolvibile.
> * **Il webhook include:** L'oggetto `decision` completo con gli avvisi che spiegano il motivo del mancato superamento.
> * **Passa a:** `"Resubmitted"` (se un revisore lo richiede). Un revisore o l'endpoint di aggiornamento dello stato può anche impostarla su `"Approved"`.

> [accordion] In revisione: "In Review"
>
> **Valore API:** `"In Review"`
>
> I controlli automatici hanno segnalato **avvisi che richiedono una revisione umana**. La decisione finale spetta a un responsabile della compliance.
>
> * **Cosa fare:** Un revisore dovrebbe aprire la sessione nella Console e approvarla, rifiutarla o richiedere un nuovo invio.
> * **Il webhook include:** L'oggetto `decision` completo con gli avvisi.
> * **Passa a:** `"Approved"`, `"Declined"`, `"Resubmitted"`

> [accordion] In attesa dell’utente: "Awaiting User"
>
> **Valore API:** `"Awaiting User"`
>
> Usato nelle **sessioni KYB (verifica aziendale)** quando il passaggio Persone chiave ha inviato l'elenco dei soggetti e ha generato sessioni KYC / KYB figlie. La sessione padre attende finché **tutti i soggetti richiesti non completano la propria verifica individuale**.
>
> * **Cosa fare:** Monitorare gli stati delle sessioni KYC figlie. Quando tutti i soggetti richiesti terminano (approvati, rifiutati o scaduti), la sessione padre ricalcola automaticamente il proprio stato finale.
> * **Il webhook include:** L'elenco attuale dei soggetti e gli stati delle rispettive sessioni figlie.
> * **Passa a:** `"Approved"`, `"Declined"`, `"In Review"` (una volta che tutte le sessioni figlie sono terminali)
> * **Proviene da:** `"In Progress"` (dopo l'invio del passaggio Persone chiave)
> * **Nota:** Se una sessione KYC figlia viene ripresentata, la sessione padre torna in `"Awaiting User"` finché la sessione ripresentata non viene completata. Un KYB Registry Check in stato `"Declined"` ha la precedenza su `"Awaiting User"`.

> [accordion] Ripresentata: "Resubmitted"
>
> **Valore API:** `"Resubmitted"`
>
> Un revisore ha richiesto che l'utente **ripeta specifici passaggi di verifica** (ad esempio, rifaccia una foto sfocata del documento).
>
> * **Cosa fare:** Attendere che l'utente completi i passaggi da ripetere. Il sistema rivaluterà automaticamente la sessione.
> * **Il webhook include:** L'oggetto `resubmit_info` con l'elenco delle funzionalità da ripetere e i motivi.
> * **Passa a:** `"Approved"`, `"Declined"`, `"In Review"`, oppure `"Abandoned"` quando la finestra della sessione termina prima che la persona ripeta i passaggi.

> [accordion] Scaduta: "Expired"
>
> **Valore API:** `"Expired"`
>
> La sessione è **scaduta prima che l'utente aprisse il link di verifica**.
>
> * **Cosa fare:** Creare una nuova sessione e inviare all'utente un nuovo link.
> * **Stato terminale**: nessun ulteriore passaggio di stato.

> [accordion] Abbandonata: "Abandoned"
>
> **Valore API:** `"Abandoned"`
>
> L'utente **ha avviato ma non ha completato** la verifica entro il tempo consentito.
>
> * **Cosa fare:** Inviare un promemoria oppure creare una nuova sessione.
> * **Nessuna transizione automatica.** Un revisore, oppure `PATCH /v3/session/{sessionId}/update-status/`, può comunque impostarla su `"Approved"`, `"Declined"` o `"Resubmitted"`.

> [accordion] KYC scaduto: "Kyc Expired"
>
> **Valore API:** `"Kyc Expired"`
>
> Il documento verificato durante la sessione ha **superato la propria data di scadenza**. Il trigger è tale data, non una finestra misurata a partire dall'approvazione, e non viene inviato alcun avviso in anticipo.
>
> * **Cosa fare:** Chiedere all'utente di ripetere la verifica con una nuova sessione. `status.updated` comunica il passaggio di stato, e il risultato della verifica dell'identità riporta un avviso `DOCUMENT_EXPIRED`.
> * **Controllato da:** **Expiration mode** del paese e del tipo di documento in *ID verification → Additional settings by country & document type*. **Reject expired** (il valore predefinito) monitora il documento, mentre **Allow expired** fa sì che la sessione non passi mai a questo stato.
> * **Nessuna transizione automatica.** Un revisore, oppure `PATCH /v3/session/{sessionId}/update-status/`, può comunque impostarla su `"Approved"`, `"Declined"` o `"Resubmitted"`.

***

## Transizioni di stato

| Da | A | Trigger |
| - | - | - |
| `"Not Started"` | `"In Progress"` | L'utente apre il link di verifica |
| `"Not Started"` | `"Expired"` | La TTL della sessione scade prima che l'utente apra il link |
| `"In Progress"` | `"Approved"` | Tutti i controlli automatici sono superati |
| `"In Progress"` | `"Declined"` | Uno o più controlli non sono superati |
| `"In Progress"` | `"In Review"` | I controlli segnalano avvisi che richiedono una revisione umana |
| `"In Progress"` | `"Awaiting User"` | Il passaggio delle persone chiave KYB è stato inviato; il genitore attende il completamento dei soggetti KYC figli |
| `"In Progress"` | `"Abandoned"` | L'utente non completa la verifica entro il tempo previsto |
| `"Awaiting User"` | `"Approved"` | Tutte le parti KYB richieste completano la verifica e i controlli aggregati sono superati |
| `"Awaiting User"` | `"Declined"` | Una parte richiesta viene rifiutata oppure il controllo sul registro KYB non è superato |
| `"Awaiting User"` | `"In Review"` | Il risultato KYB aggregato richiede una revisione manuale |
| `"In Review"` | `"Approved"` | Il revisore approva manualmente |
| `"In Review"` | `"Declined"` | Il revisore rifiuta manualmente |
| `"In Review"` | `"Resubmitted"` | Il revisore richiede che specifici passaggi vengano ripetuti |
| `"Declined"` | `"Resubmitted"` | Il revisore richiede che specifici passaggi vengano ripetuti |
| `"Approved"` | `"Resubmitted"` | Il revisore richiede che specifici passaggi vengano ripetuti |
| `"Approved"` | `"Declined"` | Il revisore o l'API imposta l'altra decisione |
| `"Declined"` | `"Approved"` | Il revisore o l'API imposta l'altra decisione |
| `"Abandoned"`, `"Kyc Expired"` | `"Approved"`, `"Declined"`, `"Resubmitted"` | Il revisore o l'API prende una decisione su una sessione terminata senza una decisione |
| `"Resubmitted"` | `"Abandoned"` | La finestra della sessione scade prima che la persona ripeta i passaggi |
| `"Resubmitted"` | `"Approved"` | I passaggi reinviati superano tutti i controlli |
| `"Resubmitted"` | `"Declined"` | I passaggi reinviati non superano i controlli |
| `"Resubmitted"` | `"In Review"` | I passaggi reinviati segnalano nuovi avvisi |
| `"Resubmitted"` (figlia KYB) | `"Awaiting User"` (genitore KYB) | Il genitore torna in stato di attesa finché la sessione figlia non completa la verifica |
| `"Approved"` | `"Kyc Expired"` | La data di scadenza del documento verificato viene superata (la modalità di scadenza è **Reject expired**) |

### Diagramma del ciclo di vita

```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"]
```

***

## Terminali e non terminali

| Categoria | Stati | Significato |
| - | - | - |
| **Deciso** | `"Approved"`, `"Declined"`, `"Kyc Expired"` | I controlli hanno prodotto una decisione e nulla la modifica da sola, tranne il passaggio da `"Approved"` a `"Kyc Expired"` quando la data di scadenza del documento verificato viene superata. Un revisore o l'endpoint di aggiornamento dello stato può ancora modificare la decisione. |
| **Non terminale** | `"Not Started"`, `"In Progress"`, `"Resubmitted"`, `"Awaiting User"` | Ancora attivi: in attesa di un'azione dell'utente, di sessioni figlie o di elaborazione. |
| **Azionabile** | `"In Review"` | Richiede un intervento manuale del tuo team. |
| **Inattivo** | `"Expired"`, `"Abandoned"` | Terminati senza una decisione di verifica. `"Expired"` non cambia mai; un revisore può ancora prendere una decisione su una sessione `"Abandoned"`. |

***

## Gestione degli stati nel tuo codice

Usa i webhook o l'[API Retrieve Session](https://docs.didit.me/it/sessions-api/retrieve-session.md) per reagire ai cambi di stato.

> [!WARNING]
>
> Gli stati sono **stringhe esatte, con distinzione tra maiuscole e minuscole e con spazi**. Ad esempio, `"In Review"` (non `"in_review"` o `"IN_REVIEW"`). Usa sempre l'uguaglianza stretta (`===`) nei confronti.

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

***

## Nuovo invio

Lo stato **Resubmitted** permette al tuo team di conformità di offrire agli utenti una seconda possibilità senza creare una nuova sessione.

**1. Il revisore avvia il nuovo invio**

Dalla Console, apri una sessione `In Review` o `Declined` e fai clic su **Richiedi un nuovo invio**. Seleziona i passaggi che devono essere ripetuti.

**2. I dati precedenti vengono archiviati**

Il sistema reimposta le funzionalità selezionate e contrassegna i dati precedenti come `previous_attempt`, conservando l'intera traccia di audit.

**3. L'utente riceve una notifica**

Se è disponibile un'email, l'utente riceve un'email localizzata con un link diretto per riprendere.

**4. L'utente ripete passaggi specifici**

L'utente ripete solo i passaggi segnalati, non l'intera verifica.

**5. Il sistema rivaluta**

Al termine, la sessione passa automaticamente a `"Approved"`, `"Declined"` o `"In Review"`.

### Payload del webhook del nuovo invio

```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` associa ogni `node_id` sottomesso di nuovo al codice di avviso del log più pertinente per quel passaggio (gli stessi codici che la [decisione](https://docs.didit.me/it/reference/data-models.md) riporta), così puoi mapparlo sul tuo testo. È anche il codice che la schermata del nuovo invio del flusso ospitato e l'email del nuovo invio localizzano per l'utente, tranne per gli avvisi che rivelerebbero un segnale di screening o di frode (duplicati, AML, blocklist, controlli tra organizzazioni, integrità della posizione e simili): in quei casi la persona vede un motivo generico, mentre `resubmit_info.reasons` nel tuo webhook riporta sempre il codice reale. Un passaggio senza avvisi registrati non ha alcuna voce.

### Quali funzionalità si possono reinviare

Qualsiasi funzionalità con uno stato non approvato: **Declined**, **In Review**, **Not Finished**, **Not Started** o **Expired**.

> [!TIP]
>
> Puoi richiedere un nuovo invio più volte sulla stessa sessione. Ogni ciclo archivia i dati del tentativo precedente, offrendoti una visibilità completa sulla cronologia di verifica dell'utente.

***

## Migliori pratiche

> [card] Monitora le sessioni in revisione
>
> Configura gli avvisi (email o Slack) nella tua Didit Console per ricevere una notifica quando le sessioni richiedono una revisione manuale.

> [card] Preferisci il nuovo invio
>
> Se il problema è risolvibile (foto sfocata, lato del documento errato), richiedi un nuovo invio invece di rifiutare. Questo migliora il tasso di conversione.

> [card] Monitora gli abbandoni
>
> Tassi elevati di sessioni abbandonate o scadute possono indicare attriti nell'esperienza utente. Valuta di modificare il TTL della sessione o di migliorare le indicazioni per l'utente.

> [card] Gestori idempotenti
>
> È possibile effettuare nuovi tentativi di consegna dei webhook. Usa `session_id` come chiave univoca per assicurarti di elaborare ogni cambio di stato una sola volta.

> [!WARNING]
>
> Verifica sempre le firme dei webhook prima di elaborare i payload. Didit fornisce tre metodi: `X-Signature`, `X-Signature-V2` (consigliato) e `X-Signature-Simple`, deprecato, che autentica solo la busta e mai il corpo `decision`. Vedi [Webhook](https://docs.didit.me/it/integration/webhooks.md#verifica-della-firma) per i dettagli.


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