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

# Informe de verificación de email: filtraciones y OTP

> Analiza el informe de verificación de email de Didit: ciclo del OTP, filtraciones, correos desechables o no entregables, coincidencias y advertencias.

El informe de Verificación de correo electrónico recoge el resultado completo de un desafío OTP por correo electrónico: a quién se envió el mensaje, si la dirección es desechable o no entregable, si aparece en filtraciones de datos conocidas, cuántos intentos necesitó el usuario y cualquier coincidencia entre sesiones con tu lista de bloqueo o con otros usuarios aprobados.

Esta página documenta la estructura JSON que devuelve el endpoint de decisión para que puedas analizar los resultados del OTP, la exposición a filtraciones y los indicadores de riesgo de cada dirección verificada.

![Informe de verificación de correo electrónico de Didit con el resultado del OTP, los datos de filtraciones y los indicadores de riesgo](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/email-verification-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=4d153b7d3d9d4c88bc3932466af7ed29)

## Descripción general

Se genera un informe de correo electrónico cada vez que un nodo de un flujo de verificación (workflow) ejecuta la función de Verificación de correo electrónico. Cada informe representa un desafío OTP para una dirección y contiene:

* La dirección `email` verificada.
* Indicadores de riesgo booleanos (`is_breached`, `is_disposable`, `is_undeliverable`) y el array `breaches[]` que los respalda, obtenido de una base de datos de inteligencia sobre filtraciones.
* El número de intentos de envío del OTP (`verification_attempts`) y la marca de tiempo de aprobación.
* Un registro cronológico `lifecycle[]` de cada envío, reintento e intento de comprobación del código.
* Un array `matches[]` que muestra la misma dirección en otras verificaciones de correo electrónico aprobadas o en tu lista de bloqueo.
* Un array `warnings[]` con los eventos de riesgo emitidos durante la verificación (consulta [Advertencias de la Verificación de correo electrónico](https://docs.didit.me/es/core-technology/email-verification/warnings-email-verification.md)).
* Un `node_id` que identifica qué nodo del grafo del flujo generó el informe (solo en sesiones V3).

En las sesiones de flujos alojados, el desafío OTP se ejecuta dentro de la interfaz de verificación de Didit: solo tienes que leer el resultado del payload de la decisión. Para un OTP de servidor a servidor sin un flujo alojado, usa la API de correo electrónico independiente: [`POST /v3/email/send/`](https://docs.didit.me/es/standalone-apis/email-send) envía el código y [`POST /v3/email/check/`](https://docs.didit.me/es/standalone-apis/email-check) valida la entrada del usuario. Las verificaciones independientes finalizadas siguen la misma estructura de informe.

De forma predeterminada, las sesiones alojadas limitan al usuario a **2 intentos incorrectos de introducir el código** (`email_max_check_attempts`) y a **2 envíos de OTP: el envío inicial más un reenvío** (`email_max_retries`), valores que se pueden ajustar en cada nodo del flujo. Superar cualquiera de los dos límites finaliza el paso como `Declined` con `EMAIL_CODE_ATTEMPTS_EXCEEDED`.

## Dónde aparece en las respuestas de la API

El endpoint de decisión (`GET /v3/session/{sessionId}/decision/`) devuelve los informes de verificación de correo electrónico con la clave de array en plural **`email_verifications`**. El array contiene una entrada por cada nodo de Verificación de correo electrónico del grafo del flujo: normalmente una, pero los flujos de verificación reforzada (step-up) pueden generar varias.

```json theme={null}
{
  "session_id": "11111111-1111-1111-1111-111111111111",
  "status": "Approved",
  "email_verifications": [
    { "node_id": "feature_email_1", "status": "Approved", "...": "..." }
  ]
}
```

Un valor `null` significa que todavía no se ha ejecutado ningún paso de Verificación de correo electrónico. Recorre el array (en lugar de leer `email_verifications[0]`) cuando tu flujo pueda recopilar más de una dirección de correo electrónico.

## Esquema

El esquema de referencia, campo por campo, está en la página [Modelos de datos](https://docs.didit.me/es/reference/data-models.md#verificación-de-correo-electrónico).

```typescript theme={null}
interface EmailVerification {
  node_id: string | null;
  status: "Not Finished" | "Approved" | "Declined" | "In Review" | "Expired";
  email: string;
  is_breached: boolean;
  breaches: Breach[];                // Up to the 5 most recent known breaches
  is_disposable: boolean;            // Disposable / throwaway provider
  is_undeliverable: boolean;         // Failed syntax / DNS (MX) validation or OTP delivery
  verification_attempts: number;     // OTP send attempts
  verified_at: string | null;        // ISO 8601, null until a valid code is entered
  lifecycle: EmailLifecycleEvent[];  // OTP send/retry/check timeline
  warnings: Warning[];               // Risk events (see Data models → Warning object)
  matches: EmailMatch[];             // Cross-session / blocklist matches
}

interface Breach {
  name: string;                      // Breached service name
  domain: string;                    // Affected domain
  breach_date: string;               // YYYY-MM-DD
  breach_emails_count: number;       // Total affected accounts
  description: string;               // HTML description of the breach
  logo_path: string;                 // Breached-service logo URL
  data_classes: string[];            // Exposed data categories (snake_case)
  is_verified: boolean;              // true when the breach is a verified incident
}
```

Una dirección que no puede recibir correo (sintaxis no válida, dominio inexistente, registros MX ausentes o un envío de OTP fallido) cierra el paso como **`Declined`** con la advertencia de rechazo automático `UNDELIVERABLE_EMAIL_DETECTED`. La única excepción: cuando el usuario escribió la dirección él mismo (no venía rellenada al crear la sesión), un envío no entregable devuelve un error en línea para que pueda reintentar con otra dirección, en lugar de rechazarlo de inmediato.

### Valores de estado

| Estado | Significado |
| - | - |
| `Not Finished` | Se ha iniciado el envío del OTP, pero la verificación aún no se ha cerrado. |
| `Approved` | El usuario introdujo un OTP válido y no coincidió ningún riesgo que implique rechazo. |
| `Declined` | Se activó una advertencia de rechazo automático (lista de bloqueo, dirección no entregable, intentos superados) o coincidió un riesgo cuya acción está configurada como `DECLINE`. |
| `In Review` | Un riesgo cuya acción está configurada como `REVIEW` envió el paso a revisión manual. |
| `Expired` | Pasó la ventana de 5 minutos del OTP sin un código válido. Se aplica a las verificaciones creadas con la API de correo electrónico independiente. |

### Tipos de eventos del ciclo de vida

`lifecycle[]` está ordenado cronológicamente. Cada evento tiene `type`, `timestamp`, `details` y un cargo facturable `fee` (cuando corresponde):

| Tipo de evento | Se emite cuando |
| - | - |
| `EMAIL_VERIFICATION_MESSAGE_SENT` | Primer intento de envío del OTP, incluidos los envíos que resultan no entregables. |
| `EMAIL_VERIFICATION_RETRY_MESSAGE_SENT` | Envío posterior del OTP después de que el usuario solicitara un reenvío. |
| `VALID_CODE_ENTERED` | El usuario envió el código OTP correcto. |
| `INVALID_CODE_ENTERED` | El usuario envió un código OTP incorrecto o expirado (cuenta para el límite de intentos). |
| `EMAIL_VERIFICATION_APPROVED` | El estado de la función pasó a `Approved`. |
| `EMAIL_VERIFICATION_DECLINED` | El estado de la función pasó a `Declined`. |
| `EMAIL_VERIFICATION_IN_REVIEW` | El estado de la función pasó a `In Review`. |
| `EMAIL_VERIFICATION_EXPIRED` | Pasó la ventana del OTP sin un código válido (API de correo electrónico independiente). |

El payload de `details` depende de la familia del evento:

* **Eventos de envío** (`EMAIL_VERIFICATION_MESSAGE_SENT`, `EMAIL_VERIFICATION_RETRY_MESSAGE_SENT`): `{ status, reason }`. `status` es `Success`, `Retry` o `Undeliverable`; `reason` es `null` salvo que el envío haya fallado (`email_can_not_be_delivered`, o `unknown` para valores heredados no reconocidos).
* **Eventos de comprobación** (`VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`): `{ code_tried, status }`, con `status` igual a `Approved`, `Failed`, `Expired or Not Found` o `Declined`.
* **Eventos de estado final**: `null`, excepto `EMAIL_VERIFICATION_DECLINED` / `EMAIL_VERIFICATION_IN_REVIEW`, que incluyen `{ "reason": "<risk code>" }` (por ejemplo, `UNDELIVERABLE_EMAIL_DETECTED`).

Los envíos con `status` `Success` o `Undeliverable` registran la tarifa de Verificación de correo electrónico de \$0.02; los envíos `Retry`, los eventos de comprobación y los eventos de estado siempre llevan `fee: 0`.

### Coincidencias entre sesiones

`matches[]` registra la misma dirección en verificaciones de correo electrónico **aprobadas anteriormente** dentro de la misma aplicación (en sesiones de KYC, KYB y de la API independiente), además de las coincidencias con la lista de bloqueo configuradas en las [listas de la API de gestión](https://docs.didit.me/es/management-api/lists/overview.md). Se excluyen las verificaciones que comparten el `vendor_data` de la sesión actual (el mismo usuario final no coincide consigo mismo); el array tiene un máximo de **5** entradas, ordenadas de la más antigua a la más reciente. Cuando la dirección está en tu lista de bloqueo, pero ninguna de las sesiones coincidentes figura en la lista de bloqueo, se añade al principio del array una entrada sintética con `source: "list_entry"` (con todos los campos de sesión en `null`).

```typescript theme={null}
interface EmailMatch {
  session_id: string | null;         // null when source = "list_entry"
  session_number: number | null;
  vendor_data: string | null;
  verification_date: string | null;  // ISO 8601, creation date of the matched session
  email: string;
  status: string | null;             // Status of the matched session
  is_blocklisted: boolean;
  api_service: string | null;        // Set when the matched session came from a standalone API
  source: "session" | "list_entry";  // "list_entry" = manual blocklist hit
}
```

## Ejemplos

### Aprobado: OTP correcto con un incumplimiento de nivel informativo

```json theme={null}
{
  "node_id": "feature_email_1",
  "status": "Approved",
  "email": "alex.sample@example.com",
  "is_breached": true,
  "breaches": [
    {
      "name": "ExampleAir",
      "domain": "example-air.com",
      "breach_date": "2022-08-25",
      "breach_emails_count": 6083479,
      "description": "In August 2022, the airline ExampleAir suffered a data breach that exposed customers' personal information.",
      "logo_path": "https://<media-host>/logos/ExampleAir.png",
      "data_classes": [
        "dates_of_birth", "email_addresses", "genders", "names",
        "nationalities", "phone_numbers", "physical_addresses",
        "salutations", "spoken_languages"
      ],
      "is_verified": true
    }
  ],
  "is_disposable": false,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2025-09-15T17:36:19.963451Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-09-15T17:35:50.000000+00:00",
      "details": { "status": "Success", "reason": null },
      "fee": 0.02
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2025-09-15T17:36:19.000000+00:00",
      "details": { "code_tried": "123456", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_APPROVED",
      "timestamp": "2025-09-15T17:36:19.963451+00:00",
      "details": null,
      "fee": 0
    }
  ],
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "BREACHED_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "information",
      "short_description": "Breached email detected",
      "long_description": "This email address was found in one or more known data breaches.",
      "node_id": "feature_email_1"
    }
  ],
  "matches": []
}
```

### Rechazado: dirección no entregable

Una dirección precompletada que no supera la validación de sintaxis o de DNS (MX), o cuyo correo con el OTP no se puede entregar, se cierra de inmediato como `Declined`. No aparecen eventos de comprobación de código porque ningún código llegó al usuario.

```json theme={null}
{
  "node_id": "feature_email_1",
  "status": "Declined",
  "email": "user@nonexistent-domain.example",
  "is_breached": false,
  "breaches": [],
  "is_disposable": false,
  "is_undeliverable": true,
  "verification_attempts": 1,
  "verified_at": null,
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-09-15T18:00:00.000000+00:00",
      "details": { "status": "Undeliverable", "reason": "email_can_not_be_delivered" },
      "fee": 0.02
    },
    {
      "type": "EMAIL_VERIFICATION_DECLINED",
      "timestamp": "2025-09-15T18:00:01.500000+00:00",
      "details": { "reason": "UNDELIVERABLE_EMAIL_DETECTED" },
      "fee": 0
    }
  ],
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "UNDELIVERABLE_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "error",
      "short_description": "Undeliverable email detected",
      "long_description": "The system detected that the email is undeliverable, which is not allowed.",
      "node_id": "feature_email_1"
    }
  ],
  "matches": []
}
```

### Rechazado: buzón desechable en la lista de bloqueo

El usuario completó el OTP, pero la dirección coincidió con tu lista de bloqueo de correos electrónicos (rechazo automático). También se activa el indicador de correo desechable, aquí con nivel `information` porque `disposable_email_action` se mantiene en su valor predeterminado `NO_ACTION`.

```json theme={null}
{
  "node_id": "feature_email_1",
  "status": "Declined",
  "email": "user@mailinator.com",
  "is_breached": false,
  "breaches": [],
  "is_disposable": true,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2025-09-15T18:05:42.201734Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-09-15T18:05:01.000000+00:00",
      "details": { "status": "Success", "reason": null },
      "fee": 0.02
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2025-09-15T18:05:42.000000+00:00",
      "details": { "code_tried": "654321", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_DECLINED",
      "timestamp": "2025-09-15T18:05:42.201734+00:00",
      "details": { "reason": "EMAIL_IN_BLOCKLIST" },
      "fee": 0
    }
  ],
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "EMAIL_IN_BLOCKLIST",
      "additional_data": {
        "blocklisted_session_id": null,
        "blocklisted_session_number": null,
        "api_service": null
      },
      "log_type": "error",
      "short_description": "Email in blocklist",
      "long_description": "The system detected that the email is in the blocklist, which is not allowed.",
      "node_id": "feature_email_1"
    },
    {
      "feature": "EMAIL",
      "risk": "DISPOSABLE_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "information",
      "short_description": "Disposable email detected",
      "long_description": "The system detected that the email is disposable, which is not allowed.",
      "node_id": "feature_email_1"
    }
  ],
  "matches": [
    {
      "session_id": null,
      "session_number": null,
      "vendor_data": null,
      "verification_date": null,
      "email": "user@mailinator.com",
      "status": null,
      "is_blocklisted": true,
      "api_service": null,
      "source": "list_entry"
    }
  ]
}
```

## Relacionado

* [Visión general de la Verificación de correo electrónico](https://docs.didit.me/es/core-technology/email-verification/overview.md): comportamiento de la función y precios.
* [Advertencias de la Verificación de correo electrónico](https://docs.didit.me/es/core-technology/email-verification/warnings-email-verification.md): todos los códigos de riesgo, los disparadores de rechazo y las acciones configurables.
* [Modelos de datos: verificación de correo electrónico](https://docs.didit.me/es/reference/data-models.md#verificación-de-correo-electrónico): esquema de referencia campo por campo.
* [API de correo electrónico: enviar OTP](https://docs.didit.me/es/standalone-apis/email-send.md) y [comprobar OTP](https://docs.didit.me/es/standalone-apis/email-check.md): endpoints independientes de servidor a servidor.
* [API de gestión: listas](https://docs.didit.me/es/management-api/lists/overview.md): gestiona la lista de bloqueo de correos electrónicos que genera coincidencias en `matches[]` con `source: list_entry`.


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