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

# API para verificar código OTP de email: validar código

> Con POST /v3/email/check/, Didit valida códigos de email de un solo uso con señales de filtraciones, emails desechables y entregabilidad. Pago por uso.

## Complemento de inteligencia

Establece `enable_enrichment` en `true` para ejecutar también inteligencia de correo electrónico para la dirección: una puntuación de riesgo y su historial de filtraciones.
El complemento se factura a \$0.05 por solicitud según el precio de lista, además del precio de la comprobación.
La solicitud devuelve `403` cuando tu saldo no alcanza para cubrirlo.

Tres campos determinan qué ocurre con las señales.
Cada uno es `NO_ACTION` (el valor predeterminado) o `DECLINE`, y cada uno solo tiene efecto cuando `enable_enrichment` es `true`.

| Campo | Rechaza cuando |
| - | - |
| `email_intelligence_score_action` | La puntuación de riesgo supera el umbral. |
| `recent_email_breach_action` | La dirección aparece en una filtración de datos conocida y reciente. |
| `frequent_email_breach_action` | La dirección aparece en muchas filtraciones de datos conocidas. |

Con `NO_ACTION`, la señal se sigue devolviendo en `email.email_intelligence`, para que puedas aplicar tu propia regla.


## OpenAPI

````yaml es/openapi-25.json POST /v3/email/check/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API de verificación de identidad. Autentícate con el encabezado x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/email/check/:
    post:
      tags:
        - Standalone APIs
      summary: Comprobar código de correo electrónico
      description: >-
        Verifica el OTP enviado por [`POST
        /v3/email/send/`](/es/standalone-apis/email-send) y obtén el resultado
        final de la verificación junto con información sobre el correo
        electrónico: entregabilidad, exposición a filtraciones (`is_breached` y
        la lista `breaches` procedente de una base de datos de inteligencia
        sobre filtraciones), detección de proveedores desechables y uso
        duplicado de la dirección en tus sesiones.


        **Cómo localiza la comprobación la verificación.** La coincidencia se
        hace por tu aplicación más la dirección `email`; `request_id` no es un
        dato de entrada. Se comprueba la verificación pendiente más reciente
        creada en los últimos **5 minutos**. Si no hay ninguna (nunca se envió,
        ya se finalizó, no se pudo entregar en el momento del envío o tiene más
        de 5 minutos), el endpoint devuelve `200` con `status: "Expired or Not
        Found"`.


        **Límite de intentos.** Cada verificación admite **3 intentos de
        código**. Los dos primeros códigos incorrectos devuelven `status:
        "Failed"` con los intentos restantes y `email: null`; el tercer código
        incorrecto finaliza la verificación como `Declined` con una advertencia
        `EMAIL_CODE_ATTEMPTS_EXCEEDED` y devuelve el informe completo del correo
        electrónico. Los códigos se comparan sin distinguir mayúsculas de
        minúsculas (relevante para los envíos `alphanumeric_code`); solo es
        válido el código enviado más recientemente.


        **Resultados.** `Approved`: código correcto y ningún riesgo que provoque
        el rechazo. `Declined`: estado terminal; el código era correcto pero
        coincidió un riesgo que provoca el rechazo (una acción `DECLINE` de las
        indicadas más abajo, una dirección en la lista de bloqueo o una
        dirección que resultó no entregable al finalizar), o se agotó el límite
        de intentos. `Failed`: código incorrecto, quedan intentos. `Expired or
        Not Found`: no hay nada que comprobar. En `Approved`/`Declined`, el
        `request_id` es igual al `request_id` del envío (el ID de la sesión) y
        `email` contiene el informe completo (`is_breached`, `breaches`,
        `is_disposable`, `is_undeliverable`, `warnings`, `lifecycle`,
        `matches`); en `Failed` y `Expired or Not Found`, el `request_id` es un
        UUID aleatorio de un solo uso.


        **Acciones de riesgo.** `duplicated_email_action`,
        `breached_email_action` y `disposable_email_action` deciden qué ocurre
        cuando se detecta el riesgo correspondiente con un código correcto:
        `DECLINE` cambia el estado final a `Declined`; `NO_ACTION` (valor
        predeterminado) registra el riesgo en `email.warnings` sin afectar al
        estado.


        **Facturación.** Las comprobaciones son gratuitas: el crédito se consume
        con el envío correcto.


        **Persistencia de la sesión.** Una comprobación finalizada actualiza la
        sesión creada por el envío (visible en la Business Console y consultable
        mediante `GET /v3/session/{sessionId}/decision/`) y dispara un webhook
        `status.updated`.


        **Sandbox.** Las claves de API de sandbox omiten todo el procesamiento:
        cualquier código con formato válido (incluido `123456`) devuelve un
        payload estático `Approved` con un objeto `email` simplificado
        (`status`, `email`, `is_breached`, `is_disposable`, `is_undeliverable`);
        una entrada con formato incorrecto sigue devolviendo `400`. No se guarda
        nada.


        **Autenticación.** Envía la clave de API de tu aplicación en el
        encabezado `x-api-key`. Si las credenciales faltan o no son válidas, se
        devuelve `403` (`{"detail": "You do not have permission to perform this
        action."}`); esta API nunca devuelve `401`.


        **Límite de solicitudes.** Presupuesto de escritura compartido de 300
        solicitudes/min por clave de API entre todos los endpoints
        POST/PATCH/DELETE; si lo superas, se devuelve `429`.


        **Huella social.** Establece `enable_social` en `true` para añadir un
        bloque `email_social`: las plataformas en línea en las que está
        registrada esta dirección, con recuentos por categoría y los detalles de
        perfil disponibles. `profiles_registered: 0` significa que se
        comprobaron las plataformas y la dirección no se encontró en ninguna de
        ellas, lo que es una respuesta válida y facturable. El bloque no aparece
        cuando no se solicitó el complemento o no se pudo completar la
        comprobación, y en ese caso no se factura. La facturación añade una
        unidad `email_social` por solicitud, además del precio propio de este
        endpoint.
      operationId: post_v3email_check
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  description: >-
                    La misma dirección de correo electrónico usada en la llamada
                    correspondiente a [`POST
                    /v3/email/send/`](/es/standalone-apis/email-send). Es lo que
                    vincula la comprobación con el envío.
                  example: alice@example.com
                code:
                  type: string
                  maxLength: 10
                  description: >-
                    El OTP que recibió el usuario final: entre 4 y 8 dígitos, o
                    entre 4 y 8 letras o dígitos cuando se usó
                    `alphanumeric_code: true` en el envío. La comparación no
                    distingue entre mayúsculas y minúsculas.
                  example: '123456'
                duplicated_email_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Qué hacer cuando otro usuario de tu aplicación (con un
                    `vendor_data` distinto) ya usó y tiene aprobada la misma
                    dirección (solo cuentan las verificaciones aprobadas
                    previamente). `DECLINE` cambia el `status` final a
                    `Declined`; `NO_ACTION` registra el riesgo en
                    `email.warnings` y rellena `email.matches`.
                breached_email_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Qué hacer cuando la dirección aparece en filtraciones de
                    datos conocidas (`email.is_breached`). `DECLINE` cambia el
                    `status` final a `Declined`; `NO_ACTION` registra el riesgo
                    en `email.warnings`.
                disposable_email_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Qué hacer cuando el dominio pertenece a un proveedor de
                    correo desechable o temporal (`email.is_disposable`).
                    `DECLINE` cambia el `status` final a `Declined`; `NO_ACTION`
                    registra el riesgo en `email.warnings`.
                enable_enrichment:
                  type: boolean
                  default: false
                  description: >-
                    Si es `true`, también ejecuta inteligencia de correo
                    electrónico sobre la dirección: una puntuación de riesgo y
                    su historial de filtraciones. Se factura como una unidad
                    `email_intelligence_api` por solicitud ($0.05 a precio de
                    lista), además del precio propio de este endpoint. La
                    solicitud devuelve `403` cuando tu saldo no alcanza para
                    cubrirlo.
                  example: false
                email_intelligence_score_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando la puntuación de riesgo de inteligencia del
                    correo electrónico supera el umbral. `DECLINE` cambia el
                    `status` final a `Declined`; `NO_ACTION` registra la señal
                    sin rechazar. Solo tiene efecto cuando `enable_enrichment`
                    es `true`.
                recent_email_breach_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando la dirección aparece en una filtración de
                    datos conocida reciente. `DECLINE` cambia el `status` final
                    a `Declined`; `NO_ACTION` registra la señal sin rechazar.
                    Solo tiene efecto cuando `enable_enrichment` es `true`.
                frequent_email_breach_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando la dirección aparece en muchas filtraciones de
                    datos conocidas. `DECLINE` cambia el `status` final a
                    `Declined`; `NO_ACTION` registra la señal sin rechazar. Solo
                    tiene efecto cuando `enable_enrichment` es `true`.
                enable_social:
                  type: boolean
                  default: false
                  description: >-
                    Si es true, también se consulta la huella social de la
                    dirección: las plataformas de correo electrónico, redes
                    sociales, profesionales, comercio electrónico y
                    entretenimiento en las que está registrada. Se factura como
                    una unidad `email_social` por solicitud, además del precio
                    propio de este endpoint.
                  example: true
                email_no_social_presence_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando la comprobación de huella social no encuentra
                    la dirección registrada en ninguna de las plataformas que
                    cubre. En este endpoint solo se aceptan NO_ACTION y DECLINE;
                    REVIEW está disponible en la clave de configuración del
                    flujo con el mismo nombre.
              required:
                - email
                - code
            examples:
              Default:
                summary: Registrar los riesgos, pero nunca rechazar automáticamente
                value:
                  email: alice@example.com
                  code: '123456'
              Strict risk policy:
                summary: >-
                  Rechazar automáticamente los buzones desechables y los
                  expuestos en filtraciones de datos
                value:
                  email: alice@example.com
                  code: '123456'
                  disposable_email_action: DECLINE
                  breached_email_action: DECLINE
      responses:
        '200':
          description: >-
            Comprobación completada: los códigos incorrectos y las
            verificaciones inexistentes también devuelven `200`; revisa
            `status`, no el código HTTP. `email` solo se rellena en resultados
            finalizados (`Approved`/`Declined`), es `null` en `Failed` y no
            aparece en `Expired or Not Found`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailVerificationCheckResponse'
              examples:
                Approved:
                  summary: >-
                    Código correcto: dirección limpia, informe completo del
                    correo electrónico
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Approved
                    message: The verification code is correct.
                    email:
                      status: Approved
                      email: alice@example.com
                      is_breached: false
                      breaches: []
                      is_disposable: false
                      is_undeliverable: false
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      warnings: []
                      lifecycle:
                        - type: EMAIL_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                          fee: 0.02
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '123456'
                            status: Approved
                          fee: 0
                        - type: EMAIL_VERIFICATION_APPROVED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details: null
                          fee: 0
                      matches: []
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Approved with breach exposure:
                  summary: >-
                    Código correcto; la exposición en filtraciones se registra
                    como advertencia (breached_email_action=NO_ACTION)
                  value:
                    request_id: 3a1f2b6c-9d4e-4f7a-8b2c-1e5d6f7a8b9c
                    status: Approved
                    message: The verification code is correct.
                    email:
                      status: Approved
                      email: bob@example.com
                      is_breached: true
                      breaches:
                        - name: ExampleApp
                          domain: exampleapp.com
                          breach_date: '2019-03-21'
                          breach_emails_count: 763117
                          description: >-
                            In March 2019, the social platform ExampleApp
                            suffered a data breach that exposed email addresses
                            and passwords.
                          logo_path: https://<media-host>/logos/ExampleApp.png
                          data_classes:
                            - email_addresses
                            - passwords
                          is_verified: true
                      is_disposable: false
                      is_undeliverable: false
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      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.
                      lifecycle:
                        - type: EMAIL_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                          fee: 0.02
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '835126'
                            status: Approved
                          fee: 0
                        - type: EMAIL_VERIFICATION_APPROVED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details: null
                          fee: 0
                      matches: []
                    vendor_data: user-5678
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Failed (attempts remaining):
                  summary: >-
                    Código incorrecto: el usuario puede reintentar; aquí
                    request_id es un UUID de un solo uso
                  value:
                    request_id: 11111111-2222-3333-4444-555555555555
                    status: Failed
                    message: 'The verification code is incorrect. Attempts remaining: 2'
                    email: null
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:21.512340+00:00'
                Declined (risk policy):
                  summary: >-
                    Código correcto, pero la dirección es desechable y
                    disposable_email_action=DECLINE
                  value:
                    request_id: 8c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f
                    status: Declined
                    message: The verification code is correct.
                    email:
                      status: Declined
                      email: tempuser42@mailinator.com
                      is_breached: false
                      breaches: []
                      is_disposable: true
                      is_undeliverable: false
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      warnings:
                        - feature: EMAIL
                          risk: DISPOSABLE_EMAIL_DETECTED
                          additional_data: null
                          log_type: error
                          short_description: Disposable email detected
                          long_description: >-
                            The system detected that the email is disposable,
                            which is not allowed.
                      lifecycle:
                        - type: EMAIL_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                          fee: 0.02
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '123456'
                            status: Approved
                          fee: 0
                        - type: EMAIL_VERIFICATION_DECLINED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details:
                            reason: DISPOSABLE_EMAIL_DETECTED
                          fee: 0
                      matches: []
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Expired or Not Found:
                  summary: >-
                    No hay ninguna verificación pendiente para esta dirección en
                    los últimos 5 minutos
                  value:
                    request_id: 88808a77-06e9-4cb0-85f5-9c052ddfd987
                    status: Expired or Not Found
                    message: No pending email verification found in the last 5 minutes.
                    vendor_data: null
                    metadata: null
                    created_at: '2026-06-12T01:24:59.887904+00:00'
        '400':
          description: >-
            Error de validación: formato de errores de campo de DRF, con un
            array de mensajes por cada campo incorrecto.
          content:
            application/json:
              examples:
                Invalid email:
                  summary: Dirección de correo electrónico con formato incorrecto
                  value:
                    email:
                      - Enter a valid email address.
                Missing code:
                  summary: '`code` no se incluye en el cuerpo'
                  value:
                    code:
                      - This field is required.
        '403':
          description: >-
            Permiso denegado. Se devuelve cuando falta el encabezado
            `x-api-key`; una clave incorrecta, revocada o expirada devuelve
            `401`. Las comprobaciones son gratuitas, por lo que aquí no se
            verifica el crédito.
          content:
            application/json:
              examples:
                Missing or invalid API key:
                  summary: >-
                    Falta el encabezado `x-api-key`, o la clave no es válida o
                    está revocada
                  value:
                    detail: You do not have permission to perform this action.
        '429':
          description: >-
            Límite de solicitudes superado. Todos los endpoints
            POST/PATCH/DELETE comparten un presupuesto de 300 solicitudes de
            escritura por minuto por clave de API. La respuesta incluye los
            encabezados `X-RateLimit-Limit`, `X-RateLimit-Remaining`,
            `X-RateLimit-Reset` y `Retry-After`.
          content:
            application/json:
              examples:
                Write rate limit exceeded:
                  summary: Más de 300 solicitudes de escritura en el minuto actual
                  value:
                    detail: >-
                      Write request rate limit exceeded. You can make up to 300
                      requests per minute.
              schema:
                type: object
                properties:
                  detail:
                    type: string
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X POST https://verification.didit.me/v3/email/check/ \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "email": "alice@example.com",
                "code": "123456",
                "disposable_email_action": "DECLINE"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.email.check_code(
                email="alice@example.com",
                code="123456",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: |-
            import Didit from "@didit-protocol/sdk-node";

            // Reads DIDIT_API_KEY.
            const didit = new Didit();

            const result = await didit.email.checkCode({
              email: "alice@example.com",
              code: "123456",
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Email.CheckCode(ctx, didit.EmailCheckCodeParams{\n\tEmail: \"alice@example.com\",\n\tCode:  \"123456\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: |-
            import me.didit.Didit;
            import me.didit.types.EmailCheckCodeParams;

            // Reads DIDIT_API_KEY.
            Didit client = new Didit();

            var result = client.email().checkCode(EmailCheckCodeParams.builder()
                    .email("alice@example.com")
                    .code("123456")
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: |-
            <?php

            require 'vendor/autoload.php';

            use Didit\DiditClient;

            // Reads DIDIT_API_KEY.
            $didit = new DiditClient();

            $result = $didit->email->checkCode([
                'email' => 'alice@example.com',
                'code' => '123456',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Reads DIDIT_API_KEY.
            didit = Didit::Client.new

            result = didit.email.check_code(
              email: "alice@example.com",
              code: "123456"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Text.Json;

            using Didit;


            // Reads DIDIT_API_KEY.

            using var client = new DiditClient();


            var result = await client.Email.CheckCodeAsync(new
            EmailCheckCodeParams

            {
                Email = "alice@example.com",
                Code = "123456",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    EmailVerificationCheckResponse:
      type: object
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            Con `Approved`/`Declined`: el id de sesión de la verificación
            coincidente, idéntico al `request_id` que devuelve `POST
            /v3/email/send/`. Con `Failed` y `Expired or Not Found`: un UUID
            aleatorio de un solo uso que no se puede consultar después.
        status:
          type: string
          enum:
            - Approved
            - Declined
            - Failed
            - Expired or Not Found
          description: >-
            `Approved`: código correcto, sin ningún riesgo que provoque rechazo.
            `Declined`: estado final; coincidió un riesgo que provoca rechazo o
            se agotó el número de intentos (3). `Failed`: código incorrecto,
            quedan intentos. `Expired or Not Found`: no hay ninguna verificación
            pendiente para esta dirección en los últimos 5 minutos.
        message:
          type: string
          description: >-
            Explicación legible del resultado, incluido el número de intentos
            restantes tras un código incorrecto.
        email:
          type: object
          nullable: true
          description: >-
            Informe de correo electrónico completo. Presente (no null) solo en
            los resultados finalizados (`Approved`/`Declined`); `null` en
            `Failed` y ausente en `Expired or Not Found`.
          properties:
            status:
              type: string
              enum:
                - Approved
                - Declined
                - In Review
                - Not Finished
                - Expired
              description: >-
                Estado final de la verificación de correo electrónico. Coincide
                con el `status` de nivel superior en las comprobaciones
                finalizadas.
            email:
              type: string
              format: email
              description: La dirección de correo electrónico verificada.
              example: alice@example.com
            is_breached:
              type: boolean
              description: >-
                `true` cuando la dirección aparece en filtraciones de datos
                conocidas (consulta de inteligencia de filtraciones realizada al
                finalizar).
            breaches:
              type: array
              description: >-
                Hasta 5 de las filtraciones conocidas más recientes que
                contienen esta dirección. Array vacío (u omitido) cuando
                `is_breached` es `false`.
              items:
                type: object
                properties:
                  name:
                    type: string
                    description: Identificador de la filtración.
                  domain:
                    type: string
                    description: Dominio del servicio filtrado.
                  breach_date:
                    type: string
                    format: date
                    description: Fecha en que se produjo la filtración.
                  breach_emails_count:
                    type: integer
                    description: Número total de cuentas expuestas en la filtración.
                  description:
                    type: string
                    description: >-
                      Descripción legible de la brecha (puede contener marcado
                      HTML).
                  logo_path:
                    type: string
                    description: URL del logotipo del servicio afectado por la filtración.
                  data_classes:
                    type: array
                    items:
                      type: string
                    description: >-
                      Categorías de datos expuestos, en snake_case (p. ej.,
                      `email_addresses`, `passwords`).
                  is_verified:
                    type: boolean
                    description: Si la filtración se ha verificado como legítima.
            is_disposable:
              type: boolean
              description: >-
                `true` cuando el dominio pertenece a un proveedor conocido de
                correo desechable o temporal.
            is_undeliverable:
              type: boolean
              description: >-
                `true` cuando la dirección no puede recibir correo (falló la
                validación de sintaxis o de DNS/MX, o el mensaje rebotó).
            verification_attempts:
              type: integer
              description: >-
                Número de envíos de OTP para esta verificación (1, o 2 tras un
                reintento).
            verified_at:
              type: string
              format: date-time
              nullable: true
              description: >-
                Cuándo se introdujo el código correcto. `null` si la
                verificación nunca se aprobó.
            warnings:
              type: array
              description: >-
                Advertencias de riesgo registradas durante la verificación
                (duplicado, filtrado, desechable, no entregable, intentos
                superados, lista de bloqueo, etc.). Array vacío cuando no hay
                ninguna.
              items:
                type: object
                properties:
                  feature:
                    type: string
                    description: >-
                      Función que generó la advertencia. Aquí siempre es
                      `EMAIL`.
                  risk:
                    type: string
                    description: Código de riesgo legible por máquina.
                  additional_data:
                    type: object
                    nullable: true
                    description: >-
                      Contexto específico del riesgo (p. ej., el id de la sesión
                      duplicada en los riesgos de duplicado). `null` cuando el
                      riesgo no incluye datos adicionales.
                  log_type:
                    type: string
                    enum:
                      - error
                      - warning
                      - information
                    description: >-
                      Gravedad. Los riesgos `error` rechazan la verificación,
                      `warning` la marca para revisión e `information` se
                      registra sin afectar al estado.
                  short_description:
                    type: string
                    description: Resumen legible del riesgo en una línea.
                  long_description:
                    type: string
                    description: Explicación legible del riesgo.
            lifecycle:
              type: array
              description: >-
                Registro de auditoría cronológico de la verificación. El `type`
                del evento es uno de `EMAIL_VERIFICATION_MESSAGE_SENT`,
                `EMAIL_VERIFICATION_RETRY_MESSAGE_SENT`, `VALID_CODE_ENTERED`,
                `INVALID_CODE_ENTERED`, `EMAIL_VERIFICATION_APPROVED`,
                `EMAIL_VERIFICATION_DECLINED`, `EMAIL_VERIFICATION_IN_REVIEW`,
                `EMAIL_VERIFICATION_EXPIRED`.
              items:
                type: object
                properties:
                  type:
                    type: string
                    description: Tipo de evento.
                  timestamp:
                    type: string
                    format: date-time
                    description: Cuándo ocurrió el evento.
                  details:
                    type: object
                    nullable: true
                    description: >-
                      Payload específico del evento. Eventos de envío: `{status,
                      reason}`. Eventos de introducción del código:
                      `{code_tried, status}`. Eventos de estado final: `null`, o
                      `{reason}` cuando está rechazado o en revisión.
                  fee:
                    type: number
                    description: >-
                      Importe en USD facturado por este evento. Distinto de cero
                      solo en el primer envío correcto; 0 en los reintentos, las
                      introducciones de código y los eventos de estado.
            matches:
              type: array
              description: >-
                Otras sesiones de tu aplicación (KYC, KYB o API) en las que un
                usuario distinto (con un `vendor_data` distinto) usó la misma
                dirección de correo electrónico. Hasta 5 entradas; cuando
                existe, se antepone una coincidencia sintética de entrada de la
                lista de bloqueo (y solo si no existe ningún correo electrónico
                bloqueado derivado de una sesión); las coincidencias derivadas
                de sesiones mantienen el orden de created_at. Array vacío cuando
                no hay coincidencias.
              items:
                type: object
                properties:
                  session_id:
                    type: string
                    format: uuid
                    description: >-
                      ID de sesión de la otra verificación que usó esta
                      dirección de correo electrónico.
                  session_number:
                    type: integer
                    description: Número secuencial legible de esa sesión.
                  vendor_data:
                    type: string
                    nullable: true
                    description: '`vendor_data` de esa sesión.'
                  verification_date:
                    type: string
                    description: Cuándo se creó esa sesión (`YYYY-MM-DDTHH:MM:SSZ`).
                  email:
                    type: string
                    description: La dirección de correo electrónico que coincidió.
                  status:
                    type: string
                    description: >-
                      Estado de esa sesión (p. ej., `Approved`, `Declined`, `In
                      Progress`).
                  is_blocklisted:
                    type: boolean
                    description: >-
                      Si la dirección de correo electrónico está en la lista de
                      bloqueo de tu aplicación.
                  api_service:
                    type: string
                    nullable: true
                    description: >-
                      En las sesiones de tipo API, la API independiente que la
                      creó (p. ej., `PHONE_VERIFICATION`); `null` en las
                      sesiones de verificación normales.
                  source:
                    type: string
                    description: >-
                      Dónde se encontró la coincidencia. Normalmente `session`;
                      una coincidencia en la lista de bloqueo a través de una
                      entrada de lista de la organización antepone una
                      coincidencia sintética con `source: "list_entry"` y
                      `session_id`/`session_number` nulos.
            email_social:
              $ref: '#/components/schemas/EmailSocialFootprint'
            email_intelligence:
              allOf:
                - $ref: '#/components/schemas/EmailIntelligence'
              description: >-
                Señales de inteligencia de correo electrónico. Solo están
                presentes cuando `enable_enrichment` era `true` en la
                comprobación.
        vendor_data:
          type: string
          nullable: true
          description: >-
            `vendor_data` de la sesión de la verificación coincidente. `null` en
            `Expired or Not Found`.
        metadata:
          type: object
          nullable: true
          description: >-
            `metadata` de la sesión de la verificación coincidente. `null` en
            `Expired or Not Found`.
        created_at:
          type: string
          format: date-time
          description: Marca de tiempo de esta respuesta de comprobación.
    EmailSocialFootprint:
      type: object
      nullable: true
      description: >-
        Huella social de la dirección de correo electrónico: las plataformas en
        línea en las que está registrada. Solo está presente cuando se activó
        `enable_social` y la comprobación finalizó. Cualquier recuento puede ser
        null cuando no se obtuvieron datos para él. `profiles_registered: 0`
        significa que se comprobaron las plataformas y que la dirección de
        correo electrónico no se encontró en ninguna de ellas: es una respuesta
        válida y facturable, y una señal habitual de identidad sintética.
      properties:
        profiles_registered:
          type: integer
          nullable: true
          description: >-
            Plataformas en las que se ha confirmado que la dirección de correo
            electrónico está registrada.
          example: 5
        profiles_checked:
          type: integer
          nullable: true
          description: Plataformas evaluadas para el registro.
          example: 14
        names_found:
          type: integer
          nullable: true
          description: Plataformas que devolvieron un nombre asociado.
          example: 0
        photos_found:
          type: integer
          nullable: true
          description: Plataformas que devolvieron una foto de perfil.
          example: 0
        communication_breadth:
          type: integer
          nullable: true
          description: Plataformas de comunicación en las que se detectó presencia.
          example: 2
        digital_footprint_diversity:
          type: integer
          nullable: true
          description: Categorías de plataforma distintas en las que se detectó presencia.
          example: 5
        digital_sophistication_index:
          type: integer
          nullable: true
          description: Indicador compuesto de madurez digital, de 0 a 10.
          example: 5
        engagement_depth_index:
          type: integer
          nullable: true
          description: Indicador de riqueza del perfil, de 0 a 10.
          example: 3
        subscription_affordability_index:
          type: integer
          nullable: true
          description: Proporción entre plataformas gratuitas y de pago, de 0 a 10.
          example: 2
        free_platforms:
          type: integer
          nullable: true
          description: Registros en plataformas gratuitas.
          example: 4
        full_paid_platforms:
          type: integer
          nullable: true
          description: Registros en plataformas totalmente de pago.
          example: 0
        partial_paid_platforms:
          type: integer
          nullable: true
          description: Registros en plataformas freemium.
          example: 1
        whatsapp_profile_completeness:
          type: string
          nullable: true
          enum:
            - Basic
            - Partial
            - Complete
            - Not Present
            - null
          description: >-
            Grado de completitud del perfil de WhatsApp. Solo para teléfono;
            null para correo electrónico.
          example: Partial
        registered_platforms:
          type: array
          description: Plataformas en las que se ha confirmado el registro.
          items:
            $ref: '#/components/schemas/SocialFootprintPlatform'
        not_registered_platforms:
          type: array
          description: Plataformas comprobadas con resultado negativo.
          items:
            $ref: '#/components/schemas/SocialFootprintPlatform'
        categories:
          type: object
          description: Número de registros y proporción por categoría de plataforma.
          additionalProperties:
            $ref: '#/components/schemas/SocialFootprintCategorySummary'
        profiles:
          type: object
          description: >-
            Detalles del perfil por plataforma, indexados por plataforma, cuando
            la plataforma los expone.
          additionalProperties:
            $ref: '#/components/schemas/SocialFootprintProfile'
    EmailIntelligence:
      type: object
      description: >-
        Bloque normalizado de inteligencia de correo electrónico. Solo está
        presente cuando el complemento de inteligencia se ejecutó para este
        correo; cuando está presente, también se expone con el alias
        `enrichment` y valores idénticos.
      properties:
        score:
          type: number
          nullable: true
          description: >-
            Puntuación de riesgo normalizada de 0 a 100. Cuanto más alta, mayor
            es el riesgo.
        deliverable:
          type: string
          nullable: true
          description: Rango de entregabilidad (p. ej., `high`).
        breach_risk_level:
          type: string
          nullable: true
          description: '`Low`, `Medium` o `High`.'
        breach_risk_index:
          type: number
          nullable: true
          description: Índice numérico de riesgo de filtración.
        is_recent_breach:
          type: boolean
          nullable: true
          description: '`true` cuando la dirección aparece en una filtración reciente.'
        is_frequent_breached:
          type: boolean
          nullable: true
          description: '`true` cuando la dirección aparece en muchas filtraciones.'
        is_disposable:
          type: boolean
          nullable: true
          description: '`true` cuando el dominio es un proveedor de correo desechable.'
        is_free_domain:
          type: boolean
          nullable: true
          description: '`true` cuando el dominio es un proveedor de correo gratuito.'
        is_breached:
          type: boolean
          nullable: true
          description: '`true` cuando la dirección aparece en filtraciones conocidas.'
        no_of_breaches:
          type: number
          nullable: true
          description: Número de filtraciones conocidas que contienen la dirección.
        reason_codes:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
                description: >-
                  Identificador estable de Didit para la señal, por ejemplo
                  `IR-5AC67A32`. Es opaco: agrupa y filtra por él, pero no lo
                  analices.
              value:
                nullable: true
                description: >-
                  En un indicador de riesgo (por ejemplo, `voip`, `leaked`,
                  `disposable`, `spam_trap`), su valor: un booleano, un nivel o
                  una fecha. Null en un código de motivo con puntuación.
              direction:
                type: string
                enum:
                  - risk
                  - trust
                description: Si la señal aumentó el riesgo o aportó confianza.
              message:
                type: string
                description: Explicación legible de la señal, en inglés.
              impact_level:
                type: string
                nullable: true
                description: >-
                  Cuánto movió la señal la puntuación, por ejemplo `low`,
                  `medium` o `high`.
          description: >-
            Señales que explican la puntuación, cada una con un código estable
            de Didit, una dirección, un mensaje y un nivel de impacto. Pueden
            aparecer códigos nuevos con el tiempo, así que no rechaces los
            códigos desconocidos.
    SocialFootprintPlatform:
      type: object
      properties:
        platform:
          type: string
          description: Identificador de la plataforma.
          example: whatsapp
        category:
          type: string
          description: >-
            Categoría de la plataforma, por ejemplo MESSAGING, SOCIAL_MEDIA,
            ECOMMERCE, PROFESSIONAL, EMAIL_PROVIDER.
          example: MESSAGING
        scope:
          type: string
          enum:
            - global
            - local
          description: >-
            `global` para plataformas de alcance mundial, `local` para las
            específicas de una región.
          example: global
    SocialFootprintCategorySummary:
      type: object
      properties:
        registered:
          type: integer
          nullable: true
          description: >-
            Plataformas de esta categoría en las que se ha confirmado el
            registro.
          example: 2
        ratio:
          type: number
          format: float
          nullable: true
          description: >-
            Proporción de las plataformas comprobadas de la categoría en las que
            existe un registro, de 0.0 a 1.0.
          example: 0.6667
    SocialFootprintProfile:
      type: object
      properties:
        name:
          type: string
          nullable: true
          description: Nombre del perfil, cuando la plataforma lo expone.
        photo:
          type: string
          nullable: true
          description: URL de la foto del perfil, cuando la plataforma la expone.
        about:
          type: string
          nullable: true
          description: >-
            Texto de presentación o biografía del perfil, cuando la plataforma
            lo expone.
        privacy_status:
          type: string
          nullable: true
          enum:
            - PUBLIC
            - PRIVATE
            - null
          description: Visibilidad del perfil, cuando la plataforma la expone.
        business_account:
          type: boolean
          nullable: true
          description: >-
            Si el perfil es una cuenta de empresa, cuando la plataforma lo
            expone.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        La clave de API de tu aplicación, que encontrarás en Developers -> API
        keys en la Business Console. La clave principal tiene acceso completo.
        Una clave con nombre puede tener un alcance limitado: ninguno, lectura o
        escritura por recurso, limitada a algunos flujos o a sesiones aprobadas,
        a una lista de direcciones IP y a una fecha de caducidad. 401 significa
        que la clave es incorrecta, se revocó o expiró; 403 significa que no se
        envió ninguna clave, que la clave no tiene acceso a este recurso o
        acción, o que la solicitud provino de una dirección fuera de su lista de
        IP; 404 en una ruta de sesión significa que la sesión está fuera de los
        flujos o estados de la clave. Una clave sin acceso a contenido
        multimedia recibe las URL de imágenes, videos y PDF como null, y una
        clave sin permiso de escritura en sesiones recibe los enlaces y tokens
        de sesión como null. Consulta https://docs.didit.me/console/api-keys.

````

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