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

# Modelli di dati e schemi JSON Didit

> Schemi JSON canonici di ogni oggetto report Didit: NFC, ID, Liveness, Face Match, AML, IP, POA, telefono, email, KYB, documenti, persone chiave.

## Panoramica

Ogni report per funzionalità segue la forma del serializzatore V3 definita in `service-didit-verification`. Lo stesso oggetto compare in tre punti, quindi lo schema che vedi qui è l'unica fonte di verità per tutti e tre:

* `GET /v3/session/{sessionId}/decision/`: ogni funzionalità viene restituita come array al plurale (`id_verifications[]`, `nfc_verifications[]`, `liveness_checks[]`, `face_matches[]`, `poa_verifications[]`, `phone_verifications[]`, `email_verifications[]`, `aml_screenings[]`, `ip_analyses[]`, `database_validations[]`, `questionnaire_responses[]`, `signatures[]`, `bank_verifications[]` (vedi [Metodi di verifica bancaria](https://docs.didit.me/it/core-technology/bank-verification/verification-methods.md#leggi-il-metodo-nel-risultato)), e gli equivalenti KYB `registry_checks[]`, `document_verifications[]`, `key_people_checks[]`).
* Payload dei webhook (`status.updated`, `data.updated`): stessa forma all'interno dell'envelope `decision`.
* API standalone: le risposte con un solo oggetto (Face Search, Age Estimation, Biometric Authentication) riutilizzano lo stesso insieme di campi.

> [!NOTE]
>
> V3 ha introdotto i workflow multi-istanza: ogni oggetto funzionalità contiene un `node_id` che collega il report al nodo del grafo del workflow che lo ha prodotto. Gli endpoint V2 (al singolare `kyc`, `face`, `aml`, ecc.) restano retrocompatibili, ma restituiscono solo la prima istanza.

## Campi comuni

Ogni oggetto report espone i seguenti campi:

| Campo | Tipo | Descrizione |
| - | - | - |
| `status` | string | Stato del ciclo di vita a livello di funzionalità: uno dei valori in [Enum dello stato](#riferimento-agli-enum-di-stato). Fonte: `common/config/choices.py:FeatureStatusChoices` (righe 343-348). Lo `status` di primo livello della sessione padre usa l'enum di sessione più ampio (`StatusChoices`, righe 106-117). |
| `node_id` | string \| null | Identificatore del nodo del grafo del workflow. Valorizzato per i workflow V3 multi-istanza; `null` per le sessioni legacy a funzionalità singola. |
| `warnings` | array di [oggetti avviso](#oggetto-avviso) | Segnali di rischio filtrati per questa funzionalità e per `node_id`. Restituiti da `Session.get_logs(...)` (`sessions/models/session.py:1611`). |

I campi media (`portrait_image`, `front_image`, `document_file`, …) sono URL prefirmati con un periodo di validità limitato: scaricali subito invece di salvare l'URL. Gli esempi li mostrano come `https://<media-host>/...`.

## Oggetto avviso

Restituito in ogni array `warnings[]`. Schema da `logs/serializers/log.py:8-65` (`LogV3Serializer`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `feature` | string (enum) | No | Quale funzionalità ha emesso l'avviso. Valori da `LogWarningChoices` (`common/config/choices.py:190-204`): `ID_VERIFICATION`, `NFC`, `LIVENESS`, `FACEMATCH`, `PROOF_OF_ADDRESS`, `PHONE`, `EMAIL`, `AML`, `LOCATION`, `DATABASE_VALIDATION`, `QUESTIONNAIRE`, `KYB_REGISTRY`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`. | `"ID_VERIFICATION"` |
| `risk` | string | No | Codice di rischio stabile (es. `DOCUMENT_EXPIRED`, `LOW_LIVENESS_SCORE`). Valori da `logs/choices.py:RiskChoices`. Usato come chiave nelle tabelle delle descrizioni. | `"DOCUMENT_EXPIRED"` |
| `additional_data` | object \| null | Sì | Contesto specifico del rischio (es. soglie di punteggio, campi corrispondenti). La forma varia in base al codice di rischio. | `{ "score": 42.1, "threshold": 70 }` |
| `log_type` | string (enum) | No | Uno tra `error`, `warning`, `information`. Da `LogTypeChoices` (`common/config/choices.py:207-210`). | `"error"` |
| `short_description` | string | No | Etichetta leggibile per il rischio. Da `logs/choices.py:RISK_SHORT_DESCRIPTIONS`. | `"Document expired"` |
| `long_description` | string | No | Spiegazione più lunga e leggibile, adatta alle superfici rivolte all'utente finale. Da `logs/choices.py:RISK_LONG_DESCRIPTIONS`. | `"The document's expiration date has passed, rendering it no longer valid for use."` |
| `node_id` | string \| null | Sì | Nodo del grafo del workflow a cui è stato associato l'avviso. `null` per i log V2 legacy senza `node_id`. | `"first_id_verification"` |

```json theme={null}
{
  "feature": "ID_VERIFICATION",
  "risk": "DOCUMENT_EXPIRED",
  "additional_data": null,
  "log_type": "error",
  "short_description": "Document expired",
  "long_description": "The document's expiration date has passed, rendering it no longer valid for use.",
  "node_id": "first_id_verification"
}
```

## Oggetti report

Le sezioni successive descrivono ciascun oggetto di report per funzionalità. Il testo dei titoli H3 è volutamente stabile, così che altre pagine possano collegarvisi direttamente.

### Verifica dell'identità

Viene restituito per ogni documento KYC/ID inviato da un utente. Compare come `id_verifications[]` in `GET /v3/session/{sessionId}/decision/` e all'interno del campo `kyc` delle risposte V2. Fonte: `kyc/serializers/kyc.py:383-414` (`IDVerificationV3Serializer`, che estende `IDVerificationV2Serializer` in `kyc/serializers/kyc.py:320-380`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | stringa | No | Vedi [Enum degli stati](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `document_type` | stringa | Sì | Classe del documento leggibile (`Passport`, `Identity Card`, `Driver's License`, `Residence Permit`, `Health Insurance Card`, `Tax Card`, `Social Security Card`, `Work Permit`, `Visa`, `Public Service Card`, `Birth Certificate`, `Firearm License`, `Other`). Fonte: `DOC_TYPE_MAPPING` (`common/config/choices.py:1275-1289`). | `"Passport"` |
| `document_subtype` | stringa | Sì | Codice del sottotipo di documento dal registro documenti di Didit, filtrato in base ai documenti accettati dalle impostazioni dei documenti del workflow. I documenti specifici di una regione includono la regione. Elenco completo dei codici: [Sottotipi di documento](https://docs.didit.me/it/core-technology/id-verification/document-subtypes-id-verification.md). | `"QUEENSLAND_DRIVER_LICENSE_GENERIC"` |
| `document_number` | stringa | Sì | Numero del documento estratto tramite OCR. | `"AB1234567"` |
| `personal_number` | stringa | Sì | Identificativo personale o nazionale estratto tramite OCR. | `"99999999R"` |
| `portrait_image` | stringa (URL) | Sì | URL prefirmato del ritaglio del volto. | `"https://<media-host>/.../portrait.jpg?..."` |
| `front_image` | stringa (URL) | Sì | URL prefirmato del fronte del documento ripulito. | `"https://<media-host>/.../front.jpg?..."` |
| `front_video` | stringa (URL) | Sì | URL prefirmato del video di acquisizione del fronte (quando disponibile). | `"https://<media-host>/.../front.mp4?..."` |
| `back_image` | stringa (URL) | Sì | URL prefirmato del retro del documento ripulito. | `"https://<media-host>/.../back.jpg?..."` |
| `back_video` | stringa (URL) | Sì | URL prefirmato del video di acquisizione del retro. | `null` |
| `full_front_image` | stringa (URL) | Sì | Acquisizione non ritagliata (a fotogramma intero) del fronte. | `"https://<media-host>/.../full_front.jpg?..."` |
| `full_back_image` | stringa (URL) | Sì | Acquisizione non ritagliata (a fotogramma intero) del retro. | `null` |
| `front_image_camera_front` | stringa (URL) | Sì | Immagine della fotocamera frontale scattata nello stesso momento del fronte del documento. | `null` |
| `back_image_camera_front` | stringa (URL) | Sì | Immagine della fotocamera frontale scattata nello stesso momento del retro del documento. | `null` |
| `front_image_camera_front_face_match_score` | float (0-100) | Sì | Somiglianza tra il ritratto del documento e l'acquisizione della fotocamera frontale. | `null` |
| `back_image_camera_front_face_match_score` | float (0-100) | Sì | Come sopra, ma per l'acquisizione del retro. | `null` |
| `document_selfie_face_matches` | array | Sì | Sessioni precedenti o voci della blocklist facciale che corrispondono al selfie scattato durante l'acquisizione del documento. Stesso formato delle voci di `liveness_checks[].matches`. `null` quando la ricerca non è stata eseguita, `[]` quando non c'è stata alcuna corrispondenza. | `null` |
| `front_image_quality_score` | oggetto | Sì | Metriche di qualità dell'immagine del fronte: punteggi da 0 a 100 (`focus_score`, `brightness_score`, `resolution_score`, `overall_score`), oltre a `brightness_issue` (`ok`, `too_dark`, `too_bright`) e `is_document_fully_visible` (booleano). | `{ "focus_score": 91.0, "overall_score": 88.5 }` |
| `back_image_quality_score` | oggetto | Sì | Stessa struttura di `front_image_quality_score`. | `null` |
| `date_of_birth` | stringa (YYYY-MM-DD) | Sì | Data di nascita estratta tramite OCR. | `"1990-05-12"` |
| `age` | intero | Sì | Età calcolata in anni al momento dell'estrazione. | `35` |
| `expiration_date` | stringa (YYYY-MM-DD) | Sì | Data di scadenza del documento. | `"2032-05-11"` |
| `date_of_issue` | stringa (YYYY-MM-DD) | Sì | Data di rilascio del documento. | `"2022-05-11"` |
| `issuing_state` | stringa (ISO 3166-1 alpha-3) | Sì | Codice del paese di emissione. | `"ESP"` |
| `issuing_state_name` | stringa | Sì | Nome localizzato del paese di emissione. | `"Spain"` |
| `first_name` | stringa | Sì | Nome o nomi di battesimo estratti tramite OCR. | `"María"` |
| `last_name` | stringa | Sì | Cognome o cognomi estratti tramite OCR. | `"García López"` |
| `full_name` | stringa | Sì | Nome completo normalizzato (fornito dal fornitore). | `"María García López"` |
| `gender` | stringa | Sì | `M`, `F` o altro valore fornito dal fornitore. | `"F"` |
| `address` | stringa | Sì | Riga di indirizzo grezza estratta tramite OCR. | `"Calle Mayor 1, 28001 Madrid"` |
| `formatted_address` | stringa | Sì | Indirizzo geocodificato e formattato (quando analizzabile). | `"Calle Mayor 1, 28001 Madrid, Spain"` |
| `parsed_address` | oggetto | Sì | Indirizzo strutturato e geocodificato: `street_1`, `street_2`, `city`, `region`, `country`, `postal_code`, `address_type`, `formatted_address`, `document_location` (`{latitude, longitude}`), `raw_results`, `is_best_match`. Fonte: `kyc/utils/address.py:147-197`. | `{ "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001", "country": "ES" }` |
| `place_of_birth` | stringa | Sì | Luogo di nascita estratto tramite OCR. | `"Madrid"` |
| `marital_status` | stringa | Sì | Quando estraibile. | `null` |
| `nationality` | stringa (ISO 3166-1 alpha-3) | Sì | Nazionalità estratta tramite OCR. | `"ESP"` |
| `extra_fields` | oggetto | Sì | Campi specifici del tipo di documento non coperti dallo schema canonico (ad esempio le categorie della patente di guida). | `{ "DL Class": "B" }` |
| `mrz` | oggetto | Sì | Campi MRZ analizzati, quando presenti (`document_number`, `birth_date`, `expiry_date`, `surname`, `given_names`, …). | `{ "document_number": "AB1234567", "surname": "GARCIA", "given_names": "MARIA" }` |
| `extra_files` | array di stringhe (URL) | No | URL prefirmati di eventuali file aggiuntivi caricati. | `[]` |
| `matches` | array di oggetti | No | Corrispondenze del documento tra sessioni diverse. Ogni elemento: `{ session_id, session_number, vendor_data, verification_date, user_details: { name, document_type, document_number }, status, is_blocklisted, api_service, front_image_url }`. `front_image_url` è prefirmato. | `[]` |
| `verification_method` | string | No | Metodo di [Verifica dell'identità](https://docs.didit.me/it/core-technology/id-verification/verification-methods.md) che ha prodotto questa riga: `document`, `id_lookup` o `wallet`. Sempre `document` per un documento fotografato, incluse tutte le sessioni create prima che esistessero gli altri metodi. | `"id_lookup"` |
| `assurance` | string | No | Livello di garanzia derivato da `verification_method`: `documentary`, `data_match` o `cryptographic`. | `"data_match"` |
| `wallet_provider` | string \| null | Sì | ID del wallet nel catalogo quando un wallet ha prodotto questa riga (`mitid`, `bankid_se`, `itsme`, ...). `null` altrimenti. | `"mitid"` |
| `fallback_from` | object \| null | Sì | Motivo per cui un metodo diverso dal documento ha concluso il passaggio di verifica dell'identità: `{ method, reason, action }`. Viene impostato quando una ricerca o un accesso con wallet non va a buon fine: sulla riga rifiutata quando l'impostazione del paese era `decline` (`action: "decline"`), e sulla verifica del documento con cui l'utente prosegue quando era `fallback_to_document` (`action: "fallback_to_document"`). `null` quando non è registrato alcun precedente errore di un metodo diverso dal documento. | `{ "method": "id_lookup", "reason": "no_match", "action": "decline" }` |
| `id_lookup` | object \| null | Sì | Evidenza della fonte, presente solo quando `verification_method` è `id_lookup`: `source` (la fonte esatta interrogata: nella maggior parte dei paesi un registro governativo, in alcuni un file di un ente di credito o di registri residenziali), `checked_at`, `attempts`, `max_attempts`, `outcome` (`match`, `partial_match`, `no_match`, `provider_error`, `format_rejected`), `comparison[]` (`{ field, label, provided, record, result }`; `field` è uno tra `identification_number`, `full_name`, `date_of_birth`, `address`, e `result` è `match`, `partial` o `no_match`; le release precedenti possono includere una riga `provider` con `error`), `source_errors[]` (staging attuale: diagnostica separata per fonte; confermare il rollout in produzione), `registry_portrait` (URL presigned, solo per le fonti che ne restituiscono uno) e `face_match_score`. | vedi sotto |
| `wallet_verification` | object \| null | Sì | Evidenza della credenziale, presente solo quando `verification_method` è `wallet`: `provider`, `provider_name`, `issuing_authority`, `issuing_country`, `credential_type`, `level_of_assurance` (`low`, `substantial`, `high`), `verified_at`, `signature_valid`, `attributes` (ciò che il wallet ha condiviso), `portrait` (URL presigned quando il wallet ne condivide uno) e `face_match_score`. | vedi sotto |
| `document_liveness` | object \| null | Sì | Punteggi di vitalità del documento per tipo di frode (`portrait_replace`, `printed_copy`, `screen_replay`), riportati indipendentemente dal fatto che sia scattato un avviso. Ciascuno con: `score` (0-100, più alto = più probabilmente autentico; il valore più basso, cioè quello usato dalla decisione), `front`, `back`, `decline_threshold`, `review_threshold`, `bucket` (`approve`, `review`, `decline` o `null`). Soglie e bucket sono salvati al momento della valutazione; tutti e tre sono `null` quando le evidenze storiche di valutazione non sono disponibili, mentre i punteggi memorizzati restano visibili. `null` quando il controllo non è stato eseguito. Vedi [Punteggi di vitalità del documento](https://docs.didit.me/it/core-technology/id-verification/report-id-verification.md#punteggi-del-rilevamento-della-vitalità-del-documento). Solo V3. | `{ "portrait_replace": { "score": 96.46, "bucket": "approve" } }` |
| `node_id` | string \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_id_verification"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |
| `region` | string | Sì | Regione o stato del paese di emissione, quando il documento ne indica uno. | `"CA"` |
| `extracted_data` | object | Sì | Istantanea dei dati estratti dal documento che la persona ha visto per la revisione, conservata accanto ai valori confermati per poterli confrontare. `null` quando alla persona non è stato chiesto di rivedere. | |
| `barcodes` | array di oggetti | No | Dati letti dai codici a barre del documento, una voce per codice a barre con `type`, `position`, `data`, `data_raw` e `side`. `[]` quando non ce ne sono. | `[]` |

```json theme={null}
{
  "status": "Approved",
  "document_type": "Passport",
  "document_subtype": "PASSPORT_GENERIC",
  "document_number": "AB1234567",
  "personal_number": "99999999R",
  "portrait_image": "https://<media-host>/.../portrait.jpg?signature=...",
  "front_image": "https://<media-host>/.../front.jpg?signature=...",
  "front_video": null,
  "back_image": "https://<media-host>/.../back.jpg?signature=...",
  "back_video": null,
  "full_front_image": "https://<media-host>/.../full_front.jpg?signature=...",
  "full_back_image": null,
  "front_image_camera_front": null,
  "back_image_camera_front": null,
  "front_image_camera_front_face_match_score": null,
  "back_image_camera_front_face_match_score": null,
  "front_image_quality_score": {
    "focus_score": 91.0,
    "brightness_score": 88.0,
    "brightness_issue": "ok",
    "is_document_fully_visible": true,
    "resolution_score": 95.0,
    "overall_score": 88.5
  },
  "back_image_quality_score": null,
  "date_of_birth": "1990-05-12",
  "age": 35,
  "expiration_date": "2032-05-11",
  "date_of_issue": "2022-05-11",
  "issuing_state": "ESP",
  "issuing_state_name": "Spain",
  "first_name": "María",
  "last_name": "García López",
  "full_name": "María García López",
  "gender": "F",
  "address": "Calle Mayor 1, 28001 Madrid",
  "formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "parsed_address": { "street_1": "Calle Mayor 1", "street_2": null, "city": "Madrid", "region": "Madrid", "postal_code": "28001", "country": "ES", "address_type": "Calle" },
  "place_of_birth": "Madrid",
  "marital_status": null,
  "nationality": "ESP",
  "extra_fields": {},
  "mrz": {
    "document_number": "AB1234567",
    "surname": "GARCIA",
    "given_names": "MARIA",
    "birth_date": "900512",
    "expiry_date": "320511"
  },
  "extra_files": [],
  "matches": [],
  "node_id": "first_id_verification",
  "verification_method": "document",
  "assurance": "documentary",
  "wallet_provider": null,
  "fallback_from": null,
  "id_lookup": null,
  "wallet_verification": null,
  "document_liveness": {
    "portrait_replace": {
      "score": 96.46,
      "front": 96.46,
      "back": 98.2,
      "decline_threshold": 35,
      "review_threshold": 70,
      "bucket": "approve"
    },
    "printed_copy": {
      "score": 91.2,
      "front": 91.2,
      "back": 93.7,
      "decline_threshold": 35,
      "review_threshold": 77,
      "bucket": "approve"
    },
    "screen_replay": {
      "score": 99.9,
      "front": 99.9,
      "back": 99.5,
      "decline_threshold": 30,
      "review_threshold": 70,
      "bucket": "approve"
    }
  },
  "warnings": []
}
```

Lo stesso oggetto con un metodo diverso dal documento. Cambiano solo le chiavi specifiche del metodo: tutto ciò che di norma viene compilato dalla lettura del documento viene invece compilato dal record del registro o dagli attributi del wallet, e le chiavi che non si applicano sono `null`.

```json theme={null}
{
  "status": "Approved",
  "issuing_state": "ZAF",
  "first_name": "Thabo",
  "last_name": "Mokoena",
  "full_name": "Thabo Mokoena",
  "date_of_birth": "1991-06-15",
  "personal_number": "9106155043088",
  "node_id": "first_id_verification",
  "verification_method": "id_lookup",
  "assurance": "data_match",
  "wallet_provider": null,
  "fallback_from": null,
  "id_lookup": {
    "source": "Department of Home Affairs",
    "checked_at": "2026-09-04T09:12:44Z",
    "attempts": 1,
    "max_attempts": 2,
    "outcome": "match",
    "comparison": [
      { "field": "identification_number", "label": "ID number", "provided": "9106155043088", "record": "9106155043088", "result": "match" },
      { "field": "full_name", "label": "Full name", "provided": "Thabo Mokoena", "record": "Thabo Mokoena", "result": "match" },
      { "field": "date_of_birth", "label": "Date of birth", "provided": "1991-06-15", "record": "1991-06-15", "result": "match" }
    ],
    "registry_portrait": "https://<media-host>/.../registry_portrait.jpg?signature=...",
    "face_match_score": 96.4
  },
  "wallet_verification": null,
  "warnings": []
}
```

```json theme={null}
{
  "status": "Approved",
  "issuing_state": "DNK",
  "first_name": "Freja",
  "last_name": "Nielsen",
  "full_name": "Freja Nielsen",
  "date_of_birth": "1988-03-02",
  "node_id": "first_id_verification",
  "verification_method": "wallet",
  "assurance": "cryptographic",
  "wallet_provider": "mitid",
  "fallback_from": null,
  "id_lookup": null,
  "wallet_verification": {
    "provider": "mitid",
    "provider_name": "MitID",
    "issuing_authority": "Danish Agency for Digital Government",
    "issuing_country": "DNK",
    "credential_type": "person_identification",
    "level_of_assurance": "substantial",
    "verified_at": "2026-09-04T09:12:44Z",
    "signature_valid": true,
    "attributes": {
      "full_name": "Freja Nielsen",
      "date_of_birth": "1988-03-02",
      "cpr_alias": "b0f1c2d3-e4f5-4678-9abc-def012345678"
    },
    "portrait": null,
    "face_match_score": null
  },
  "warnings": []
}
```

### Verifica NFC

Restituito per ogni lettura del chip su un documento d'identità: un chip ePassport ICAO 9303 o eID, oppure una lettura della My Number Card giapponese tramite JPKI (`chip_protocol: "jpki"`). Compare come `nfc_verifications[]` in `GET /v3/session/{sessionId}/decision/` (uno per record KYC principale). Fonte: `kyc/serializers/epassport.py:121-139` (`NFCV3Serializer`, estende `NFCV2Serializer` in `kyc/serializers/epassport.py:83-118`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Vedi [Enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `portrait_image` | string (URL) | Sì | URL presigned dell'immagine del volto estratta dal chip. | `"https://<media-host>/.../nfc_portrait.jpg?..."` |
| `signature_image` | string (URL) | Sì | URL presigned dell'immagine della firma estratta dal chip (quando è memorizzata sul chip). | `null` |
| `chip_data` | object | Sì | Dati personali analizzati dai Data Group del chip, appiattiti (`kyc/utils/epassport.py:165-212`): `dgs` (Data Group letti), `surname`, `name`, `country`, `nationality`, `birth_date` (`YYYY-MM-DD`), `expiry_date` (`YYYY-MM-DD`), `sex` (`M`/`F`), `document_type` (codice del documento MRZ), `document_number`, `optional_data`, cifre di controllo MRZ (`birth_date_hash`, `expiry_date_hash`, `document_number_hash`, `optional_data_hash`, `final_hash`), `mrz_string`, `mrz_type` (`TD1`/`TD2`/`TD3`); più `place_of_birth` e `address` (e `full_name` / `full_name_non_latin` per i nomi non latini) quando il chip contiene il DG11: in caso contrario queste chiavi sono assenti. `null` quando il passaggio NFC è stato saltato. | `{ "document_number": "AB1234567", "name": "MARIA" }` |
| `authenticity` | object | Sì | `{ sod_integrity, dg_integrity }`; `null` per una lettura JPKI. `sod_integrity` verifica che la firma del Document Security Object (SOD) risalga a una CSCA valida del paese di emissione (e che il DSC non sia revocato né scaduto); `dg_integrity` verifica che l'hash di ciascun Data Group corrisponda al SOD. Entrambi `true` significano che il chip è autentico e non manomesso. | `{ "sod_integrity": true, "dg_integrity": true }` |
| `certificate_summary` | object | Sì | Riepilogo del certificato del firmatario del documento (`kyc/utils/epassport.py:338-348`): `issuer`, `subject`, `serial_number` (intero), `not_valid_before`, `not_valid_after` (`YYYY-MM-DD HH:MM:SS`), più un oggetto `validation` `{ csca_verified, dsc_revoked, dsc_expired, csca_expired }` (`kyc/views/epassport.py:86`). | `{ "issuer": "Common Name: CSCA SPAIN, Country: ES", "not_valid_after": "2031-02-18 10:21:11" }` |
| `node_id` | string \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_nfc"` |
| `is_nfc_skipped` | boolean | No | `true` quando questo passaggio NFC è stato saltato esplicitamente invece di essere letto; `skip_reason` ne indica il motivo. | `false` |
| `skip_reason` | string | Sì | Motivo per cui il passaggio è stato saltato: impostato solo quando `is_nfc_skipped` è `true`. Uno dei seguenti valori: `USER_SKIPPED`, `DOCUMENT_WITHOUT_CHIP`, `CHIP_CERTIFICATE_UNAVAILABLE`, `DEVICE_WITHOUT_NFC`, `INTEGRATION_WITHOUT_NFC_ACCESS`, `MRZ_KEY_UNAVAILABLE`, `JPKI_UNAVAILABLE`; vedi [Motivi di salto](https://docs.didit.me/it/core-technology/nfc-verification/warnings-nfc-verification.md#motivi-di-esclusione). Il payload della decisione contiene anche un `nfc_skip_reason` a livello di sessione, con la stessa tassonomia, che copre i passaggi NFC ignorati prima della creazione di qualsiasi report. | `null` |
| `chip_protocol` | string | No | Modalità di lettura del chip: `icao` (chip ePassport o eID conforme a ICAO 9303) oppure `jpki` (My Number Card giapponese). Per `jpki`, `portrait_image`, `signature_image`, `chip_data`, `authenticity` e `certificate_summary` sono `null`. Impostato anche sui passaggi saltati. | `"icao"` |
| `jpki` | object | Sì | Cosa ha dimostrato la lettura di una My Number Card: `certificate_types`, `chain_valid`, `signature_valid`, `revocation_status` (`good`, `revoked` o `unchecked`), `ca_generation`, `certificate_expires_at`, `certificates[]`, `attributes` (nome, data di nascita, sesso e indirizzo dal certificato di firma), `attributes_match_ocr` e `mismatched_attributes`. Non include mai i certificati, i relativi numeri di serie o le firme. `null` per i chip ICAO, per i passaggi saltati e quando il passaggio si è chiuso senza alcuna lettura della carta. Vedi [Campi JPKI](https://docs.didit.me/it/core-technology/nfc-verification/report-nfc-verification.md#campi-jpki). | `null` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

```json theme={null}
{
  "status": "Approved",
  "portrait_image": "https://<media-host>/.../nfc_portrait.jpg?signature=...",
  "signature_image": null,
  "chip_data": {
    "dgs": ["DG1", "DG2", "DG11"],
    "surname": "GARCIA LOPEZ",
    "name": "MARIA",
    "country": "ESP",
    "nationality": "ESP",
    "birth_date": "1990-05-12",
    "expiry_date": "2032-05-11",
    "sex": "F",
    "document_type": "P",
    "document_number": "AB1234567",
    "optional_data": "",
    "birth_date_hash": "4",
    "expiry_date_hash": "7",
    "document_number_hash": "3",
    "optional_data_hash": "",
    "final_hash": "8",
    "mrz_string": "P<ESPGARCIA<LOPEZ<<MARIA<<<<<<<<<<<<<<<<<<<<AB1234567ESP9005124F3205117<<<<<<<<<<<<<<08",
    "mrz_type": "TD3",
    "place_of_birth": "MADRID",
    "address": "CALLE MAYOR 1, MADRID"
  },
  "authenticity": { "sod_integrity": true, "dg_integrity": true },
  "certificate_summary": {
    "issuer": "Common Name: CSCA SPAIN, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
    "subject": "Common Name: DS n-eID SPAIN 2, Organizational Unit: PASSPORT, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
    "serial_number": 118120836164494130086420187336801405660,
    "not_valid_before": "2020-11-18 10:21:11",
    "not_valid_after": "2031-02-18 10:21:11",
    "validation": {
      "csca_verified": true,
      "dsc_revoked": false,
      "dsc_expired": false,
      "csca_expired": false
    }
  },
  "node_id": "first_nfc",
  "is_nfc_skipped": false,
  "skip_reason": null,
  "chip_protocol": "icao",
  "jpki": null,
  "warnings": []
}
```

### Rilevamento della vitalità

Restituito per ogni sessione di rilevamento della vitalità. Compare come `liveness_checks[]` in `GET /v3/session/{sessionId}/decision/`. Fonte: `face/serializers/face.py:301-320` (`LivenessV3Serializer`, estende `LivenessV2Serializer` in `face/serializers/face.py:216-298`).

| Campo | Tipo | Nullabile | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Vedi [Enum degli stati](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `method` | string (enum) | Sì | `ACTIVE_3D`, `FLASHING` oppure `PASSIVE` (`LivenessMethodChoices`, `common/config/choices.py:514-517`). La modalità passiva viene eseguita quando le sessioni desktop sono consentite e l'utente si trova su desktop. | `"PASSIVE"` |
| `score` | float (0-100) | Sì | Confidenza del rilevamento della vitalità, arrotondata a 2 decimali. | `92.41` |
| `reference_image` | string (URL) | Sì | URL prefirmato del ritaglio del volto di riferimento dell'utente. | `"https://<media-host>/.../reference.jpg?..."` |
| `video_url` | string (URL) | Sì | URL prefirmato del video di vitalità (solo modalità attiva). | `"https://<media-host>/.../liveness.webm?..."` |
| `age_estimation` | float | Sì | Età stimata (in anni) del volto più grande nell'immagine di riferimento. | `34.2` |
| `matches` | array di oggetti | No | Corrispondenze facciali tra sessioni. Ogni elemento: `{ session_id, session_number, similarity_percentage, vendor_data, vendor_user_id, biometric_template_id, verification_date, user_details: { full_name, document_type, document_number }, match_image_url, status, is_blocklisted, is_allowlisted, api_service, source }`. `source` è `session`, `imported`, `list_entry` o `retained_template`. Una corrispondenza con modello conservato ha `vendor_user_id`, `vendor_data` e `biometric_template_id`; i suoi campi relativi alla sessione, all'immagine, ai dettagli dell'identità, allo stato e al servizio API sono `null`. | `[]` |
| `face_quality` | float (0-100) | Sì | Punteggio di qualità del volto per il rilevamento della vitalità passiva (normalizzato in percentuale). | `87.50` |
| `face_luminance` | float (0-100) | Sì | Punteggio di luminanza del volto per il rilevamento della vitalità passiva (normalizzato da 0-255 a una percentuale). | `54.12` |
| `node_id` | string \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_liveness"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

```json theme={null}
{
  "status": "Approved",
  "method": "PASSIVE",
  "score": 92.41,
  "reference_image": "https://<media-host>/.../reference.jpg?signature=...",
  "video_url": null,
  "age_estimation": 34.2,
  "matches": [],
  "face_quality": 87.50,
  "face_luminance": 54.12,
  "node_id": "first_liveness",
  "warnings": []
}
```

### Confronto facciale

Restituito per ogni confronto facciale (tipicamente il volto dell'utente rilevato durante il controllo di vitalità, confrontato con il ritratto sul documento). Compare come `face_matches[]` in `GET /v3/session/{sessionId}/decision/`. Fonte: `face/serializers/face.py:367-389` (`FaceMatchV3Serializer`, estende `FaceMatchV2Serializer` in `face/serializers/face.py:323-364`).

| Campo | Tipo | Nullabile | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Vedi [Enum degli stati](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `score` | float (0-100) | Sì | Somiglianza, arrotondata a 2 decimali. Quando il provider restituisce solo un `unmatched_faces[].Confidence`, questo valore viene convertito in `100 - confidence`. | `97.83` |
| `source_image_session_id` | string (UUID) | Sì | La sessione il cui ritratto memorizzato ha fornito l'immagine di origine (di riferimento): impostato nei flussi basati sul ritratto (autenticazione biometrica, oppure un ritratto fornito alla creazione della sessione). `null` quando il riferimento è il ritratto del documento della stessa sessione. | `null` |
| `source_image` | string (URL) | Sì | URL prefirmato dell'immagine di origine (di riferimento), di solito il ritratto del documento oppure il ritratto memorizzato nei flussi di autenticazione biometrica. | `"https://<media-host>/.../source.jpg?..."` |
| `target_image` | string (URL) | Sì | URL prefirmato dell'immagine di destinazione (volto dal vivo) acquisita durante il rilevamento della vitalità. | `"https://<media-host>/.../target.jpg?..."` |
| `node_id` | string \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_face_match"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |
| `face_coverage` | object | Sì | Indica se `eyes`, `mouth` e `face` sono coperti nell'immagine acquisita. Ogni regione ha `covered`, `calibrated` e `visibility_score`; `calibrated: false` indica la presenza di ombre, che non attiva alcun avviso. Restituito solo da `GET /v3/session/{sessionId}/decision/`, mai nei payload dei webhook. | `{ "eyes": { "covered": false, "calibrated": true, "visibility_score": 0.98 } }` |

```json theme={null}
{
  "status": "Approved",
  "score": 97.83,
  "source_image_session_id": null,
  "source_image": "https://<media-host>/.../source.jpg?signature=...",
  "target_image": "https://<media-host>/.../target.jpg?signature=...",
  "node_id": "first_face_match",
  "warnings": []
}
```

### Ricerca facciale

Restituito dall'API autonoma di Ricerca facciale (`POST /v3/face-search/`). Ricerca facciale non compare mai come array plurale in `/v3/session/{sessionId}/decision/`. Quando viene salvata con `save_api_request=true`, la sessione compare lì come voce `FACE_SEARCH` in `features[]`, insieme a un elemento `liveness_checks[]` che contiene le `matches` salvate. Fonti: `apis/serializers/face_search.py:8-79` (`FaceSearchResponseSerializer`, che incapsula `FaceSearchDetailsSerializer`); i dizionari delle corrispondenze sono costruiti in `face/utils/utils.py:869-884`.

Risposta di primo livello:

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `request_id` | stringa (UUID) | No | L'id della sessione salvata quando `save_api_request=true` (utilizzabile con `GET /v3/session/{sessionId}/decision/`); altrimenti un UUID di correlazione temporaneo. | `"4a1c2c4e-8b1b-4d6a-91b5-ee9a1f3a2c7f"` |
| `face_search` | oggetto | No | Il payload dei dettagli della ricerca: vedi i campi seguenti. | - |
| `vendor_data` | stringa | Sì | `vendor_data` ripreso dalla richiesta. | `null` |
| `metadata` | oggetto | Sì | `metadata` ripreso dalla richiesta. | `null` |
| `created_at` | stringa (ISO 8601) | No | Timestamp lato server della richiesta. | `"2026-06-12T01:04:42.763237+00:00"` |

Oggetto `face_search`:

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | stringa | No | `Declined` solo quando si attiva un avviso `FACE_IN_BLOCKLIST` o `POSSIBLE_FACE_IN_BLOCKLIST`; `Approved` in tutti gli altri casi. Le sole corrispondenze duplicate non causano mai un rifiuto (`apis/views/face_search.py:242-248`). | `"Approved"` |
| `total_matches` | intero | No | Numero di corrispondenze restituite in `matches[]` (0–5). | `1` |
| `matches` | array di [oggetti di corrispondenza di Ricerca facciale](#oggetto-di-corrispondenza-di-ricerca-facciale) | No | Fino a 5 corrispondenze sopra la soglia minima di somiglianza, ordinate per somiglianza decrescente (prima le voci in blocklist, con `search_type=blocklisted_or_approved`). | `[…]` |
| `user_image` | oggetto | No | Risultato del rilevamento per l'immagine inviata: `{ entities: [{ bbox, confidence }], best_angle }`, con un'entità per ogni volto rilevato. | `{ "entities": [{ "bbox": [40, 40, 120, 120], "confidence": 0.73 }], "best_angle": 0 }` |
| `warnings` | array di oggetti | No | Forma ridotta degli avvisi per questa API autonoma, senza `node_id`. Il contratto del serializer dichiara `{ risk, additional_data, log_type, short_description, long_description }` (`apis/serializers/face_search.py:49-54`); il payload a runtime contiene anche `feature`, sempre `"LIVENESS"` (`apis/views/face_search.py:332-341`). | `[]` |

#### Oggetto di corrispondenza di Ricerca facciale

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `session_id` | stringa (UUID) | Sì | La sessione di verifica corrispondente. `null` quando `source` è `imported`, `list_entry` o `retained_template`. | `"a3f2a6f1-…"` |
| `session_number` | intero | Sì | Numero leggibile nella console della sessione corrispondente; `null` per le corrispondenze che non sono sessioni. | `1024` |
| `similarity_percentage` | float (0-100) | No | Somiglianza tra il volto inviato e il volto corrispondente. | `96.42` |
| `source` | stringa (enum) | No | Da dove è stato registrato il volto corrispondente: `session` (sessione di verifica o chiamata autonoma salvata), `imported` (caricamento diretto del volto nel profilo utente), `list_entry` (volto associato a una lista), `retained_template` ([modello biometrico](https://docs.didit.me/it/management-api/biometric-templates/overview.md) senza immagine, conservato dopo l'eliminazione della sessione di origine). | `"session"` |
| `vendor_data` | stringa | Sì | Il `vendor_data` della sessione corrispondente, oppure quello dell'utente collegato per le corrispondenze `imported` e `retained_template`. | `"user-12345"` |
| `vendor_user_id` | stringa (UUID) | Sì | L'utente collegato. `null` per le corrispondenze `list_entry` e per le sessioni senza utente. | `"2f7c1a9e-…"` |
| `biometric_template_id` | stringa (UUID) | Sì | Il modello conservato che ha trovato corrispondenza. Valorizzato solo per le corrispondenze `retained_template`; usalo con `GET`/`DELETE /v3/biometric-templates/{id}/`. | `null` |
| `verification_date` | stringa (ISO 8601) | Sì | Quando il volto corrispondente è stato acquisito, oppure quando un `retained_template` è stato conservato; `null` per le corrispondenze `list_entry`. | `"2024-11-04T09:14:02Z"` |
| `user_details` | oggetto | Sì | `{ full_name, document_type, document_number }` dalla verifica del documento della sessione corrispondente. Per le corrispondenze `imported` è valorizzato solo `full_name`. `null` quando non esistono dati identificativi, e sempre `null` per le corrispondenze `retained_template`. | `{ "full_name": "María García López", "document_type": "Passport", "document_number": "AB1234567" }` |
| `match_image_url` | stringa (URL) | Sì | Volto di riferimento dell'utente corrispondente: URL prefirmato quando `save_api_request=true`, altrimenti percorso di storage grezzo. Sempre `null` per le corrispondenze `retained_template`, che non contengono immagini. | `"https://<media-host>/.../matched.jpg?..."` |
| `status` | stringa | Sì | Lo stato di verifica della sessione corrispondente (vedi [enum dello stato](#riferimento-agli-enum-di-stato)); `null` per le corrispondenze che non sono sessioni. | `"Approved"` |
| `is_blocklisted` | booleano | No | Indica se il volto corrispondente è nella tua blocklist di volti. Sempre `false` per le corrispondenze `retained_template`; un volto in blocklist viene segnalato separatamente come corrispondenza `list_entry`. | `false` |
| `is_allowlisted` | booleano | No | Indica se il volto corrispondente è in una delle tue allowlist. | `false` |
| `api_service` | stringa (enum) | Sì | Tipo di API autonoma in maiuscolo della sessione corrispondente (es. `PASSIVE_LIVENESS`, `FACE_MATCH`); `null` per le sessioni di workflow e per le corrispondenze che non sono sessioni. | `null` |

```json theme={null}
{
  "request_id": "4a1c2c4e-8b1b-4d6a-91b5-ee9a1f3a2c7f",
  "face_search": {
    "status": "Approved",
    "total_matches": 1,
    "matches": [
      {
        "session_id": "a3f2a6f1-1c1c-4eec-8b69-1c1c2f3a2c7f",
        "session_number": 1024,
        "similarity_percentage": 96.42,
        "source": "session",
        "vendor_data": "user-12345",
        "verification_date": "2024-11-04T09:14:02Z",
        "user_details": {
          "full_name": "María García López",
          "document_type": "Passport",
          "document_number": "AB1234567"
        },
        "match_image_url": "https://<media-host>/.../matched.jpg?signature=...",
        "status": "Approved",
        "is_blocklisted": false,
        "is_allowlisted": false,
        "api_service": null
      }
    ],
    "user_image": {
      "entities": [
        {
          "bbox": [40, 40, 120, 120],
          "confidence": 0.732973
        }
      ],
      "best_angle": 0
    },
    "warnings": []
  },
  "vendor_data": null,
  "metadata": null,
  "created_at": "2026-06-12T01:04:42.763237+00:00"
}
```

### Screening AML

Restituito per ogni entità sottoposta a screening. Compare come `aml_screenings[]` in `GET /v3/session/{sessionId}/decision/`, sia per le sessioni KYC sia per quelle KYB. Fonte: `aml/serializers/aml.py:63-85` (`AMLV3Serializer`, che estende `AMLV2Serializer` in `aml/serializers/aml.py:28-60`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | stringa | No | Vedi [enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `total_hits` | intero | No | Numero di riscontri di screening (sempre presente, con valore predefinito `0`). | `2` |
| `entity_type` | stringa (enum) | Sì | `person` o `company` (`EntityTypeChoices`, `common/config/choices.py:675-677`). | `"person"` |
| `hits` | array di oggetti | No | Una voce per ogni riscontro. Campi principali: `id`, `caption`, `match` (booleano), `target` (booleano \| null: indica se l'entità è il bersaglio diretto della voce in lista), `match_score` (float 0-100, grado di confidenza sull'identità), `risk_score` (float 0-100, rischio dell'entità), `score` (float 0-1, deprecato), `datasets[]` (es. `PEP`, `PEP Level 1`-`4`, `Sanctions`, `Adverse Media`, `Warnings and Regulatory Enforcement`, `Fitness and Probity`), `properties` (nomi, alias, date di nascita, ...), `features`, `url`, `first_seen`, `last_seen`, `rca_name`, `risk_view`, `score_breakdown`, `pep_matches`, `sanction_matches`, `warning_matches`, `adverse_media_matches`, `adverse_media_details`, `linked_entities`, `additional_information`, e `review_status` (`Unreviewed`, `Confirmed Match`, `False Positive`, `Inconclusive`; modificabile tramite l'endpoint di aggiornamento dello stato dei riscontri AML, `AMLHitStatusChoices`). | `[…]` |
| `score` | float (0-100) | Sì | Punteggio complessivo di screening: il `risk_score` più alto tra i riscontri non contrassegnati come `False Positive` (`aml/services/aml.py:832-842`); `0` quando ogni riscontro è un falso positivo. `null` finché non viene calcolato. | `42.7` |
| `screened_data` | object | Sì | Snapshot dei dati inviati allo screening: `full_name`, `nationality`, `date_of_birth`, `document_number`. | `{ "full_name": "María García López", "date_of_birth": "1990-05-12" }` |
| `is_ongoing_monitoring_enabled` | boolean | No | Indica se l'entità è iscritta ai nuovi screening periodici del monitoraggio continuo. | `false` |
| `next_ongoing_monitoring_bill_date` | string (YYYY-MM-DD) | Sì | Calcolata come `last_aml_bill_date + 365 days` quando il monitoraggio continuo è attivo. Si tratta di una data di **fatturazione**, non di una data di screening. | `null` |
| `last_ongoing_screening_at` | string (ISO 8601) | Sì | Momento in cui il monitoraggio continuo ha completato l'ultimo nuovo screening di questo record, indipendentemente dal fatto che il risultato sia cambiato. `null` se non è mai stato ricontrollato; non viene mai valorizzato retroattivamente. | `"2026-09-12T04:03:11Z"` |
| `last_ongoing_screening_datasets_updated_at` | string (ISO 8601) | Sì | Ultimo aggiornamento del dataset AML riportato dal provider per quello screening. `null` quando il provider non ha riportato alcuna data del dataset; non viene mai stimata. | `null` |
| `node_id` | string \| null | Sì | Identificativo del nodo del workflow (V3). | `"first_aml"` |
| `warnings` | array | No | Vedi [Oggetto dell'avviso](#oggetto-avviso). | `[]` |

```json theme={null}
{
  "status": "In Review",
  "total_hits": 1,
  "entity_type": "person",
  "hits": [
    {
      "id": "Q7XW3-aml-hit-1",
      "caption": "Maria Garcia Lopez",
      "match": true,
      "target": true,
      "match_score": 86.4,
      "risk_score": 42.7,
      "datasets": ["PEP Level 2"],
      "properties": {
        "name": ["María García López", "M. García"],
        "alias": ["Maria Garcia"],
        "birthDate": ["1990-05-12"]
      },
      "url": "https://example.org/registry/entities/Q7XW3",
      "first_seen": "2023-11-02T00:00:00Z",
      "last_seen": "2026-05-01T00:00:00Z",
      "review_status": "Unreviewed"
    }
  ],
  "score": 42.7,
  "screened_data": {
    "full_name": "María García López",
    "date_of_birth": "1990-05-12",
    "nationality": "ES",
    "document_number": "AB1234567"
  },
  "is_ongoing_monitoring_enabled": false,
  "next_ongoing_monitoring_bill_date": null,
  "last_ongoing_screening_at": null,
  "last_ongoing_screening_datasets_updated_at": null,
  "node_id": "first_aml",
  "warnings": []
}
```

### Analisi IP

Restituito per ogni posizione di rete acquisita. Compare come `ip_analyses[]` in `GET /v3/session/{sessionId}/decision/` sia per le sessioni KYC sia per quelle KYB. Fonte: `kyc/serializers/location.py:196-243` (`IPAnalysisSerializerV3`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Vedi [enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `node_id` | string \| null | Sì | Identificativo del nodo del workflow (V3). | `"first_ip_analysis"` |
| `device_brand` | string | Sì | Marca del dispositivo ricavata dallo user agent. | `"Apple"` |
| `device_model` | string | Sì | Modello del dispositivo. | `"iPhone"` |
| `browser_family` | string | Sì | Famiglia del browser. | `"Mobile Safari"` |
| `os_family` | string | Sì | Famiglia del sistema operativo. | `"iOS"` |
| `platform` | string | Sì | Piattaforma di alto livello (`mobile`, `desktop`, `tablet`). | `"mobile"` |
| `device_fingerprint` | string | Sì | Hash stabile dell'impronta del dispositivo, specifico per ogni dispositivo. | `"f2a3…"` |
| `ip_country` | string | Sì | Nome del paese ricavato dall'IP. | `"Spain"` |
| `ip_country_code` | string (ISO 3166-1 alpha-2) | Sì | Codice del paese ricavato dall'IP. | `"ES"` |
| `ip_state` | string | Sì | Regione o stato ricavato dall'IP. | `"Comunidad de Madrid"` |
| `ip_city` | string | Sì | Città ricavata dall'IP. | `"Madrid"` |
| `latitude` | float | Sì | Latitudine ricavata dall'IP. | `40.4168` |
| `longitude` | float | Sì | Longitudine ricavata dall'IP. | `-3.7038` |
| `ip_address` | string | Sì | L'indirizzo acquisito. | `"203.0.113.42"` |
| `isp` | string | Sì | Nome dell'ISP. | `"Telefonica de Espana"` |
| `organization` | string | Sì | Nome dell'organizzazione (spesso uguale all'ISP). | `"Telefonica de Espana"` |
| `is_vpn_or_tor` | boolean | Sì | `true` quando l'IP appartiene a una VPN, a un proxy o a un nodo di uscita Tor. | `false` |
| `is_data_center` | boolean | Sì | `true` quando l'IP appartiene a un ASN noto di hosting o data center. | `false` |
| `time_zone` | string | Sì | Nome del fuso orario IANA. | `"Europe/Madrid"` |
| `time_zone_offset` | string | Sì | Scostamento rispetto a UTC. | `"+02:00"` |
| `ip` | object | No | `{ location, distance_from_id_document, distance_from_poa_document }`. `location = { latitude, longitude }`. Distanze in km, `null` quando manca uno dei due lati. | `{ "location": { "latitude": 40.4168, "longitude": -3.7038 }, "distance_from_id_document": 3.4, "distance_from_poa_document": 1.1 }` |
| `id_document` | object | No | `{ location, distance_from_ip, distance_from_poa_document }`. Posizione del documento d'identità ricavata da `issuing_state` e dall'indirizzo analizzato. | `{ "location": { "latitude": 40.4165, "longitude": -3.7026 }, "distance_from_ip": 3.4, "distance_from_poa_document": 4.0 }` |
| `poa_document` | object | No | `{ location, distance_from_ip, distance_from_id_document }`. Indirizzo della prova di residenza geocodificato. | `{ "location": { "latitude": 40.4170, "longitude": -3.7040 }, "distance_from_ip": 1.1, "distance_from_id_document": 4.0 }` |
| `matches` | array of objects | No | Corrispondenze IP e dispositivo tra sessioni. Ogni elemento: `{ session_id, session_number, vendor_data, verification_date, match_type, match_source, matched_value, status, is_blocklisted, api_service, source, device_info, location_info, confidence, match_mode }`. `match_type` è `ip_address` o `device_fingerprint`; `match_source` è `ip_address`, `persistent_id`, `legacy_fp` o `recovered_high` (le corrispondenze recuperate includono anche `recovery_similarity`, `tls_ja4_corroborated`, `recovery_gate_reason`). Limitato a 5 corrispondenze IP e 5 corrispondenze di dispositivo. | `[]` |
| `warnings` | array | No | Vedi [Oggetto dell'avviso](#oggetto-avviso). | `[]` |
| `browser_version`, `os_version` | string | Sì | Versioni del browser e del sistema operativo ricavate dallo user agent. | `"17.4"` |
| `user_agent`, `accept_language` | string | Sì | La stringa user agent e l'intestazione `Accept-Language` inviate dal browser. | `"en-US,en;q=0.9"` |
| `session_identifier`, `session_age_ms` | string, integer | Sì | La sessione di navigazione in cui è stato eseguito il passaggio e la sua età in millisecondi. | `48210` |
| `coords_accuracy` | float | Sì | Raggio di precisione, in metri, delle coordinate riportate dal dispositivo. | `35.0` |
| `raw_device_data` | object | Sì | Segnali grezzi del dispositivo raccolti per il passaggio. | `{}` |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_ip_analysis",
  "device_brand": "Apple",
  "device_model": "iPhone",
  "browser_family": "Mobile Safari",
  "os_family": "iOS",
  "platform": "mobile",
  "device_fingerprint": "f2a3c1de8b994a3f9e4cdf3a02b1a7c9",
  "ip_country": "Spain",
  "ip_country_code": "ES",
  "ip_state": "Comunidad de Madrid",
  "ip_city": "Madrid",
  "latitude": 40.4168,
  "longitude": -3.7038,
  "ip_address": "203.0.113.42",
  "isp": "Telefonica de Espana",
  "organization": "Telefonica de Espana",
  "is_vpn_or_tor": false,
  "is_data_center": false,
  "time_zone": "Europe/Madrid",
  "time_zone_offset": "+02:00",
  "ip": {
    "location": { "latitude": 40.4168, "longitude": -3.7038 },
    "distance_from_id_document": 3.4,
    "distance_from_poa_document": 1.1
  },
  "id_document": {
    "location": { "latitude": 40.4165, "longitude": -3.7026 },
    "distance_from_ip": 3.4,
    "distance_from_poa_document": 4.0
  },
  "poa_document": {
    "location": { "latitude": 40.4170, "longitude": -3.7040 },
    "distance_from_ip": 1.1,
    "distance_from_id_document": 4.0
  },
  "matches": [],
  "warnings": []
}
```

### Verifica della posizione

Restituito per ogni passaggio di [Verifica della posizione](https://docs.didit.me/it/core-technology/location-verification/overview.md). Compare come `geolocation_checks[]` in `GET /v3/session/{sessionId}/decision/`: un elemento per passaggio, corrispondente al tentativo accettato. `geolocation_attempts[]` elenca ogni tentativo di ogni passaggio, dal più vecchio al più recente. Entrambi sono `null` per un workflow che non include il passaggio. Fonte: `GeolocationDecisionSerializer`.

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `node_id` | string | Sì | Nodo del workflow che ha prodotto il risultato. | `"geolocation_1"` |
| `status` | stringa | No | Vedi [Enum dello stato](#riferimento-agli-enum-di-stato). | `"Declined"` |
| `outcome` | stringa | Sì | Cosa è successo nel tentativo: `verified`, `low_accuracy`, `accuracy_undetermined`, `stale`, `approximate`, `denied`, `restricted`, `unavailable`, `timeout`, `mock_detected`, `outside_geofence`, `in_blocked_area`, `anonymizer_detected`, `skipped`, `replay_rejected` o `unsupported_client`. | `"outside_geofence"` |
| `permission` | stringa | Sì | Cosa ha concesso il sistema: `granted_precise`, `granted_approximate`, `denied`, `restricted`, `unavailable`, `timeout`, `dismissed` o `not_requested`. | `"granted_precise"` |
| `latitude`, `longitude` | float | Sì | Posizione WGS84. `null` quando non c'è una posizione. | `48.8566` |
| `accuracy_m` | float | Sì | Raggio di incertezza in metri. | `35.0` |
| `accuracy_confidence` | stringa | Sì | `p95`, `p68` o `unspecified`. | `"p95"` |
| `measured_at`, `age_seconds` | datetime, intero | Sì | Quando il dispositivo ha rilevato la posizione e i secondi trascorsi fino alla ricezione da parte di Didit. | `2` |
| `source`, `platform`, `sdk_version` | stringa | Sì | Da dove proviene la posizione, il client che l'ha prodotta e la relativa versione dell'SDK. | `"browser"` |
| `is_mock`, `produced_by_accessory` | booleano | Sì | Prove di spoofing riportate dalla piattaforma. `null` significa che la piattaforma non le riporta. | `null` |
| `integrity` | stringa | No | `attested`, `not_attested`, `failed`, `unsupported` (web) o `not_determined`. | `"unsupported"` |
| `country_code`, `region_code`, `city` | stringa | Sì | Il luogo a cui corrisponde la posizione. | `"FR"` |
| `geofence`, `inside_geofence`, `geofence_basis`, `inside_areas`, `blocked_areas` | oggetto, booleano, stringa, array | Sì | Il risultato relativo al paese e alle aree. | `{ "enabled": true, "result": "outside" }` |
| `position_source`, `anonymizers` | stringa, oggetto | Sì | Da dove il passaggio ricava la posizione e i segnali di VPN, proxy, Tor, spoofing ed emulatore. | `"device_and_ip"` |
| `ip_distance_km`, `ip_distance_uncertainty_km`, `ip_consistent`, `document_distance_km`, `travel_excused`, `consecutive_mismatches` | numero, booleano, intero | Sì | I confronti con la posizione IP e con l'indirizzo registrato. | `12.4` |
| `attempts` | intero | No | Il numero del tentativo all'interno del passaggio. | `3` |
| `consent` | oggetto | Sì | `accepted_at`, `version` e `locale` dell'informativa accettata dalla persona. | |
| `warnings` | array di [oggetti di avviso](#oggetto-avviso) | No | Gli avvisi `LOCATION_*` del passaggio. Non presenti in `geolocation_attempts[]`, che aggiunge `received_at` e `created_at`. | `[]` |

Tutti i campi e gli esempi sono nel [report di verifica della posizione](https://docs.didit.me/it/core-technology/location-verification/report-location-verification.md).

### Prova di residenza

Restituito per ogni documento di indirizzo inviato. Compare come `poa_verifications[]` in `GET /v3/session/{sessionId}/decision/`. Fonte: `poa/serializers/poa.py:212-227` (`POAV3Serializer`, estende `POAV2Serializer` in `poa/serializers/poa.py:173-209`).

| Campo | Tipo | Nullabile | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | stringa | No | Vedi [Enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `issuing_state` | stringa (ISO 3166-1 alpha-3) | Sì | Codice paese dell'emittente del documento. | `"ESP"` |
| `document_type` | stringa | No | Tipologia generale definita da `PoaDocumentTypeChoices` (`common/config/choices.py:868-873`): `UTILITY_BILL`, `BANK_STATEMENT`, `GOVERNMENT_ISSUED_DOCUMENT`, `OTHER_POA_DOCUMENT`. Viene impostato su `UNKNOWN`, mai `null`. | `"UTILITY_BILL"` |
| `document_subtype` | stringa | No | Codice del sottotipo da `PoaDocumentSubtypeChoices` (ad esempio `ELECTRICITY_BILL`, `WATER_BILL`, `ACCOUNT_STATEMENT`). Ricade su `UNKNOWN`, mai `null`. | `"ELECTRICITY_BILL"` |
| `issuer` | stringa | Sì | Nome dell'ente emittente. | `"Iberdrola"` |
| `issue_date` | stringa (YYYY-MM-DD) | Sì | Data di emissione del documento. | `"2026-04-15"` |
| `expiration_date` | stringa (YYYY-MM-DD) | Sì | Data di scadenza stampata sul documento, quando presente. | `null` |
| `poa_address` | stringa | Sì | Indirizzo grezzo estratto tramite OCR. | `"Calle Mayor 1, 28001 Madrid"` |
| `poa_formatted_address` | stringa | Sì | Indirizzo geocodificato e formattato. | `"Calle Mayor 1, 28001 Madrid, Spain"` |
| `poa_parsed_address` | oggetto | Sì | Indirizzo strutturato (`street_1`, `street_2`, `city`, `region`, `postal_code`, `country` (alpha-2), `address_type`, `document_location`, …). | `{ "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001" }` |
| `document_file` | stringa (URL) | Sì | URL prefirmato del documento caricato. | `"https://<media-host>/.../poa.pdf?..."` |
| `document_language` | stringa | Sì | Lingua del documento rilevata (ISO 639-1). | `"es"` |
| `document_metadata` | oggetto | Sì | Metadati filtrati: `file_size`, `content_type`, `creation_date`, `modified_date`, `creator`, `producer`, `software`, `encryption`, `is_signed`, `is_tampered`, `signature_info`, `exif_original_date`, `exif_digitized_date`, `processed_by_known_editor`, `has_different_creation_mod_date`, `overlay_manipulation`. | `{ "file_size": 184221, "content_type": "application/pdf", "is_tampered": false }` |
| `extra_fields` | oggetto | No | Campi del conto bancario (`bank_account_number`, `bank_iban`, `bank_sort_code`, `bank_routing_number`, `bank_swift_bic`, `bank_branch_name`, `bank_branch_address`), `document_phone_number`, `additional_names`, più eventuali chiavi personalizzate salvate nel record. | `{ "bank_iban": null, "additional_names": [] }` |
| `name_on_document` | stringa | Sì | Nome così come compare sulla prova di residenza. | `"María García López"` |
| `expected_details_address` | stringa | Sì | Indirizzo digitato dal cliente durante la registrazione (testo originale). | `"Calle Mayor 1, Madrid"` |
| `expected_details_formatted_address` | stringa | Sì | Indirizzo atteso geocodificato. | `"Calle Mayor 1, 28001 Madrid, Spain"` |
| `expected_details_parsed_address` | oggetto | Sì | Indirizzo atteso strutturato. | `{ "city": "Madrid", "postal_code": "28001" }` |
| `name_match_score_expected_details` | float (0-100) | Sì | Confronto approssimato tra `name_on_document` e il nome fornito alla creazione della sessione. | `94.0` |
| `name_match_score_id_verification` | float (0-100) | Sì | Confronto approssimato tra `name_on_document` e il `full_name` del documento d'identità verificato. | `100.0` |
| `extra_files` | array di stringhe (URL) | No | URL prefirmati dei file aggiuntivi caricati. | `[]` |
| `detected_codes` | array di oggetti | No | Codici QR e a barre rilevati in tutte le pagine elaborate del documento: `type`, `page_number` (a partire da 1), `position` (poligono), `x`/`y`/`width`/`height` (riquadro di delimitazione), `page_width`/`page_height`, `raw_payload` (base64), `parsed_payload` (valore decodificato, `null` quando un codice è stato individuato ma non è stato possibile decodificarlo). Array vuoto quando il rilevamento non trova nulla. | `[{ "type": "QR_CODE", "page_number": 1, "parsed_payload": "https://issuer.example/inv/9981" }]` |
| `node_id` | stringa \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_poa"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

```json theme={null}
{
  "status": "Approved",
  "issuing_state": "ESP",
  "document_type": "UTILITY_BILL",
  "document_subtype": "ELECTRICITY_BILL",
  "issuer": "Iberdrola",
  "issue_date": "2026-04-15",
  "expiration_date": null,
  "poa_address": "Calle Mayor 1, 28001 Madrid",
  "poa_formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "poa_parsed_address": { "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001", "country": "ES" },
  "document_file": "https://<media-host>/.../poa.pdf?signature=...",
  "document_language": "es",
  "document_metadata": {
    "file_size": 184221,
    "content_type": "application/pdf",
    "creation_date": "2026-04-15T08:11:32Z",
    "modified_date": "2026-04-15T08:11:32Z",
    "creator": "Iberdrola Billing",
    "producer": "Adobe PDF Library 15.0",
    "software": null,
    "encryption": null,
    "is_signed": true,
    "is_tampered": false,
    "signature_info": { "signer_name": "Iberdrola Clientes", "date": "2026-04-15T08:11:32Z" },
    "exif_original_date": null,
    "exif_digitized_date": null,
    "processed_by_known_editor": false,
    "has_different_creation_mod_date": false,
    "overlay_manipulation": null
  },
  "extra_fields": {
    "bank_account_number": null,
    "bank_iban": null,
    "bank_sort_code": null,
    "bank_routing_number": null,
    "bank_swift_bic": null,
    "bank_branch_name": null,
    "bank_branch_address": null,
    "document_phone_number": null,
    "additional_names": []
  },
  "name_on_document": "María García López",
  "expected_details_address": "Calle Mayor 1, Madrid",
  "expected_details_formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "expected_details_parsed_address": { "city": "Madrid", "postal_code": "28001", "country": "ES" },
  "name_match_score_expected_details": 94.0,
  "name_match_score_id_verification": 100.0,
  "extra_files": [],
  "detected_codes": [
    {
      "type": "QR_CODE",
      "page_number": 1,
      "position": [[820, 1120], [1002, 1120], [1002, 1302], [820, 1302]],
      "x": 820,
      "y": 1120,
      "width": 182,
      "height": 182,
      "page_width": 1190,
      "page_height": 1684,
      "raw_payload": "aHR0cHM6Ly9pYmVyZHJvbGEuZXMvZmFjdHVyYS85OTgx",
      "parsed_payload": "https://iberdrola.es/factura/9981"
    },
    {
      "type": "CODE_128",
      "page_number": 1,
      "position": [[112, 1480], [560, 1480], [560, 1540], [112, 1540]],
      "x": 112,
      "y": 1480,
      "width": 448,
      "height": 60,
      "page_width": 1190,
      "page_height": 1684,
      "raw_payload": "MDA5OTgxMDAwNDI=",
      "parsed_payload": "0099810042"
    }
  ],
  "node_id": "first_poa",
  "warnings": []
}
```

### Verifica telefonica

Restituito per ogni tentativo di verifica telefonica. Compare come `phone_verifications[]` in `GET /v3/session/{sessionId}/decision/` per le sessioni KYC e KYB. Fonte: `phone/serializers/phone.py:251-266` (`PhoneV3Serializer`, estende `PhoneV2Serializer` in `phone/serializers/phone.py:103-248`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | stringa | No | Vedi [Enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `phone_number_prefix` | stringa | No | Prefisso paese E.164 (con `+`). | `"+34"` |
| `phone_number` | stringa | No | Numero dell'abbonato senza prefisso. | `"612345678"` |
| `full_number` | stringa | No | Numero E.164 completo (`phone_number_prefix + phone_number`). | `"+34612345678"` |
| `country_code` | stringa (ISO 3166-1 alpha-2) | Sì | Paese del numero. | `"ES"` |
| `country_name` | stringa | Sì | Nome del paese localizzato. | `"Spain"` |
| `carrier` | oggetto | No | `{ name, type }` dove `type` è un valore di `LineTypeChoices` (`common/config/choices.py:648-667`): `mobile`, `fixed_line`, `voip`, `isp`, `vpn`, `toll_free`, `premium_rate`, `satellite`, `pager`, `payphone`, `voice_mail`, `unknown` e altre classi di linea. | `{ "name": "Movistar", "type": "mobile" }` |
| `is_disposable` | booleano | No | `true` quando il gestore segnala il numero come temporaneo o usa e getta. | `false` |
| `is_virtual` | booleano | No | `true` quando `carrier.type` è uno tra `voip`, `isp`, `vpn`. | `false` |
| `verification_method` | stringa | No | Canale usato per inviare l'OTP (`whatsapp`, `sms`, …). Viene letto da `actual_channel` dell'ultimo tentativo di invio (in alternativa dal `channel` richiesto, poi `sms`). | `"whatsapp"` |
| `verification_attempts` | intero | No | Numero totale di tentativi di invio dell'OTP (invio iniziale più reinvii). | `1` |
| `verified_at` | stringa (ISO 8601) | Sì | Momento in cui l'OTP è stato inserito correttamente. | `"2026-05-17T10:14:02Z"` |
| `lifecycle` | array di oggetti | No | Eventi in ordine cronologico: tentativi di invio, callback di consegna, verifiche del codice ed evento finale di stato. Ogni evento è `{ type, timestamp, details, fee }`. I tipi di evento provengono da `PhoneEventChoices`. | `[…]` |
| `matches` | array di oggetti | No | Corrispondenze del numero di telefono tra sessioni diverse. Ogni elemento: `{ session_id, session_number, vendor_data, verification_date, phone_number, status, is_blocklisted, api_service, source }`. `source` è `session` o `list_entry`. | `[]` |
| `node_id` | stringa \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_phone"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |
| `phone_intelligence` | oggetto | Sì | Segnali di intelligence sul numero di telefono. Presenti solo quando l'add-on di intelligence è stato eseguito per il numero. | |
| `phone_social` | oggetto | Sì | Impronta social del numero. Presente solo quando l'add-on dell'impronta social è stato eseguito. | |

```json theme={null}
{
  "status": "Approved",
  "phone_number_prefix": "+34",
  "phone_number": "612345678",
  "full_number": "+34612345678",
  "country_code": "ES",
  "country_name": "Spain",
  "carrier": { "name": "Movistar", "type": "mobile" },
  "is_disposable": false,
  "is_virtual": false,
  "verification_method": "whatsapp",
  "verification_attempts": 1,
  "verified_at": "2026-05-17T10:14:02Z",
  "lifecycle": [
    {
      "type": "PHONE_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2026-05-17T10:13:51Z",
      "details": { "status": "Success", "reason": null, "channel": "whatsapp", "actual_channel": "whatsapp" },
      "fee": 0.02
    },
    {
      "type": "PHONE_DELIVERY_DELIVERED",
      "timestamp": "2026-05-17T10:13:52Z",
      "details": { "channel": "whatsapp", "status": "delivered" },
      "fee": 0
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2026-05-17T10:14:02Z",
      "details": { "code_tried": "482917", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "PHONE_VERIFICATION_APPROVED",
      "timestamp": "2026-05-17T10:14:02Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "first_phone",
  "warnings": []
}
```

### Verifica email

Restituito per ogni tentativo di verifica email. Compare come `email_verifications[]` in `GET /v3/session/{sessionId}/decision/` per le sessioni KYC e KYB. Fonte: `email_verification/serializers/email.py:149-164` (`EmailV3Serializer`, estende `EmailV2Serializer` in `email_verification/serializers/email.py:38-146`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | stringa | No | Vedi [Enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `email` | stringa | No | L'indirizzo email fornito. | `"maria.garcia@example.com"` |
| `is_breached` | booleano | No | `true` quando l'email compare in una violazione di dati nota. | `false` |
| `breaches` | array di oggetti | No | Dettaglio per ogni violazione quando `is_breached` è `true`: `{ name, domain, logo_path, breach_date, description, is_verified, data_classes, breach_emails_count }`. | `[]` |
| `is_disposable` | booleano | No | `true` quando l'email appartiene a un provider di posta usa e getta. | `false` |
| `is_undeliverable` | booleano | No | `true` quando la verifica SMTP indica che la casella non accetta posta. | `false` |
| `verification_attempts` | intero | No | Numero totale di tentativi di verifica dell'OTP. | `1` |
| `verified_at` | stringa (ISO 8601) | Sì | Momento in cui l'OTP è stato inserito correttamente. | `"2026-05-17T10:15:22Z"` |
| `lifecycle` | array di oggetti | No | Eventi in ordine cronologico: tentativi di invio, verifiche del codice ed evento finale di stato. Ogni evento è `{ type, timestamp, details, fee }`. I tipi di evento provengono da `EmailEventChoices`. | `[…]` |
| `matches` | array di oggetti | No | Corrispondenze dell'email tra sessioni diverse. Ogni elemento: `{ session_id, session_number, vendor_data, verification_date, email, status, is_blocklisted, api_service, source }`. `source` è `session` o `list_entry`. | `[]` |
| `node_id` | stringa \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_email"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |
| `email_intelligence` | oggetto | Sì | Segnali di intelligence sull'email. Presenti solo quando l'add-on di intelligence è stato eseguito per l'indirizzo. | |
| `email_social` | oggetto | Sì | Impronta social dell'indirizzo. Presente solo quando l'add-on dell'impronta social è stato eseguito. | |

```json theme={null}
{
  "status": "Approved",
  "email": "maria.garcia@example.com",
  "is_breached": false,
  "breaches": [],
  "is_disposable": false,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2026-05-17T10:15:22Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2026-05-17T10:15:11Z",
      "details": { "status": "Success", "reason": null },
      "fee": 0.02
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2026-05-17T10:15:22Z",
      "details": { "code_tried": "739204", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_APPROVED",
      "timestamp": "2026-05-17T10:15:22Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "first_email",
  "warnings": []
}
```

### Validazione su database

Restituito per ogni ricerca in database eseguita sui dati inviati dall'utente. Compare come `database_validations[]` in `GET /v3/session/{sessionId}/decision/`. Fonte: `database_validation/serializers/database_validation.py:21-142` (`DatabaseValidationV3Serializer`, estende `DatabaseValidationV2Serializer`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `issuing_state` | stringa (ISO 3166-1 alpha-3) | Sì | Paese il cui registro è stato interrogato. | `"ESP"` |
| `validation_type` | stringa (enum) | No | Come è stato confermato il risultato: `one_by_one` (esito di un singolo servizio), `two_by_two` (due o più servizi distinti hanno confermato in modo indipendente con corrispondenza completa il numero di identificazione) oppure `not_enabled` (il validatore è stato saltato o nessun provider ha risposto: un `no_match` definitivo produce comunque `one_by_one`). Mai `null`. Fonte: `DatabaseValidationChoices` (`common/config/choices.py:1097-1100`). | `"one_by_one"` |
| `screened_data` | oggetto | No | I dati inviati al registro. I campi file (`selfie`, `cnh_qr_code_image`, `document_image`) sono pre-firmati al momento della lettura. | `{ "document_number": "99999999R", "date_of_birth": "1990-05-12" }` |
| `validations` | array di oggetti | No | Una voce per ogni servizio del catalogo che ha prodotto una corrispondenza. Ogni voce può includere `service_id`, `service_name`, `validation` (oggetto con il verdetto del provider), `outcome_code`, `outcome_detail` e `source_data` (profilo del cittadino normalizzato: `full_name`, `gender`, `date_of_birth`, `photo` (URL pre-firmato), `signature` (URL pre-firmato), …). | `[…]` |
| `errors` | array di oggetti | Sì | Errori per servizio quando una ricerca non è riuscita; la chiave viene omessa del tutto quando è vuota. Ogni voce è l'oggetto di errore del servizio a monte, con il `service_id` che l'ha generato. | `[]` |
| `match_type` | stringa (enum) | Sì | Verdetto di corrispondenza complessivo tra i servizi interrogati: `full_match`, `partial_match` oppure `no_match` (`DatabaseValidationMatchTypeChoices`, `common/config/choices.py:1103-1106`). `null` finché non viene valutato. | `"full_match"` |
| `status` | stringa | No | Vedi [enum dello status](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `node_id` | stringa \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_db_validation"` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

```json theme={null}
{
  "issuing_state": "ESP",
  "validation_type": "one_by_one",
  "screened_data": {
    "document_number": "99999999R",
    "date_of_birth": "1990-05-12",
    "first_name": "María",
    "last_name": "García López"
  },
  "validations": [
    {
      "service_id": "esp_dni",
      "service_name": "Spain - DNI/NIE verification",
      "validation": { "is_valid": true, "match_score": 100 },
      "outcome_code": "MATCH",
      "outcome_detail": "All identifiers match the registry record.",
      "source_data": {
        "full_name": "María García López",
        "gender": "F",
        "date_of_birth": "1990-05-12",
        "photo": "https://<media-host>/.../registry_photo.jpg?signature=...",
        "signature": null
      }
    }
  ],
  "match_type": "full_match",
  "status": "Approved",
  "node_id": "first_db_validation",
  "warnings": []
}
```

### Risposta del questionario

Restituita per ogni invio di un questionario. Compare come `questionnaire_responses[]` in `GET /v3/session/{sessionId}/decision/` sia per le sessioni KYC sia per quelle KYB. Fonte: `questionnaires/serializers/questionnaire.py:591-597` (`QuestionnaireResponseV3Serializer`, estende `QuestionnaireResponseSerializer` in `questionnaires/serializers/questionnaire.py:520-588`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `questionnaire_id` | stringa (UUID) | No | Identificatore della versione del questionario a cui si è risposto. | `"6a0f1c2c-…"` |
| `title` | stringa | No | Nome del questionario, come impostato nella Console. | `"Customer risk profile"` |
| `description` | stringa | Sì | Descrizione del questionario. | `"Short risk-profile questions."` |
| `languages` | array di stringhe | No | Codici delle lingue in cui il questionario è pubblicato. | `["en", "es"]` |
| `default_language` | stringa | No | Codice della lingua di riserva. | `"en"` |
| `is_active` | booleano | No | Indica se questa versione del questionario è quella attiva. | `true` |
| `is_simple_questionnaire` | booleano | No | `true` quando il questionario non ha diramazioni (elenco piatto). | `true` |
| `questionnaire_group_id` | stringa (UUID) | No | Identificatore condiviso tra le versioni dello stesso questionario. | `"a7c2c2c2-…"` |
| `version` | intero | No | Numero di versione del modello attivo. | `3` |
| `status` | stringa | No | Uno tra `Approved`, `In Review`, `Not Finished` (un rifiuto a livello di questionario viene mappato come `In Review`). | `"Approved"` |
| `published_at` | stringa (ISO 8601) | Sì | Quando il modello è stato pubblicato. | `"2026-01-12T11:00:00Z"` |
| `sections` | array di oggetti | No | Sezioni ordinate dopo l'applicazione dell'attraversamento del grafo e del filtro di visibilità. Ogni sezione è `{ title, description, items[] }` (title e description provengono dal `SECTION_HEADER` iniziale, già tradotti). Ogni elemento è un elemento del modulo (`uuid`, `value` (id del nodo), `element_type`, `is_required`, `title`, `description`, `placeholder`, `choices`, `max_files`, `required_if`, `repeatable_config`, più un campo `answer`: `null` se non è stata fornita una risposta, omesso per gli elementi di layout `HEADING`/`PARAGRAPH`/`SEPARATOR`). Le risposte con file contengono `{ files: [<presigned URL>, …] }`. | `[…]` |
| `node_id` | stringa \| null | Sì | Identificatore del nodo del workflow (V3). | `"first_questionnaire"` |

```json theme={null}
{
  "questionnaire_id": "6a0f1c2c-3b7d-4d2c-9eb6-fdc6c7c92ef9",
  "title": "Customer risk profile",
  "description": "Short risk-profile questions.",
  "languages": ["en", "es"],
  "default_language": "en",
  "is_active": true,
  "is_simple_questionnaire": true,
  "questionnaire_group_id": "a7c2c2c2-1111-4d2c-9eb6-fdc6c7c92ef9",
  "version": 3,
  "status": "Approved",
  "published_at": "2026-01-12T11:00:00Z",
  "sections": [
    {
      "title": "Source of funds",
      "description": null,
      "items": [
        {
          "uuid": "4f1d5e2c-aaaa-4d2c-9eb6-fdc6c7c92ef9",
          "value": "q_source_of_funds",
          "element_type": "SINGLE_CHOICE",
          "is_required": true,
          "title": "What is your main source of funds?",
          "description": null,
          "placeholder": null,
          "choices": [
            { "label": "Salary", "value": "salary" },
            { "label": "Business income", "value": "business" },
            { "label": "Investments", "value": "investments" }
          ],
          "max_files": 1,
          "required_if": null,
          "repeatable_config": null,
          "answer": { "value": "salary" }
        }
      ]
    }
  ],
  "node_id": "first_questionnaire"
}
```

### Firma elettronica

Restituita per ogni firmatario di un passaggio di [Firma elettronica](https://docs.didit.me/it/core-technology/electronic-signature/overview.md). Compare come `signatures[]` in `GET /v3/session/{sessionId}/decision/` sia per le sessioni KYC sia per quelle KYB, solo quando il workflow include il passaggio. A differenza degli altri oggetti del report, il suo `status` indica la fase di firma e l'esito si trova in `verdict`, e gli elementi di `warnings[]` sono `{ code, node_id }` anziché [oggetti avviso](#oggetto-avviso).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `id` | stringa (UUID) | No | La firma del firmatario. Usala come `signature_id` per gli endpoint delle prove e della validazione. | `"0e6c2a8e-…"` |
| `node_id` | stringa | No | Identificatore del nodo del workflow. | `"feature_signature"` |
| `status` | stringa | No | Fase della firma: `intro`, `review`, `code`, `signing`, `signed` oppure `declined`. Solo `signed` indica che i documenti sono firmati. | `"signed"` |
| `verdict` | stringa | No | `Not Finished`, `Approved`, `In Review` oppure `Declined`. | `"Approved"` |
| `level` | stringa | No | `simple` (predefinito) oppure `aes`. `qes` è un'opzione aggiuntiva non ancora disponibile. | `"aes"` |
| `format` | stringa | No | `pdf` per una firma Simple, `pades` per una firma Avanzata (AES). | `"pades"` |
| `profile` | stringa | Sì | `PAdES-B-LT` una volta firmata una firma Avanzata (AES), altrimenti null. | `"PAdES-B-LT"` |
| `signer` | oggetto | No | `{ name, capacity, company, role, roles, identity_session_id }`. `capacity` è `self` (KYC) o `company` (KYB). | `{ "name": "Jane Doe", "capacity": "self", … }` |
| `identity_used` | oggetto | No | `{ session_id, kyc_id, verified, expected_name }`: l'identità verificata su cui si basa la firma. Vuoto per una firma Simple senza identità verificata. | `{ "verified": true, … }` |
| `certificate` | oggetto | Sì | `{ issuer, issued_to, serial, valid_from, valid_until }`. `null` finché non viene firmato, e sempre `null` per una firma Simple. | `{ "serial": "5A3F9C21", … }` |
| `confirmation` | oggetto | No | `{ channel, destination, confirmed_at, attempts }`. `destination` è mascherato; `attempts` conta i codici inseriti, incluso quello corretto. Una firma Simple non prevede codice, quindi `channel` e `destination` sono `null`. | `{ "channel": "email", … }` |
| `timestamp` | oggetto | Sì | `{ time, qualified, valid }`. `qualified` è sempre `false` per AES. `null` finché non viene firmato, e sempre `null` per una firma Simple. | `{ "qualified": false, … }` |
| `documents` | array di oggetti | No | `{ id, uuid, title, file_name, pages, size_bytes, sha256_original, sha256_signed, status, opened_at, read_at, read_to_end, consented_at, consent, signed_file, mode, source_format, conversion, fields }`. `status` è `signed`, `declined`, `not_signed` o `not_reached`. `mode` è `fields` o `read_and_agree`. `source_format` è `pdf` o `docx`; `conversion` descrive il file Word originale, oppure è `null` per un PDF. | `[…]` |
| `documents[].fields` | array di oggetti | No | `{ key, type, role, label, page, x, y, width, height, required, value, display_value, value_source, filled_at, image_url, value_unavailable_reason }` per ogni campo del documento. `value` è una stringa, un booleano per una casella di spunta, oppure `true` per una firma o delle iniziali apposte. Vuoto per un documento senza campi. | `[…]` |
| `adopted_signature` | oggetto | Sì | `{ method, font, adopted_at }`: la firma e le iniziali adottate dal firmatario. `method` è `typed` o `drawn`; `font` è lo stile calligrafico di una firma digitata. `null` finché non viene adottata. | `{ "method": "drawn", … }` |
| `electronic_signature_consent_at` | stringa (ISO 8601) | Sì | Momento in cui il firmatario ha acconsentito a firmare i documenti elettronicamente. Impostato quando almeno un documento contiene campi. | `"2026-11-03T10:41:40Z"` |
| `evidence_file` | stringa | Sì | Percorso del PDF delle prove, una volta firmato. | `"/v3/session/…/evidence/?signature_id=…"` |
| `warnings` | array di oggetti | No | `{ code, node_id }`, dove `code` è uno tra `SIGNATURE_DECLINED`, `SIGNATURE_OTP_FAILED`, `SIGNATURE_NAME_MISMATCH`, `SIGNATURE_IDENTITY_NOT_VERIFIED`, `SIGNATURE_DOCUMENT_CHANGED`. | `[]` |
| `validation` | oggetto | Sì | `{ valid, checked_at, documents[] }`: l'ultima verifica crittografica dei documenti firmati. `null` finché non viene firmato. `{ valid: null, reason: "signature_provider_outcome_unknown", checked_at }` quando non è stato possibile confermare l'esito della firma. | `{ "valid": true, … }` |
| `declined_at` | stringa (ISO 8601) | Sì | Momento in cui il firmatario ha rifiutato. | `null` |
| `declined_action` | stringa | No | Il valore `signature_declined_action` del passaggio. | `"REVIEW"` |
| `signed_at` | stringa (ISO 8601) | Sì | Momento in cui i documenti sono stati firmati. | `"2026-11-03T10:42:24Z"` |
| `expires_at` | stringa (ISO 8601) | No | Momento in cui il link di firma smette di funzionare. | `"2026-11-10T10:30:00Z"` |
| `email_sent_at` | stringa (ISO 8601) | Sì | Momento in cui al firmatario è stata inviata via email una copia firmata. | `"2026-11-03T10:42:30Z"` |
| `email_unavailable_reason` | stringa | Sì | Motivo per cui non è stata inviata alcuna copia via email, quando era stata richiesta. | `null` |
| `ip_address` | stringa | Sì | Indirizzo IP del firmatario al momento della richiesta del codice. | `"203.0.113.10"` |
| `place` | stringa | Sì | Non raccolto: sempre `null`. | `null` |
| `place_unavailable_reason` | stringa | Sì | `not_collected`. | `"not_collected"` |

Il [report Firma elettronica](https://docs.didit.me/it/core-technology/electronic-signature/report-electronic-signature.md) contiene un esempio completo e tutti i campi annidati.

### Stima dell'età

Restituito dalla API autonoma di Stima dell'età (`POST /v3/age-estimation/`). La risposta contiene un sottoinsieme della struttura di [`Liveness check`](#rilevamento-della-vitalità) all'interno di un contenitore `age_estimation`: `status`, `method`, `score`, `age_estimation`, `warnings`. Include inoltre un blocco `user_image` per il rilevamento del volto, disponibile solo nella modalità autonoma; **non** include `reference_image`, `video_url`, `matches`, `face_quality` o `face_luminance`. Nelle sessioni workflow non esiste un array separato: l'età stimata compare in `liveness_checks[].age_estimation` in `GET /v3/session/{sessionId}/decision/`. Fonte: `apis/serializers/age_estimation.py:50-55` (`AgeEstimationResponseSerializer`), contenitore costruito in `apis/views/age_estimation.py:138-174`.

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `request_id` | stringa (UUID) | No | ID della sessione salvato quando `save_api_request=true` (il valore predefinito); altrimenti un UUID di correlazione temporaneo. | `"3b1f1e2c-…"` |
| `age_estimation` | oggetto | No | Contenitore del risultato: `status` (`Approved` / `Declined`), `method` (sempre `PASSIVE`), `score` (punteggio di vitalità da 0 a 100, nullable), `age_estimation` (età prevista in anni del volto più grande, nullable), `user_image` (`entities[]` con `age`, `bbox` `[x_min, y_min, x_max, y_max]`, `confidence` e `gender` per ogni volto; inoltre `best_angle`), `warnings[]`. | `{ … }` |
| `vendor_data` | stringa | Sì | `vendor_data` della richiesta, restituito così com'è. | `null` |
| `metadata` | oggetto | Sì | `metadata` della richiesta, restituito così com'è. | `null` |
| `created_at` | stringa (ISO 8601) | No | Data e ora della richiesta lato server. | `"2026-05-17T10:22:13.512941+00:00"` |

```json theme={null}
{
  "request_id": "3b1f1e2c-7777-4d2c-9eb6-fdc6c7c92ef9",
  "age_estimation": {
    "status": "Approved",
    "method": "PASSIVE",
    "score": 94.10,
    "age_estimation": 28.7,
    "user_image": {
      "entities": [
        { "age": 28.7, "bbox": [40, 40, 100, 100], "confidence": 0.72, "gender": "male" }
      ],
      "best_angle": 0
    },
    "warnings": []
  },
  "vendor_data": null,
  "metadata": null,
  "created_at": "2026-05-17T10:22:13.512941+00:00"
}
```

### Autenticazione biometrica

L'autenticazione biometrica esegue la stessa pipeline di Rilevamento della vitalità + Confronto facciale usata nel KYC standard, ma configurata per confrontare il volto acquisito con l'immagine di riferimento di un utente esistente, invece che con un ritratto del documento appena sottoposto a OCR. Non esiste un serializzatore dedicato: `GET /v3/session/{sessionId}/decision/` restituisce gli oggetti standard [Rilevamento della vitalità](#rilevamento-della-vitalità) e [Confronto facciale](#confronto-facciale) in `liveness_checks[]` e `face_matches[]`. Il workflow della sessione è configurato con `workflow_type = "biometric_authentication"` (`WorkflowTypeChoices`, `common/config/choices.py:636`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `liveness_checks` | array di [Controllo della vitalità](#rilevamento-della-vitalità) | No | Risultato del rilevamento della vitalità per il tentativo di autenticazione. | `[ { "status": "Approved", … } ]` |
| `face_matches` | array di [Confronto facciale](#confronto-facciale) | No | Risultato del confronto con il riferimento registrato. `source_image_session_id` è impostato sull'`session_id` della sessione stessa: il volto di riferimento (il `portrait_image` fornito, oppure il volto memorizzato riutilizzato tramite `vendor_data` quando `portrait_image` è omesso) viene registrato sotto la sessione di autenticazione stessa (`face/views/face.py:656-659`). | `[ { "status": "Approved", "source_image_session_id": "…", … } ]` |
| `status` | string | No | Stato della sessione a livello superiore (vedi [Enum dello stato](#riferimento-agli-enum-di-stato)). | `"Approved"` |

```json theme={null}
{
  "session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
  "status": "Approved",
  "liveness_checks": [
    {
      "status": "Approved",
      "method": "PASSIVE",
      "score": 95.10,
      "reference_image": "https://<media-host>/.../reference.jpg?signature=...",
      "video_url": null,
      "age_estimation": null,
      "matches": [],
      "face_quality": 91.20,
      "face_luminance": 53.10,
      "node_id": "biometric_auth_liveness",
      "warnings": []
    }
  ],
  "face_matches": [
    {
      "status": "Approved",
      "score": 98.42,
      "source_image_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
      "source_image": "https://<media-host>/.../source.jpg?signature=...",
      "target_image": "https://<media-host>/.../target.jpg?signature=...",
      "node_id": "biometric_auth_face_match",
      "warnings": []
    }
  ]
}
```

### Registro KYB

Restituito per ogni azienda confermata dal registro in un workflow KYB. Compare come `registry_checks[]` in `GET /v3/session/{sessionId}/decision/` per le sessioni aziendali. Fonte: `kyb/serializers/kyb.py:939-964` (`RegistryCheckV3Serializer`).

| Campo | Tipo | Ammette null | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Vedi [Enum dello stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `node_id` | string \| null | Sì | Identificativo del nodo del workflow (V3). | `"first_registry"` |
| `data_resolved` | boolean | No | `true` quando il recupero dal registro è completato (oppure quando `is_from_registry` è `false`, cioè i dati sono stati inseriti manualmente). | `true` |
| `company` | object | No | Payload completo dell'azienda: vedi [Oggetto azienda](#oggetto-azienda) più avanti. | `{ … }` |
| `ownership_structure` | object | Sì | L'assetto proprietario dimostrato dal registro: `shareholders[]` e `beneficial_owners[]`, con ogni titolare, la sua identità nel registro, la quota e lo `shareholding` canonico. | `{ "shareholders": [...], "beneficial_owners": [] }` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

#### Oggetto azienda

Da `kyb/serializers/kyb.py:220-321` (`KYBCompanyResponseSerializer`).

| Campo | Tipo | Ammette null | Descrizione |
| - | - | - | - |
| `uuid` | string (UUID) | No | Identificativo interno dell'azienda. |
| `node_id` | string \| null | Sì | Identificativo del nodo del workflow. |
| `status` | string | No | Stato della funzionalità (`FeatureStatusChoices`). |
| `registry_status` | string | Sì | Stato dell'azienda nel registro (`active`, `dissolved`, …). |
| `data_resolved` | boolean | No | Stesso significato dell'oggetto padre. |
| `company_name` | string | Sì | Nome registrato dell'azienda. |
| `registration_number` | string | Sì | Identificativo nel registro. |
| `country_code` | string (ISO 3166-1 alpha-2) | Sì | Paese di costituzione. |
| `region` | string | Sì | Suddivisione ISO 3166-2, quando applicabile (ad es. `US-CA`). |
| `company_type` | string | Sì | Forma giuridica (`LLC`, `SL`, …). |
| `incorporation_date` | string (YYYY-MM-DD) | Sì | Data di costituzione. |
| `registered_address` | string | Sì | Indirizzo legale registrato. |
| `tax_number` | string | Sì | Identificativo fiscale o partita IVA. |
| `risk_level` | string | Sì | Valutazione del rischio fornita dal provider. |
| `verification_status` | string | Sì | Enum interno dello stato di verifica. |
| `is_from_registry` | boolean | No | `true` quando il dato proviene dal registro (anziché dall'inserimento manuale). |
| `fetch_status` | string | Sì | `pending`, `resolved`, `failed`. |
| `alternative_names` | string | Sì | Nomi commerciali alternativi separati da virgole. |
| `nature_of_business` | string | Sì | Descrizione in testo libero dell'attività aziendale. |
| `registered_capital` | string | Sì | Capitale sociale come stringa leggibile. |
| `registered_capital_amount` | string (decimal) | Sì | Importo analizzato del capitale sociale. |
| `registered_capital_currency` | string (ISO 4217) | Sì | Codice valuta. |
| `website` | string (URL) | Sì | Sito web dell'azienda. |
| `email` | string | Sì | Email di contatto pubblica. |
| `phone` | string | Sì | Telefono di contatto pubblico. |
| `legal_entity_identifier` | string | Sì | LEI, quando disponibile. |
| `location_of_registration` | string | Sì | Ufficio o regione del registro. |
| `vat_number` | string | Sì | Numero IVA inviato per l'azienda. |
| `vat_validation_status` | string | No | Esito della validazione del numero IVA, oppure del `tax_number` quando manca: `valid`, `invalid`, `format_valid`, `invalid_format`, `could_not_validate` o `not_applicable`. Vedi [Validazione di IVA e identificativo fiscale](https://docs.didit.me/it/business-verification/company-data.md#validazione-del-numero-vat-e-dell’identificativo-fiscale). |
| `vat_validated_number` | string | Sì | Il numero verificato, come lo conosce la fonte. |
| `vat_validation_source` | string | Sì | Fonte che ha determinato lo stato: `eu_vies`, `pl_vat_white_list`, `no_brreg`, `ch_uid_register`, `br_receita_federal`, `co_rues`, `cr_hacienda`, `ec_sri`, `py_dnit` o `format_rules`. |
| `vat_validated_name` | string | Sì | Nome registrato presso la fonte (vuoto se la fonte non lo rende noto). |
| `vat_validated_address` | string | Sì | Indirizzo registrato presso la fonte (vuoto se non reso noto). |
| `vat_checked_at` | string (ISO 8601) | Sì | Data e ora del controllo; `null` quando non è stato eseguito alcun controllo. |
| `financial_summary` | object | Sì | Istantanea dei principali dati finanziari, quando forniti dal registro. |
| `officers` | array of objects | No | Elenco dei dirigenti adatto al B2C: `{ uuid, name, designation, role, nationality, is_active, kyc_status, kyc_session_url }`. |
| `beneficial_owners` | array of objects | No | Elenco dei titolari effettivi (UBO) adatto al B2C: `{ uuid, name, first_name, last_name, entity_type, roles, ownership_min_shares, ownership_max_shares, is_active, kyc_status, kyc_session_url, effective_ownership_percent }`. |
| `addresses` | array of objects | Sì | Dettaglio per indirizzo dal registro. |
| `industries` | array of objects | Sì | Classificazioni in stile SIC/NAICS. |
| `accounts` | array of objects | Sì | Metadati dei bilanci depositati. |
| `registry_data` | object | Sì | Dettaglio normalizzato del registro di Didit (esito dell'assetto proprietario, correzioni dalla console, dati del registro senza un campo dedicato). Non è un contratto stabile. |
| `user_provided_data` | object | Sì | Istantanea dei campi modificati dall'utente. |
| `confirmed_by_user_at` | string (ISO 8601) | Sì | Data e ora in cui l'utente ha confermato i dati estratti. |
| `last_console_edit_at` | string (ISO 8601) | Sì | Data e ora dell'ultima modifica dalla console. |
| `is_editable` | boolean | No | `true` finché i dati provenienti dal registro possono ancora essere modificati dall'utente finale. |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_registry",
  "data_resolved": true,
  "company": {
    "uuid": "b1f1e2c2-9999-4d2c-9eb6-fdc6c7c92ef9",
    "node_id": "first_registry",
    "status": "Approved",
    "registry_status": "active",
    "data_resolved": true,
    "company_name": "Sante Clinics SL",
    "registration_number": "B12345678",
    "country_code": "ES",
    "region": null,
    "company_type": "SL",
    "incorporation_date": "2018-03-22",
    "registered_address": "Calle Mayor 1, 28001 Madrid, Spain",
    "tax_number": "B12345678",
    "risk_level": "low",
    "verification_status": "verified",
    "is_from_registry": true,
    "fetch_status": "resolved",
    "alternative_names": "Sante Clinics",
    "nature_of_business": "Medical clinic operations",
    "registered_capital": "EUR 50,000",
    "registered_capital_amount": "50000.00",
    "registered_capital_currency": "EUR",
    "website": "https://santeclinics.com",
    "email": "info@santeclinics.com",
    "phone": "+34911223344",
    "legal_entity_identifier": null,
    "location_of_registration": "Registro Mercantil de Madrid",
    "vat_number": "ESB12345678",
    "vat_validation_status": "valid",
    "vat_validated_name": "SANTE CLINICS SL",
    "vat_validated_address": "CALLE MAYOR 1, 28001 MADRID",
    "vat_checked_at": "2026-05-17T10:11:05Z",
    "financial_summary": null,
    "officers": [
      {
        "uuid": "c1f1e2c2-aaaa-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "designation": "Administrador único",
        "role": "Director",
        "nationality": "ESP",
        "is_active": true,
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…"
      }
    ],
    "beneficial_owners": [
      {
        "uuid": "d1f1e2c2-bbbb-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "first_name": "María",
        "last_name": "García López",
        "entity_type": "person",
        "roles": ["UBO"],
        "ownership_min_shares": "75.00",
        "ownership_max_shares": "75.00",
        "is_active": true,
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "effective_ownership_percent": 75.0
      }
    ],
    "addresses": [],
    "industries": [],
    "accounts": [],
    "registry_data": {},
    "user_provided_data": {},
    "confirmed_by_user_at": "2026-05-17T10:11:02Z",
    "last_console_edit_at": null,
    "is_editable": false
  },
  "ownership_structure": null,
  "warnings": []
}
```

### Documento KYB

Restituito per ogni nodo che raccoglie documenti di supporto KYB. Compare come `document_verifications[]` in `GET /v3/session/{sessionId}/decision/` per le sessioni aziendali: una voce per ogni `node_id`, con `items[]` che elenca ciascun documento caricato. Fonte: `kyb/serializers/kyb.py:1053-1068` (`DocumentVerificationV3Serializer`); ogni elemento segue `kyb/serializers/kyb.py:811-851` (`KYBDocumentResponseSerializer`).

| Campo | Tipo | Ammette null | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Stato aggregato dei documenti di questo nodo: `Approved` solo se ogni documento della pipeline è approvato; `Declined` se almeno uno è rifiutato; `In Review` negli altri casi; `Not Finished` finché è in attesa. Vedi [Enum di stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `node_id` | string \| null | Sì | Identificativo del nodo del workflow (V3). | `"first_kyb_documents"` |
| `items` | array di [oggetti documento KYB](#oggetto-voce-documento-kyb) | No | Una voce per ogni documento caricato o richiesto. | `[…]` |
| `groups` | object | No | Conteggi per gruppo di documenti: `{ <group_name>: { total, approved, pending, declined, in_review, other, missing } }`. | `{ "incorporation_certificate": { "total": 1, "approved": 1, "pending": 0, "declined": 0, "in_review": 0, "other": 0, "missing": 0 } }` |
| `required_groups` | array di stringhe | No | Gruppi di documenti richiesti dalla configurazione del workflow. | `["incorporation_certificate", "shareholder_register"]` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

#### Oggetto voce documento KYB

| Campo | Tipo | Nullable | Descrizione |
| - | - | - | - |
| `uuid` | string (UUID) | No | Identificativo interno del documento. |
| `document_type` | string | Sì | Gruppo di alto livello (`incorporation_certificate`, `shareholder_register`, …). |
| `document_subtype` | string | Sì | Sottotipo specifico del provider. |
| `document_group` | string | Sì | Rispecchiamento di `document_type` (alias mantenuto per chiarezza). |
| `file_url` | string (URL) | Sì | URL prefirmato del file pulito. |
| `original_filename` | string | Sì | Nome del file così come caricato. |
| `file_size` | integer | Sì | Dimensione del file in byte. |
| `status` | string | No | Stato del singolo documento (`FeatureStatusChoices`). |
| `created_at` | string (ISO 8601) | No | Timestamp del caricamento. |
| `cross_check_result` | object | Sì | Esito del controllo incrociato con il registro o con altri documenti. |
| `document_metadata` | object | Sì | Stessa struttura di metadati filtrati del `document_metadata` del POA. |
| `description` | string | Sì | Descrizione fornita dal revisore o dal sistema. |
| `is_requested` | boolean | No | `true` quando il workflow prevedeva questo documento. |
| `ocr_data` | object | Sì | Campi estratti tramite OCR, quando disponibili. |
| `is_console_upload` | boolean | No | `true` quando il documento è stato caricato da un revisore dalla console (escluso dall'esito aggregato). |
| `is_confirmed` | boolean | No | `true` quando il revisore ha confermato esplicitamente il documento. |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_kyb_documents",
  "items": [
    {
      "uuid": "e1f1e2c2-cccc-4d2c-9eb6-fdc6c7c92ef9",
      "document_type": "incorporation_certificate",
      "document_subtype": "registro_mercantil_extract",
      "document_group": "incorporation_certificate",
      "file_url": "https://<media-host>/.../incorporation.pdf?signature=...",
      "original_filename": "incorporation_certificate.pdf",
      "file_size": 256412,
      "status": "Approved",
      "created_at": "2026-05-17T10:08:00Z",
      "cross_check_result": { "matches_registry_name": true, "matches_registration_number": true },
      "document_metadata": {
        "file_size": 256412,
        "content_type": "application/pdf",
        "is_signed": true,
        "is_tampered": false
      },
      "description": null,
      "is_requested": true,
      "ocr_data": { "company_name": "Sante Clinics SL", "registration_number": "B12345678" },
      "is_console_upload": false,
      "is_confirmed": true
    }
  ],
  "groups": {
    "incorporation_certificate": { "total": 1, "approved": 1, "pending": 0, "declined": 0, "in_review": 0, "other": 0, "missing": 0 }
  },
  "required_groups": ["incorporation_certificate", "shareholder_register"],
  "warnings": []
}
```

### Persona chiave KYB

Restituita per ogni nodo Persone chiave in un workflow KYB. Compare come `key_people_checks[]` in `GET /v3/session/{sessionId}/decision/` per le sessioni aziendali. Fonte: `kyb/serializers/kyb.py:967-1050` (`KeyPeopleCheckV3Serializer`).

| Campo | Tipo | Nullable | Descrizione | Esempio |
| - | - | - | - | - |
| `status` | string | No | Vedi [Enum di stato](#riferimento-agli-enum-di-stato). | `"Approved"` |
| `node_id` | string \| null | Sì | Identificativo del nodo del workflow (V3). | `"first_key_people"` |
| `registry` | object | No | `{ officers[], beneficial_owners[] }` estratti dal registro delle imprese. I dirigenti seguono `KYBPersonResponseSerializer` (`kyb/serializers/kyb.py:533-645`); i titolari effettivi seguono `KYBBeneficialOwnerResponseSerializer` (`kyb/serializers/kyb.py:648-788`, che aggiunge `date_of_birth`, `country_of_birth`, `email`, `company_name`, `registration_number`, `entity_type`, `roles`, `ownership_min_shares`, `ownership_max_shares`, `child_beneficial_owners`, `effective_ownership_percent`). Entrambi includono l'arricchimento AML e KYC per ogni soggetto (`aml_status`, `kyc_status`, `kyc_session_url`, `kyc_session_id`, `verification_workflow_type`, `verification_workflow_id`, `verification_workflow_label`, `verification_workflow_features`, `didit_internal_id`, `kyc_document_type`, `kyc_nationality`, `kyc_liveness_passed`, `kyc_verified_at`, `kyc_aml_categories`, `kyc_notification_sent_at`). | `{ "officers": [...], "beneficial_owners": [...] }` |
| `submitted` | object | No | `{ parties[] }`: voci che l'azienda ha confermato o inviato tramite il flusso Persone chiave (righe `BusinessParty` con `source=USER`). Ogni soggetto segue `BusinessPartySubmissionResponseSerializer` (`kyb/serializers/party.py:146-194`): `uuid`, `entity_type`, `source`, `name`, `first_name`, `last_name`, `company_name`, `registration_number`, `email`, `nationality`, `phone_number`, `date_of_birth`, `position`, `custom_fields`, `is_active`, `is_skipped`, `requires_verification`, `roles[]` (`{ role, ownership_percent, voting_percent }`), `kyc_session_id`, `kyc_session_status`, `kyc_session_url`, `kyc_session_deleted`, `kyb_sub_session_id`, `kyb_sub_session_status`, `kyb_sub_session_url`, `kyb_sub_session_deleted`, `verification_workflow_type`, `verification_workflow_id`, `verification_workflow_label`, `verification_workflow_features`, `didit_internal_id`. `kyc_session_deleted` / `kyb_sub_session_deleted` indicano una sotto-sessione figlia eliminata: il suo stato resta congelato su quello che aveva, il corrispondente `*_session_url` torna `null` perché il link non è più risolvibile, e il soggetto smette di bloccare la sessione padre (il controllo passa a `In Review`). Per azzerare questo valore usa [`PATCH /v3/session/{id}/kyb/parties/{party_uuid}/`](https://docs.didit.me/it/sessions-api/update-data#escludere-una-parte-della-sezione-key-people). | `{ "parties": [...] }` |
| `ubo_kyc_summary` | object | Sì | Conteggi tra i titolari effettivi attivi con KYC collegato: `{ total, approved, flagged, pending }`. `null` quando nessun titolare effettivo attivo ha un KYC collegato. | `{ "total": 2, "approved": 2, "flagged": 0, "pending": 0 }` |
| `warnings` | array | No | Vedi [Oggetto avviso](#oggetto-avviso). | `[]` |

```json theme={null}
{
  "status": "Approved",
  "node_id": "first_key_people",
  "registry": {
    "officers": [
      {
        "uuid": "c1f1e2c2-aaaa-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "designation": "Administrador único",
        "role": "Director",
        "nationality": "ESP",
        "appointment_date": "2018-03-22",
        "termination_date": null,
        "is_active": true,
        "address": "Calle Mayor 1, 28001 Madrid",
        "aml_status": "Approved",
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "kyc_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
        "verification_workflow_type": "kyc",
        "verification_workflow_id": "11111111-1111-1111-1111-111111111111",
        "verification_workflow_label": "KYB officer KYC",
        "verification_workflow_features": [
          { "feature": "ID_VERIFICATION", "status": "Approved" },
          { "feature": "LIVENESS", "status": "Approved" },
          { "feature": "FACE_MATCH", "status": "Approved" }
        ],
        "didit_internal_id": "user-12345",
        "kyc_document_type": "Passport",
        "kyc_nationality": "ESP",
        "kyc_liveness_passed": true,
        "kyc_verified_at": "2026-05-17T10:10:11Z",
        "kyc_aml_categories": [],
        "kyc_notification_sent_at": "2026-05-15T08:00:00Z"
      }
    ],
    "beneficial_owners": []
  },
  "submitted": {
    "parties": [
      {
        "uuid": "d1f1e2c2-bbbb-4d2c-9eb6-fdc6c7c92ef9",
        "entity_type": "person",
        "source": "USER",
        "name": "María García López",
        "first_name": "María",
        "last_name": "García López",
        "company_name": null,
        "registration_number": null,
        "email": "maria.garcia@example.com",
        "nationality": "ESP",
        "phone_number": null,
        "date_of_birth": "1990-05-12",
        "position": "Administrador único",
        "custom_fields": {},
        "is_active": true,
        "is_skipped": false,
        "requires_verification": true,
        "roles": [
          { "role": "UBO", "ownership_percent": 75.0, "voting_percent": null }
        ],
        "kyc_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
        "kyc_session_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "kyb_sub_session_id": null,
        "kyb_sub_session_status": null,
        "kyb_sub_session_url": null,
        "verification_workflow_type": "kyc",
        "verification_workflow_id": "11111111-1111-1111-1111-111111111111",
        "verification_workflow_label": "KYB officer KYC",
        "verification_workflow_features": [
          { "feature": "ID_VERIFICATION", "status": "Approved" },
          { "feature": "LIVENESS", "status": "Approved" }
        ],
        "didit_internal_id": "user-12345"
      }
    ]
  },
  "ubo_kyc_summary": { "total": 1, "approved": 1, "flagged": 0, "pending": 0 },
  "warnings": []
}
```

## Campi a livello di decisione

Queste chiavi si trovano accanto agli array delle funzionalità in `GET /v3/session/{sessionId}/decision/` e all'interno del campo `decision` di un webhook.

| Campo | Tipo | Nullable | Descrizione |
| - | - | - | - |
| `status_override` | object | Sì | `{ overridden_at, automatic_status }` dopo che un revisore ha impostato `status` manualmente; `null` quando lo stato è quello automatico. |
| `decision_trace` | object | No | Come si è arrivati allo stato: `status`, `decided_by` (`manual`, `automatic` o `investigator`), `decided_at`, `automatic_status`, `terminal_node_id`, `actor`, `warning_counts` e `status_warnings`. |
| `linked_records` | object | Sì | Riepiloghi di `same_face`, `earlier_verifications` e `networks`; `null` quando non c'è nulla da mostrare. |
| `biometric_retention` | object | No | `{ jurisdictions, deletes_at }`. `deletes_at` è la data in cui vengono eliminati i dati biometrici acquisiti in tempo reale della sessione, e `null` quando non si applica ancora alcuna data. |
| `database_validation_not_performed_reason` | object | Sì | `{ code, message }` che spiega perché una validazione su database configurata non ha prodotto alcun risultato. |
| `assignee`, `waiting_since`, `sla_due_at` | object, datetime | Sì | Il revisore della Console a cui è assegnata la sessione e il relativo timer di revisione; il timer è `null` a meno che la sessione non sia `In Review`. |
| `shared_from_session`, `shared_from_session_number` | UUID, integer | Sì | La sessione di origine di una sessione importata. |
| `sandbox_scenario` | string | Sì | Lo scenario con cui è stata creata una sessione sandbox. |
| `fraud_check` | object | Sì | Il risultato della Fraud Check API; `null` per tutte le altre sessioni. |
| `full_session_video`, `full_session_video_recorded_at` | URL, datetime | Sì | La registrazione e il momento in cui è stata effettuata. Restituiti solo quando la tua organizzazione registra il video dell'intera sessione. |

Per capire come leggerli, consulta [Recupera sessione](https://docs.didit.me/it/sessions-api/retrieve-session.md#stato-tracciamento-della-decisione-e-campi-di-revisione).

## Consenso biometrico

Ogni decisione di Verifica degli utenti e ogni webhook di sessione contiene un unico oggetto `biometric_consent` (non un array): se la sessione richiedeva un consenso biometrico esplicito, il motivo e le prove della risposta. È `null` quando la sessione non è mai stata valutata, ad esempio un workflow senza acquisizione del volto. Fonte: `BiometricConsentDecisionSerializer` (`sessions/serializers/biometric_consent.py`). Quando compare il passaggio e cosa significa ogni caso è spiegato in [Consenso biometrico](https://docs.didit.me/it/getting-started/biometric-consent.md).

I campi senza un valore registrato sono `null`, mai una stringa vuota.

| Campo | Tipo | Descrizione |
| - | - | - |
| `required` | boolean | Se la sessione deve raccogliere un consenso biometrico esplicito. Non torna mai a `false`. |
| `trigger` | string (enum) \| null | Perché il consenso è richiesto, o come è stato soddisfatto: `declared_state`, `ip_state`, `ip_unknown`, `document_issuer`, `forced` (la modalità dell'applicazione è Always), `customer_collected` (hai inviato `biometric_consent` alla creazione della sessione). `null` finché non è richiesto. |
| `status` | string (enum) | `not_required`, `pending` (richiesto, non ancora dato), `given`, `declined` (è stato registrato un rifiuto; nessuna schermata di Didit consente oggi di rifiutare). |
| `given_at` | string (ISO 8601) \| null | Quando il consenso è stato dato. Per `customer_collected`, il `given_at` che hai inviato. |
| `declined_at` | string (ISO 8601) \| null | Quando è stato registrato un rifiuto. |
| `text_version` | string \| null | ID della versione del testo del consenso a cui la persona ha risposto, o quella che hai inviato. |
| `text_hash` | string \| null | SHA-256 (esadecimale) del testo esatto mostrato, nella lingua in cui è stato mostrato. |
| `locale` | string \| null | Lingua in cui è stato mostrato il testo. |
| `policy_url` | string \| null | La policy sui dati biometrici a cui rimandava il passaggio. |
| `step` | string \| null | Passaggio del workflow su cui si trovava la sessione quando la persona ha risposto (ad esempio `LIVENESS`). |
| `node_id` | string \| null | Nodo del grafo del workflow su cui si trovava la sessione quando la persona ha risposto. |
| `ip_address` | string \| null | IP da cui proveniva la risposta. |
| `ip_country_code` | string \| null | Codice paese ISO 3166-1 alpha-2 dell'indirizzo IP da cui proviene la risposta. |
| `ip_state` | string \| null | Suddivisione ISO 3166-2 dell'IP della risposta (ad esempio `US-IL`). |
| `ip_city` | string \| null | Città dell'IP della risposta. |
| `user_agent` | string \| null | User agent della richiesta di risposta. |
| `detected_ip_address` | string \| null | IP della persona da cui il requisito è stato valutato per l'ultima volta. Può differire da `ip_address` quando la persona ha risposto su un altro dispositivo. |
| `detected_country_code` | string \| null | Codice paese ISO 3166-1 alpha-2 dell'indirizzo IP rilevato. |
| `detected_state` | string \| null | Suddivisione ISO 3166-2 dell'IP rilevato. |
| `detected_city` | string \| null | Città dell'IP rilevato. |
| `declared_state` | string \| null | Suddivisione ISO 3166-2 dichiarata da te: `user_state`, oppure lo stato di un indirizzo statunitense in `expected_details`. |
| `document_state` | string \| null | Suddivisione ISO 3166-2 che ha emesso il documento d'identità, letta durante l'acquisizione del documento. |
| `jurisdictions` | array di stringhe | Stati USA (codici USPS, ad esempio `IL`) la cui legge sui dati biometrici copre la persona. `US` quando le prove collocano la persona negli Stati Uniti ma non si conosce lo stato. Vuoto quando nessuna si applica. |
| `retention_months` | integer \| null | Il limite di conservazione dei dati biometrici più breve, in mesi, tra le `jurisdictions`. `null` quando nessuna si applica. |
| `reason` | string (enum) \| null | `BIOMETRIC_CONSENT_UNSUPPORTED_SDK`: il consenso era richiesto e un SDK nativo precedente alla 4.10.0, oppure uno che non ha riportato la propria versione, ha acquisito un volto senza il passaggio; `status` resta `pending`, oppure `given` se la persona in seguito ha acconsentito nel flusso ospitato. `BIOMETRIC_CONSENT_DECLINED`: è stato registrato un rifiuto (sostituisce il motivo dell'SDK). `null` altrimenti, e sempre `null` quando la sessione non richiedeva il consenso. |
| `decline_reason` | string \| null | `BIOMETRIC_CONSENT_DECLINED` quando un rifiuto registrato ha concluso la sessione, altrimenti `null`. |
| `face_data_deleted_at` | string (ISO 8601) \| null | Quando il rifiuto ha eliminato le immagini del volto, i video e i modelli facciali della sessione. `null` a meno che non sia stato registrato un rifiuto. |

Una sessione nell'Illinois servita da un SDK nativo precedente alla 4.10.0, che ha acquisito il selfie senza il passaggio:

```json theme={null}
{
  "required": true,
  "trigger": "ip_state",
  "status": "pending",
  "given_at": null,
  "declined_at": null,
  "text_version": null,
  "text_hash": null,
  "locale": null,
  "policy_url": null,
  "step": null,
  "node_id": null,
  "ip_address": null,
  "ip_country_code": null,
  "ip_state": null,
  "ip_city": null,
  "user_agent": null,
  "detected_ip_address": "203.0.113.42",
  "detected_country_code": "US",
  "detected_state": "US-IL",
  "detected_city": "Chicago",
  "declared_state": null,
  "document_state": null,
  "jurisdictions": ["IL"],
  "retention_months": 36,
  "reason": "BIOMETRIC_CONSENT_UNSUPPORTED_SDK",
  "decline_reason": null,
  "face_data_deleted_at": null
}
```

Una persona con una VPN che esce al di fuori degli Stati Uniti, che ha acconsentito nel flusso ospitato:

```json theme={null}
{
  "required": true,
  "trigger": "declared_state",
  "status": "given",
  "given_at": "2026-10-13T18:31:07.412000Z",
  "declined_at": null,
  "text_version": "bio-consent-2026-10-12",
  "text_hash": "9b2f0c5e4d8a7f61c3e2b4a5d6f7081923a4b5c6d7e8f90a1b2c3d4e5f6a7b8c",
  "locale": "en",
  "policy_url": "https://didit.me/legal/biometric-data-policy",
  "step": "LIVENESS",
  "node_id": "feature_liveness_1",
  "ip_address": "198.51.100.23",
  "ip_country_code": "ES",
  "ip_state": "ES-M",
  "ip_city": "Madrid",
  "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
  "detected_ip_address": "198.51.100.23",
  "detected_country_code": "ES",
  "detected_state": "ES-M",
  "detected_city": "Madrid",
  "declared_state": null,
  "document_state": null,
  "jurisdictions": ["IL"],
  "retention_months": 36,
  "reason": null,
  "decline_reason": null,
  "face_data_deleted_at": null
}
```

## Riferimento agli enum di stato

Due spazi di valori distinti condividono il nome di campo `status`. Ogni oggetto report per funzionalità in questa pagina usa l'enum a livello di funzionalità; il campo `status` di primo livello della sessione padre usa l'enum più ampio della sessione.

### Stati a livello di funzionalità

Usati dal campo `status` di ogni oggetto report. Fonte: `common/config/choices.py:343-348` (`FeatureStatusChoices`).

| Valore | Significato |
| - | - |
| `Not Finished` | La funzionalità è stata predisposta, ma l'utente non l'ha ancora completata. |
| `Approved` | La funzionalità ha superato tutti i controlli. |
| `Declined` | La funzionalità non ha superato almeno un controllo bloccante (vedi `warnings[]` con `log_type: "error"`). |
| `In Review` | La funzionalità ha attivato segnali non bloccanti ed è in attesa di revisione manuale (vedi `warnings[]` con `log_type: "warning"`). |
| `Resub Requested` | Un revisore ha chiesto all'utente di inviare di nuovo questa funzionalità. |

La verifica telefonica, la verifica email e la verifica dell'identità possono inoltre restituire `Expired` quando il loro passaggio scade (`PhoneStatusChoices` in `common/config/choices.py:377-382`, `EmailStatusChoices` in `common/config/choices.py:434-439`).

### Stati a livello di sessione

Usati dal campo `status` di primo livello della sessione padre. Fonte: `common/config/choices.py:106-117` (`StatusChoices`).

| Valore | Significato |
| - | - |
| `Not Started` | La sessione è stata creata, ma l'utente non l'ha ancora avviata. |
| `In Progress` | L'utente ha avviato il flusso; il risultato non è ancora definitivo. |
| `Approved` | La sessione ha superato tutti i controlli. |
| `Declined` | La sessione non ha superato almeno un controllo bloccante. |
| `In Review` | La sessione è in attesa di revisione manuale. |
| `Expired` | La sessione è scaduta prima del completamento. |
| `Abandoned` | L'utente ha lasciato il flusso senza completarlo. |
| `Kyc Expired` | La finestra di validità del KYC è scaduta (usato nei flussi di nuova verifica). |
| `Resubmitted` | L'utente ha reinviato i dati dopo un rifiuto precedente; questa sessione è stata sostituita da una sessione più recente. |
| `Awaiting User` | Il sistema è in attesa di un'azione dell'utente (ad esempio l'inserimento di un OTP). |

> [!TIP]
>
> I valori di sessione finali sono `Approved`, `Declined`, `In Review`, `Expired`, `Kyc Expired` e `Abandoned`. Una sessione può raggiungere la decisione complessiva mentre una singola funzionalità resta `In Review`.


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