> ## 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 OTP por teléfono: validar código SMS

> Didit valida el código OTP del teléfono con POST /v3/phone/check/ y detecta operador, números virtuales y desechables. Pago por uso, sin mínimos.

## Gestionar caídas del proveedor

Si el proveedor de telefonía no está disponible temporalmente, este endpoint devuelve `502` con un código estable y legible por máquinas:

```json theme={null}
{
  "detail": "The phone verification provider is temporarily unavailable.",
  "code": "phone_provider_unavailable"
}
```

Considera que se puede reintentar esta respuesta. Usa un backoff corto y muestra al usuario un mensaje de servicio temporalmente no disponible en lugar de pedirle que cambie un número de teléfono o un código válidos.

## Complemento de inteligencia

Establece `enable_enrichment` en `true` para ejecutar también la inteligencia telefónica del número: una puntuación de riesgo, el tipo de línea, si el número se portó recientemente y un índice de confianza.
El complemento se factura a \$0.05 por solicitud a precio de lista, además del precio de la verificación.
La solicitud devuelve `403` cuando tu saldo no alcanza para cubrirlo.

Cuatro campos determinan cómo se tratan 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 |
| - | - |
| `phone_intelligence_score_action` | La puntuación de riesgo supera el umbral. |
| `phone_type_risk_action` | El número es de un tipo de línea de alto riesgo. |
| `recent_port_action` | El número se portó a otro operador recientemente. |
| `low_phone_trust_action` | El índice de confianza es igual o inferior al umbral. |

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


## OpenAPI

````yaml es/openapi-25.json POST /v3/phone/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/phone/check/:
    post:
      tags:
        - Standalone APIs
      summary: Comprobar código de teléfono
      description: >-
        Verifica el OTP enviado por [`POST
        /v3/phone/send/`](/es/standalone-apis/phone-send) y obtén el resultado
        final de la verificación junto con inteligencia telefónica: nombre del
        operador y tipo de línea, indicadores de número virtual (VoIP) y
        desechable, y uso duplicado del número en tus sesiones.


        **Cómo localiza la comprobación la verificación.** La coincidencia se
        hace por tu aplicación más el `phone_number` en formato E.164.
        `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ó o tiene más de 5 minutos), el
        endpoint devuelve `200` con `status: "Expired or Not Found"`.


        **Límite de intentos.** Cada verificación permite **3 intentos de
        código**. Los dos primeros códigos incorrectos devuelven `status:
        "Failed"` con los intentos restantes y `phone: null`. El tercer código
        incorrecto finaliza la verificación como `Declined` con una advertencia
        `VERIFICATION_CODE_ATTEMPTS_EXCEEDED` y devuelve el informe completo del
        teléfono.


        **Resultados.** `Approved`: código correcto y ningún riesgo que provoque
        el rechazo. `Declined`: estado definitivo. El código era correcto pero
        coincidió un riesgo que provoca el rechazo (una acción `DECLINE` de las
        que se describen más abajo, o un número en la lista de bloqueo o de alto
        riesgo), o se agotaron los intentos. `Failed`: código incorrecto, con
        intentos restantes. `Expired or Not Found`: no hay nada que comprobar.
        Con `Approved`/`Declined`, el `request_id` es igual al `request_id` del
        envío (el ID de la sesión) y `phone` contiene el informe completo
        (`carrier`, `is_virtual`, `is_disposable`, `warnings`, `lifecycle`,
        `matches`). Con `Failed` y `Expired or Not Found`, el `request_id` es un
        UUID aleatorio de un solo uso.


        **Acciones de riesgo.** `duplicated_phone_number_action`,
        `disposable_number_action` y `voip_number_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 `phone.warnings` sin afectar al
        estado.


        **Facturación.** Las comprobaciones son gratuitas. La entrega se factura
        en el envío (consulta [Precios de Verificación de
        teléfono](/es/getting-started/phone-verification-pricing)).


        **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 (de 4 a 8 dígitos, `123456`
        incluido) devuelve un payload estático `Approved` con un objeto `phone`
        plano y simplificado (`status`, `phone_number`, `country_code`,
        `carrier_name`, `line_type`, `flags`). 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 faltan las credenciales o no son válidas, se
        devuelve `403` (`{"detail": "You do not have permission to perform this
        action."}`). Esta API nunca devuelve `401`.


        **Límites de solicitudes.** Límite de escritura compartido de 300
        solicitudes por minuto por clave de API, más el límite antiabuso del
        proveedor de 4 intentos por número y hora. Si se supera cualquiera de
        los dos, se devuelve `429`.


        **Huella social.** Establece `enable_social` en `true` para añadir un
        bloque `phone_social`: las plataformas en línea en las que está
        registrado este número, con recuentos por categoría y los datos de
        perfil disponibles. `profiles_registered: 0` significa que se
        comprobaron las plataformas y el número no se encontró en ninguna. 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 `phone_social` por
        solicitud, además del precio propio de este endpoint.
      operationId: post_v3phone_check
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phone_number:
                  type: string
                  maxLength: 20
                  description: >-
                    El mismo número de teléfono usado en la llamada
                    correspondiente a [`POST
                    /v3/phone/send/`](/es/standalone-apis/phone-send), en
                    formato E.164. Es lo que vincula la comprobación con el
                    envío.
                  example: '+14155552671'
                code:
                  type: string
                  minLength: 4
                  maxLength: 8
                  pattern: ^[0-9]{4,8}$
                  description: >-
                    El OTP que recibió el usuario final. Debe tener entre 4 y 8
                    dígitos numéricos; cualquier otro valor devuelve `400` sin
                    consumir un intento. Un código con formato correcto pero
                    erróneo devuelve `200` con `status: "Failed"` y consume uno
                    de los 3 intentos.
                  example: '123456'
                duplicated_phone_number_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ó el mismo número. `DECLINE`
                    cambia el `status` final a `Declined`; `NO_ACTION` registra
                    el riesgo en `phone.warnings` y rellena `phone.matches`.
                disposable_number_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Qué hacer cuando la consulta al operador marca el número
                    como línea temporal o desechable (`phone.is_disposable`).
                    `DECLINE` cambia el `status` final a `Declined`; `NO_ACTION`
                    registra el riesgo en `phone.warnings`.
                voip_number_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Qué hacer cuando la consulta al operador indica un tipo de
                    línea virtual: `voip`, `isp` o `vpn` (`phone.is_virtual`).
                    `DECLINE` cambia el `status` final a `Declined`; `NO_ACTION`
                    registra el riesgo en `phone.warnings`.
                enable_enrichment:
                  type: boolean
                  default: false
                  description: >-
                    Si es `true`, también ejecuta inteligencia de teléfono sobre
                    el número: una puntuación de riesgo, el tipo de línea, si se
                    portó recientemente y un índice de confianza. Se factura
                    como una unidad `phone_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
                phone_intelligence_score_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando la puntuación de riesgo de inteligencia del
                    teléfono 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`.
                phone_type_risk_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando el número es de un tipo de línea de alto
                    riesgo. `DECLINE` cambia el `status` final a `Declined`;
                    `NO_ACTION` registra la señal sin rechazar. Solo tiene
                    efecto cuando `enable_enrichment` es `true`.
                recent_port_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando el número se portó recientemente a otro
                    operador. `DECLINE` cambia el `status` final a `Declined`;
                    `NO_ACTION` registra la señal sin rechazar. Solo tiene
                    efecto cuando `enable_enrichment` es `true`.
                low_phone_trust_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    Acción cuando el índice de confianza de inteligencia del
                    teléfono es igual o inferior al umbral. `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 del número:
                    las plataformas de mensajería, redes sociales, comercio
                    electrónico y profesionales en las que está registrado. Se
                    factura como una unidad `phone_social` por solicitud, además
                    del precio propio de este endpoint.
                  example: true
                phone_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
                    el número registrado 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:
                - phone_number
                - code
            examples:
              Default:
                summary: Registrar los riesgos, pero nunca rechazar automáticamente
                value:
                  phone_number: '+14155552671'
                  code: '123456'
              Strict risk policy:
                summary: Rechazar automáticamente las líneas VoIP y desechables
                value:
                  phone_number: '+14155552671'
                  code: '123456'
                  voip_number_action: DECLINE
                  disposable_number_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. `phone` 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/PhoneVerificationCheckResponse'
              examples:
                Approved:
                  summary: >-
                    Código correcto: informe completo del teléfono con operador,
                    ciclo de vida y coincidencias
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Approved
                    message: The verification code is correct.
                    phone:
                      status: Approved
                      phone_number_prefix: '+1'
                      phone_number: '4155552671'
                      full_number: '+14155552671'
                      country_code: US
                      country_name: United States
                      carrier:
                        name: AT&T
                        type: mobile
                      is_disposable: false
                      is_virtual: false
                      verification_method: whatsapp
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      warnings: []
                      lifecycle:
                        - type: PHONE_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                            channel: whatsapp
                            actual_channel: whatsapp
                          fee: 0.0509
                        - type: PHONE_DELIVERY_DELIVERED
                          timestamp: '2026-06-12T01:23:43.118220+00:00'
                          details:
                            channel: whatsapp
                            status: delivered
                          fee: 0
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '123456'
                            status: Approved
                          fee: 0
                        - type: PHONE_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'
                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'
                    phone: null
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:21.512340+00:00'
                Declined (max attempts):
                  summary: >-
                    Tercer código incorrecto: verificación finalizada como
                    Declined
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Declined
                    message: >-
                      The verification code is incorrect. Maximum attempts
                      reached.
                    phone:
                      status: Declined
                      phone_number_prefix: '+1'
                      phone_number: '4155552671'
                      full_number: '+14155552671'
                      country_code: US
                      country_name: United States
                      carrier:
                        name: AT&T
                        type: mobile
                      is_disposable: false
                      is_virtual: false
                      verification_method: whatsapp
                      verification_attempts: 1
                      verified_at: null
                      warnings:
                        - feature: PHONE
                          risk: VERIFICATION_CODE_ATTEMPTS_EXCEEDED
                          additional_data: null
                          log_type: error
                          short_description: Verification code attempts exceeded
                          long_description: >-
                            The system detected that the phone number has
                            exceeded the maximum number of verification code
                            attempts.
                      lifecycle:
                        - type: PHONE_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                            channel: whatsapp
                            actual_channel: whatsapp
                          fee: 0.0509
                        - type: INVALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:01.118220+00:00'
                          details:
                            code_tried: '111111'
                            status: Failed
                          fee: 0
                        - type: INVALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:21.512340+00:00'
                          details:
                            code_tried: '222222'
                            status: Failed
                          fee: 0
                        - type: INVALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '333333'
                            status: Failed
                          fee: 0
                        - type: PHONE_VERIFICATION_DECLINED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details:
                            reason: VERIFICATION_CODE_ATTEMPTS_EXCEEDED
                          fee: 0
                      matches: []
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Declined (risk policy):
                  summary: >-
                    Código correcto, pero la línea es VoIP y
                    voip_number_action=DECLINE
                  value:
                    request_id: 7f1c9d2e-44a1-4b6e-9a3e-5b8e6f1c2d3a
                    status: Declined
                    message: The verification code is correct.
                    phone:
                      status: Declined
                      phone_number_prefix: '+1'
                      phone_number: '5005550006'
                      full_number: '+15005550006'
                      country_code: US
                      country_name: United States
                      carrier:
                        name: CLEC LLC
                        type: voip
                      is_disposable: false
                      is_virtual: true
                      verification_method: sms
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      warnings:
                        - feature: PHONE
                          risk: VOIP_NUMBER_DETECTED
                          additional_data: null
                          log_type: error
                          short_description: VoIP number detected
                          long_description: >-
                            The system detected that the phone number is a VoIP
                            number, which is not allowed.
                      lifecycle:
                        - type: PHONE_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                            channel: whatsapp
                            actual_channel: sms
                          fee: 0.0509
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '123456'
                            status: Approved
                          fee: 0
                        - type: PHONE_VERIFICATION_DECLINED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details:
                            reason: VOIP_NUMBER_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 este número en
                    los últimos 5 minutos
                  value:
                    request_id: 69cc35c6-280a-47a6-ab8c-4f32abc02ed0
                    status: Expired or Not Found
                    message: No pending phone verification found in the last 5 minutes.
                    vendor_data: null
                    metadata: null
                    created_at: '2026-06-12T01:24:47.311323+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 code format:
                  summary: '`code` no tiene entre 4 y 8 dígitos numéricos'
                  value:
                    code:
                      - Invalid code format. Enter 4 to 8 numeric digits.
                Invalid phone number:
                  summary: '`phone_number` no es un número E.164 válido'
                  value:
                    phone_number:
                      - Invalid phone number provided.
                Invalid action:
                  summary: Las acciones de riesgo solo aceptan NO_ACTION o DECLINE
                  value:
                    voip_number_action:
                      - '"REVIEW" is not a valid choice.'
        '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. Además, se aplica previamente
            un tope antiabuso de 4 intentos de verificación por número de
            teléfono por hora. La respuesta incluye los encabezados
            `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` y
            `Retry-After`. Nota: los encabezados `X-RateLimit-*`/`Retry-After`
            acompañan solo al 429 del límite de escritura de 300 por minuto; el
            429 del tope por número no incluye encabezados de límite de
            solicitudes.
          content:
            application/json:
              examples:
                Per-number cap:
                  summary: >-
                    Más de 4 intentos de verificación para el mismo número en la
                    última hora
                  value:
                    detail: >-
                      Maximum verification attempts reached for this phone
                      number. Only 4 authentication attempts are allowed per
                      hour. Try again later or use a different number.
                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
        '500':
          description: >-
            Error inesperado al verificar el código en el proveedor que no
            corresponde a una caída conocida del proveedor. Se puede reintentar
            sin riesgo; el cupo de intentos solo lo consumen las comprobaciones
            completadas.
          content:
            application/json:
              examples:
                Provider error:
                  summary: No se pudo completar la verificación del código
                  value:
                    detail: Error checking phone verification
              schema:
                type: object
                properties:
                  detail:
                    type: string
        '502':
          description: >-
            El proveedor de verificación de teléfono no está disponible
            temporalmente: una respuesta 5xx, un tiempo de espera agotado o un
            fallo de conexión que persistió tras los reintentos integrados.
            Puedes reintentar sin riesgo; no se consume el cupo de intentos.
          content:
            application/json:
              examples:
                Provider outage:
                  summary: El proveedor no respondió a la solicitud de comprobación
                  value:
                    detail: >-
                      Phone verification is temporarily unavailable. Please try
                      again shortly.
                    code: phone_provider_unavailable
              schema:
                type: object
                properties:
                  detail:
                    type: string
                  code:
                    type: string
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X POST https://verification.didit.me/v3/phone/check/ \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "phone_number": "+14155552671",
                "code": "123456",
                "voip_number_action": "DECLINE"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.phone.check_code(
                phone_number="+14155552671",
                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.phone.checkCode({
              phone_number: "+14155552671",
              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.Phone.CheckCode(ctx, didit.PhoneCheckCodeParams{\n\tPhoneNumber: \"+14155552671\",\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.PhoneCheckCodeParams;

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

            var result = client.phone().checkCode(PhoneCheckCodeParams.builder()
                    .phoneNumber("+14155552671")
                    .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->phone->checkCode([
                'phone_number' => '+14155552671',
                'code' => '123456',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

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

            result = didit.phone.check_code(
              phone_number: "+14155552671",
              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.Phone.CheckCodeAsync(new
            PhoneCheckCodeParams

            {
                PhoneNumber = "+14155552671",
                Code = "123456",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    PhoneVerificationCheckResponse:
      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/phone/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 este número 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.
        phone:
          type: object
          nullable: true
          description: >-
            Informe completo del teléfono. Presente (no nulo) solo en 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 teléfono. Coincide con el
                `status` de nivel superior en las comprobaciones finalizadas.
            phone_number_prefix:
              type: string
              description: Código telefónico del país con `+` inicial (por ejemplo, `+1`).
              example: '+1'
            phone_number:
              type: string
              description: Número nacional sin el prefijo telefónico del país.
              example: '4155552671'
            full_number:
              type: string
              description: Número completo en formato E.164.
              example: '+14155552671'
            country_code:
              type: string
              nullable: true
              description: País ISO 3166-1 alpha-2 del número.
              example: US
            country_name:
              type: string
              description: Nombre completo del país derivado de `country_code`.
              example: United States
            carrier:
              type: object
              description: >-
                Red actual que da servicio al número, según la consulta al
                operador realizada en la finalización.
              properties:
                name:
                  type: string
                  description: >-
                    Nombre del operador. Cadena vacía cuando la consulta no pudo
                    identificarlo.
                type:
                  type: string
                  description: >-
                    Tipo de línea que devuelve la consulta: `mobile`,
                    `fixed_line`, `voip`, `isp`, `vpn`, `toll_free`,
                    `premium_rate`, `pager`, `payphone`, `satellite`, `service`,
                    `shared_cost`, `short_codes_commercial`, `calling_cards`,
                    `local_rate`, `universal_access`, `voice_mail`, `other` o
                    `unknown`.
            is_disposable:
              type: boolean
              description: >-
                `true` cuando el número pertenece a un servicio de números
                temporales o desechables.
            is_virtual:
              type: boolean
              description: >-
                `true` cuando el tipo de línea es virtual (`voip`, `isp` o
                `vpn`).
            verification_method:
              type: string
              description: >-
                Canal que realmente entregó el OTP una vez confirmada la entrega
                (p. ej., `whatsapp`, `sms`); hasta entonces, el canal
                solicitado.
            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, desechable, VoIP, 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
                      `PHONE`.
                  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 `PHONE_VERIFICATION_MESSAGE_SENT`,
                `PHONE_VERIFICATION_RETRY_MESSAGE_SENT`,
                `PHONE_VERIFICATION_BLOCKED`, `PHONE_DELIVERY_DELIVERED`,
                `PHONE_DELIVERY_UNDELIVERABLE`, `VALID_CODE_ENTERED`,
                `INVALID_CODE_ENTERED`, `PHONE_VERIFICATION_APPROVED`,
                `PHONE_VERIFICATION_DECLINED`, `PHONE_VERIFICATION_IN_REVIEW`,
                `PHONE_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, channel, actual_channel}` (`actual_channel` se
                      completa cuando se confirma la entrega). Eventos de
                      entrega: `{channel, status}`. 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 los eventos de envío (el precio de la entrega); 0
                      en las introducciones de código, las confirmaciones de
                      entrega 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` diferente) usó el mismo
                número de teléfono. Hasta 5 entradas; si existe, primero aparece
                una coincidencia sintética con una entrada de la lista de
                bloqueo (las coincidencias derivadas de sesiones conservan el
                orden de la consulta). 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ó este número
                      de teléfono.
                  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`).
                  phone_number:
                    type: string
                    description: El número de teléfono que coincidió.
                  status:
                    type: string
                    description: >-
                      Estado de esa sesión (p. ej., `Approved`, `Declined`, `In
                      Progress`).
                  is_blocklisted:
                    type: boolean
                    description: >-
                      Si el número de teléfono 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.
            phone_social:
              $ref: '#/components/schemas/PhoneSocialFootprint'
            phone_intelligence:
              allOf:
                - $ref: '#/components/schemas/PhoneIntelligence'
              description: >-
                Señales de inteligencia telefónica. Solo aparecen 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.
    PhoneSocialFootprint:
      type: object
      nullable: true
      description: >-
        Huella social del número de teléfono: las plataformas en línea en las
        que está registrado. 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 el número de teléfono 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 el número de teléfono
            está registrado.
          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'
    PhoneIntelligence:
      type: object
      description: >-
        Bloque normalizado de inteligencia telefónica. Solo está presente cuando
        el complemento de inteligencia se ejecutó para esta consulta; 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.
        phone_type_risk:
          type: string
          nullable: true
          description: '`Low`, `Medium` o `High`, según la puntuación.'
        phone_trust_index:
          type: number
          nullable: true
          description: >-
            Inverso de la puntuación, para paneles en los que un valor más alto
            es mejor.
        network_stability_index:
          type: number
          nullable: true
          description: Estabilidad de la red de la línea.
        is_disposable:
          type: boolean
          nullable: true
          description: '`true` cuando el número parece desechable o virtual.'
        is_ported:
          type: boolean
          nullable: true
          description: '`true` cuando el número ha cambiado de operador.'
        is_recently_ported:
          type: boolean
          nullable: true
          description: '`true` cuando la portabilidad se produjo recientemente.'
        carrier_type:
          type: string
          nullable: true
          description: >-
            Clasificación de la línea que devuelve la consulta (p. ej.,
            `mobile`).
        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.