> ## 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 telefónica: JSON, OTP y operador

> Informe telefónico de Didit: operador, tipo de línea, ciclo OTP, coincidencias y advertencias de riesgo. Desde $0.02/OTP + tarifas del operador.

El informe de Verificación de teléfono recoge el resultado completo de un desafío OTP por teléfono: a quién enviamos el código, qué operador y qué canal lo gestionaron, cuántos intentos fueron necesarios, si el número es desechable o VoIP, y las coincidencias entre sesiones con tu lista de bloqueo o con sesiones de otros usuarios.

Esta página documenta la estructura JSON que devuelve el endpoint de decisión, para que puedas procesar los resultados del desafío OTP, los metadatos del operador y los indicadores de riesgo de cada número verificado.

![Informe de verificación de teléfono de Didit con el resultado del OTP, los metadatos del operador y los indicadores de riesgo](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/phone-verification-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=9b5c6c6112303ebc60c0f287aafdb996)

## Descripción general

Se genera un informe de teléfono cada vez que un nodo de un flujo de verificación (workflow) ejecuta la función de Verificación de teléfono. Cada informe corresponde a un desafío OTP para un número de teléfono y contiene:

* El número de teléfono desglosado en prefijo, número nacional y formato E.164 completo, junto con el código de país ISO y el nombre del país.
* Metadatos del operador (`name`, `type`) obtenidos a partir de la red de destino.
* Indicadores de riesgo booleanos (`is_disposable`, `is_virtual`) derivados del análisis del tipo de línea.
* El canal de entrega utilizado realmente (`verification_method`) y el número de intentos de envío del OTP.
* Un registro cronológico `lifecycle[]` de cada envío, reintento, evento de entrega e intento de comprobación del código.
* Un array `matches[]` que muestra el mismo número en otras sesiones (con cualquier estado, en verificaciones KYC, KYB y de API independiente) o en tu lista de bloqueo.
* Un array `warnings[]` con los eventos de riesgo emitidos durante la verificación (consulta [Advertencias de Verificación de teléfono](https://docs.didit.me/es/core-technology/phone-verification/warnings-phone-verification.md)).
* Un `node_id` que identifica qué nodo del grafo del flujo generó el informe (solo en sesiones V3).

En los flujos de verificación alojados, Didit gestiona el intercambio del OTP por ti. En las integraciones directas con la API, el mismo flujo se resuelve con dos llamadas: [`POST /v3/phone/send/`](https://docs.didit.me/es/standalone-apis/phone-send) para enviar el código y [`POST /v3/phone/check/`](https://docs.didit.me/es/standalone-apis/phone-check) para validar lo que introduce el usuario. Un OTP pendiente es válido durante **5 minutos desde el primer envío** (los reintentos no amplían ese plazo). En las sesiones de flujo, los usuarios disponen por defecto de 2 intentos de envío del OTP (`phone_max_retries`) y 2 intentos de introducción del código (`phone_max_check_attempts`), ambos configurables por nodo del flujo; agotar cualquiera de los dos límites finaliza el paso como `Declined` con `VERIFICATION_CODE_ATTEMPTS_EXCEEDED`. La API de teléfono independiente permite 3 intentos de introducción del código por verificación.

## 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 telefónica bajo la clave de array en plural **`phone_verifications`**. El array contiene una entrada por cada nodo de Verificación de teléfono del grafo del flujo; normalmente es una, pero los flujos de verificación reforzada pueden generar varias.

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

Un valor `null` significa que todavía no se ha ejecutado ningún paso de Verificación de teléfono. Recorre el array (en lugar de leer `phone_verifications[0]`) cuando tu flujo pueda recopilar más de un número de teléfono.

## Esquema

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

```typescript theme={null}
interface PhoneVerification {
  status: "Not Finished" | "Approved" | "Declined" | "In Review" | "Expired";
  phone_number_prefix: string;       // E.g. "+34"
  phone_number: string;              // National number, no prefix
  full_number: string;               // Full E.164, e.g. "+34600600600"
  country_code: string;              // ISO 3166-1 alpha-2, e.g. "ES"
  country_name: string;
  carrier: {
    name: string;
    type:                              // From LineTypeChoices
      | "mobile" | "fixed_line" | "voip" | "isp" | "vpn"
      | "toll_free" | "premium_rate" | "shared_cost" | "local_rate"
      | "satellite" | "pager" | "payphone" | "voice_mail"
      | "calling_cards" | "service" | "short_codes_commercial"
      | "universal_access" | "other" | "unknown";
  };
  is_disposable: boolean;            // Temporary / burner number
  is_virtual: boolean;               // true when carrier.type is voip, isp or vpn
  verification_method:               // Actual channel that delivered the OTP
    | "sms" | "whatsapp" | "telegram" | "voice" | "rcs" | "viber" | "zalo";
  verification_attempts: number;     // OTP send attempts (initial send + resends)
  verified_at: string | null;        // ISO 8601, set when a valid OTP was entered
  warnings: Warning[];               // Risk events emitted during verification
  lifecycle: PhoneLifecycleEvent[];  // OTP send/retry/delivery/check timeline
  matches: PhoneMatch[];             // Cross-session / blocklist matches (max 5)
  node_id: string;                   // Workflow graph node that produced this report
}
```

### Valores de estado

| Estado | Significado |
| - | - |
| `Not Finished` | Se inició el envío del OTP, pero la verificación aún no ha finalizado. |
| `Approved` | El usuario introdujo un OTP válido y no coincidió ningún riesgo que provoque el rechazo. |
| `Declined` | Se activó una advertencia de rechazo automático (lista de bloqueo, alto riesgo, intentos superados) o coincidió una acción de riesgo configurada como `DECLINE`. |
| `In Review` | Una acción de riesgo configurada como `REVIEW` dirigió el paso a revisión manual. |
| `Expired` | Transcurrió la ventana de 5 minutos del OTP sin un código válido. Se aplica a las verificaciones creadas mediante la API de teléfono independiente. |

### Tipos de eventos del ciclo de vida

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

| Tipo de evento | Se emite cuando |
| - | - |
| `PHONE_VERIFICATION_MESSAGE_SENT` | Primer intento de envío del OTP por el canal solicitado. |
| `PHONE_VERIFICATION_RETRY_MESSAGE_SENT` | Envío posterior del OTP después de que el usuario solicitara un reenvío. |
| `PHONE_VERIFICATION_BLOCKED` | El envío se bloqueó (spam, sospechoso, repetido, número no válido). |
| `PHONE_DELIVERY_DELIVERED` | El operador confirmó la entrega por el canal realmente utilizado. |
| `PHONE_DELIVERY_UNDELIVERABLE` | El operador informó que no se pudo entregar el mensaje. |
| `VALID_CODE_ENTERED` | El usuario envió el código OTP correcto. |
| `INVALID_CODE_ENTERED` | El usuario envió un código OTP incorrecto (cuenta para el límite de introducción de códigos). |
| `PHONE_VERIFICATION_APPROVED` | El estado a nivel de función se estableció en `Approved`. |
| `PHONE_VERIFICATION_DECLINED` | El estado a nivel de función se estableció en `Declined`. |
| `PHONE_VERIFICATION_IN_REVIEW` | El estado a nivel de función se estableció en `In Review`. |
| `PHONE_VERIFICATION_EXPIRED` | La ventana del OTP transcurrió sin un código válido. |

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

* **Eventos de envío** (`PHONE_VERIFICATION_MESSAGE_SENT`, `PHONE_VERIFICATION_RETRY_MESSAGE_SENT`, `PHONE_VERIFICATION_BLOCKED`): `{ status, reason, channel, actual_channel }`. `status` es `Success`, `Retry` o `Blocked`; `reason` es `null` salvo que el envío se haya bloqueado (`invalid_phone_number`, `repeated_attempts`, `suspicious`, `spam`, `unknown`); `channel` es el canal solicitado y `actual_channel` el canal por el que se realizó la entrega (por ejemplo, un envío por WhatsApp que recurrió a SMS).
* **Eventos de entrega** (`PHONE_DELIVERY_DELIVERED`, `PHONE_DELIVERY_UNDELIVERABLE`): `{ channel, status }` con `status` `delivered` o `undeliverable`.
* **Eventos de comprobación** (`VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`): `{ code_tried, status }` con `status` `Approved`, `Declined`, `Failed` o `Expired or Not Found`.
* **Eventos de estado final**: `null`, excepto `PHONE_VERIFICATION_DECLINED` / `PHONE_VERIFICATION_IN_REVIEW`, que incluyen `{ "reason": "<risk code>" }` (por ejemplo, `PHONE_NUMBER_IN_BLOCKLIST`).

`fee` en un evento de envío es el precio total de ese envío: el precio del operador o de WhatsApp más la tarifa de Didit de $0.02, o solo la tarifa de Didit de $0.02 para un código de WhatsApp enviado desde [tu propio número de WhatsApp Business](https://docs.didit.me/es/core-technology/phone-verification/overview.md#envía-los-códigos-de-whatsapp-desde-tu-propio-número). Es el precio estimado hasta que se confirma la entrega y, a partir de ese momento, el importe realmente facturado. Solo los envíos `Blocked` son gratuitos con garantía: cualquier otro envío se cobra cuando la verificación finaliza o expira, aunque nunca se haya confirmado la entrega o el mensaje no se haya podido entregar. Los eventos de entrega, de comprobación y de estado siempre incluyen `fee: 0`.

### Coincidencias entre sesiones

`matches[]` registra otras sesiones de la misma aplicación en las que se vio el mismo número (en verificaciones KYC, KYB y mediante la API de teléfono independiente, sea cual sea su estado), además de las coincidencias con la lista de bloqueo configurada en las [listas de la management API](https://docs.didit.me/es/management-api/lists/overview.md). Se excluyen las sesiones que comparten el `vendor_data` de la sesión actual (el mismo usuario final no coincide consigo mismo) y el array está limitado a **5** entradas. Cuando el número está en tu lista de bloqueo pero ninguna de las sesiones coincidentes está en ella, se antepone al array una entrada sintética con `source: "list_entry"` (con todos los campos de sesión en `null`).

```typescript theme={null}
interface PhoneMatch {
  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
  phone_number: 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 por WhatsApp, operador móvil

```json theme={null}
{
  "status": "Approved",
  "phone_number_prefix": "+34",
  "phone_number": "600600600",
  "full_number": "+34600600600",
  "country_code": "ES",
  "country_name": "Spain",
  "carrier": { "name": "Orange", "type": "mobile" },
  "is_disposable": false,
  "is_virtual": false,
  "verification_method": "whatsapp",
  "verification_attempts": 1,
  "verified_at": "2025-08-24T09:12:39.684292Z",
  "warnings": [],
  "lifecycle": [
    {
      "type": "PHONE_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-08-24T09:12:30.580554Z",
      "details": { "status": "Success", "reason": null, "channel": "whatsapp", "actual_channel": "whatsapp" },
      "fee": 0.0509
    },
    {
      "type": "PHONE_DELIVERY_DELIVERED",
      "timestamp": "2025-08-24T09:12:31.000000Z",
      "details": { "channel": "whatsapp", "status": "delivered" },
      "fee": 0
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2025-08-24T09:12:39.662157Z",
      "details": { "code_tried": "123456", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "PHONE_VERIFICATION_APPROVED",
      "timestamp": "2025-08-24T09:12:39.684292Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "feature_phone_1"
}
```

### Rechazado: número VoIP en la lista de bloqueo

El usuario introdujo un OTP válido, pero al finalizar se encontró el número en la lista de bloqueo de la aplicación (rechazo automático) y se marcó su tipo de línea VoIP (`voip_number_action` se dejó en `NO_ACTION`, por lo que se registra como `information`). Como ninguna sesión coincidente está en la lista de bloqueo, la coincidencia con la lista de bloqueo aparece como una coincidencia sintética `list_entry`.

```json theme={null}
{
  "status": "Declined",
  "phone_number_prefix": "+1",
  "phone_number": "5551234567",
  "full_number": "+15551234567",
  "country_code": "US",
  "country_name": "United States",
  "carrier": { "name": "VoIP Carrier", "type": "voip" },
  "is_disposable": false,
  "is_virtual": true,
  "verification_method": "sms",
  "verification_attempts": 1,
  "verified_at": "2025-08-24T09:11:10.221340Z",
  "warnings": [
    {
      "feature": "PHONE",
      "risk": "PHONE_NUMBER_IN_BLOCKLIST",
      "additional_data": { "blocklisted_session_id": null, "blocklisted_session_number": null, "api_service": null },
      "log_type": "error",
      "short_description": "Phone number in blocklist",
      "long_description": "The system detected that the phone number is in the blocklist, which is not allowed.",
      "node_id": "feature_phone_1"
    },
    {
      "feature": "PHONE",
      "risk": "VOIP_NUMBER_DETECTED",
      "additional_data": null,
      "log_type": "information",
      "short_description": "VoIP number detected",
      "long_description": "The system detected that the phone number is a VoIP number, which is not allowed.",
      "node_id": "feature_phone_1"
    }
  ],
  "lifecycle": [
    {
      "type": "PHONE_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-08-24T09:11:00.000000Z",
      "details": { "status": "Success", "reason": null, "channel": "sms", "actual_channel": "sms" },
      "fee": 0.0509
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2025-08-24T09:11:10.221340Z",
      "details": { "code_tried": "482917", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "PHONE_VERIFICATION_DECLINED",
      "timestamp": "2025-08-24T09:11:10.350000Z",
      "details": { "reason": "PHONE_NUMBER_IN_BLOCKLIST" },
      "fee": 0
    }
  ],
  "matches": [
    {
      "session_id": null,
      "session_number": null,
      "vendor_data": null,
      "verification_date": null,
      "phone_number": "+15551234567",
      "status": null,
      "is_blocklisted": true,
      "api_service": null,
      "source": "list_entry"
    }
  ],
  "node_id": "feature_phone_1"
}
```

## Relacionado

* [Descripción general de la verificación de teléfono](https://docs.didit.me/es/core-technology/phone-verification/overview.md): comportamiento de la función, precios y canales compatibles.
* [Advertencias de la verificación de teléfono](https://docs.didit.me/es/core-technology/phone-verification/warnings-phone-verification.md): todos los códigos de riesgo, factores que desencadenan un rechazo y acciones configurables.
* [Modelos de datos: verificación de teléfono](https://docs.didit.me/es/reference/data-models.md#verificación-de-teléfono): esquema canónico campo por campo.
* [API de teléfono independiente](https://docs.didit.me/es/standalone-apis/phone-send.md): endpoints `POST /v3/phone/send/` y [`POST /v3/phone/check/`](https://docs.didit.me/es/standalone-apis/phone-check).
* [Management API: listas](https://docs.didit.me/es/management-api/lists/overview.md): gestiona la lista de bloqueo de teléfonos que alimenta `matches[]` con `source: list_entry`.


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