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

# Relatório de verificação de telefone: OTP e operadora

> A Didit retorna operadora, tipo de linha, ciclo do OTP, correspondências entre sessões e avisos de risco. OTP a partir de $0.02 + taxas da operadora.

O relatório de Verificação de telefone registra o resultado completo de um desafio de OTP por telefone: para quem enviamos o código, qual operadora e qual canal o processaram, quantas tentativas foram necessárias, se o número é descartável ou VoIP e quaisquer correspondências entre sessões com a sua lista de bloqueio ou com sessões de outros usuários.

Esta página documenta a estrutura JSON retornada pelo endpoint de decisão, para que você possa interpretar os resultados de OTP, os metadados da operadora e os indicadores de risco de cada número verificado.

![Relatório de verificação de telefone da Didit mostrando o resultado do OTP, os metadados da operadora e os indicadores de risco](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/phone-verification-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=9b5c6c6112303ebc60c0f287aafdb996)

## Visão geral

Um relatório de telefone é gerado sempre que um nó do fluxo executa o recurso Verificação de telefone. Cada relatório representa um desafio OTP para um número de telefone e contém:

* O número de telefone dividido em prefixo, número nacional e formato E.164 completo, além do código de país ISO e do nome do país.
* Metadados da operadora (`name`, `type`) obtidos a partir da rede de destino.
* Indicadores de risco booleanos (`is_disposable`, `is_virtual`) derivados da análise do tipo de linha.
* O canal de entrega efetivamente usado (`verification_method`) e a quantidade de tentativas de envio do OTP.
* Um registro cronológico `lifecycle[]` de cada envio, nova tentativa, evento de entrega e tentativa de verificação do código.
* Um array `matches[]` que mostra o mesmo número em outras sessões (qualquer status, em verificações KYC, KYB e verificações avulsas via API) ou na sua lista de bloqueio.
* Um array `warnings[]` com os eventos de risco emitidos durante a verificação (consulte [Avisos da Verificação de telefone](https://docs.didit.me/pt-br/core-technology/phone-verification/warnings-phone-verification.md)).
* Um `node_id` que identifica qual nó do grafo do fluxo gerou o relatório (somente sessões V3).

Nos fluxos de verificação hospedados, a Didit executa a troca do OTP para você. Em integrações diretas via API, o mesmo fluxo é feito com duas chamadas: [`POST /v3/phone/send/`](https://docs.didit.me/pt-br/standalone-apis/phone-send) para enviar o código e [`POST /v3/phone/check/`](https://docs.didit.me/pt-br/standalone-apis/phone-check) para validar o que o usuário digitou. Um OTP pendente é válido por **5 minutos a partir do primeiro envio** (novas tentativas não estendem esse prazo). Em sessões de fluxo, por padrão, os usuários têm 2 tentativas de envio do OTP (`phone_max_retries`) e 2 tentativas de digitação do código (`phone_max_check_attempts`), ambas ajustáveis por nó do fluxo; esgotar qualquer um desses limites finaliza a etapa como `Declined` com `VERIFICATION_CODE_ATTEMPTS_EXCEEDED`. A API avulsa de telefone permite 3 tentativas de digitação do código por verificação.

## Onde aparece nas respostas da API

O endpoint de decisão (`GET /v3/session/{sessionId}/decision/`) retorna os relatórios de verificação de telefone na chave de array no plural **`phone_verifications`**. O array contém uma entrada para cada nó de Verificação de telefone no grafo do fluxo. Normalmente há apenas uma, mas fluxos com verificação adicional (step-up) podem gerar várias.

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

Um valor `null` significa que nenhuma etapa de Verificação de telefone foi executada ainda. Percorra o array (em vez de ler `phone_verifications[0]`) quando o seu fluxo puder coletar mais de um número de telefone.

## Schema

O schema canônico, campo a campo, está na página [Modelos de dados](https://docs.didit.me/pt-br/reference/data-models.md#verificação-de-telefone).

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

### Valores de status

| Status | Significado |
| - | - |
| `Not Finished` | O envio do OTP foi iniciado, mas a verificação ainda não foi finalizada. |
| `Approved` | O usuário inseriu um OTP válido e nenhum risco que leve à recusa foi identificado. |
| `Declined` | Um aviso de recusa automática foi disparado (lista de bloqueio, alto risco, tentativas excedidas) ou uma ação de risco configurada como `DECLINE` foi acionada. |
| `In Review` | Uma ação de risco configurada como `REVIEW` encaminhou a etapa para revisão manual. |
| `Expired` | A janela de 5 minutos do OTP terminou sem um código válido. Aplica-se a verificações criadas pela API de telefone independente. |

### Tipos de evento do ciclo de vida

`lifecycle[]` é ordenado cronologicamente. Cada evento tem `type`, `timestamp`, `details` e uma `fee` faturável (quando aplicável):

| Tipo de evento | Emitido quando |
| - | - |
| `PHONE_VERIFICATION_MESSAGE_SENT` | Primeira tentativa de envio do OTP pelo canal solicitado. |
| `PHONE_VERIFICATION_RETRY_MESSAGE_SENT` | Envio posterior do OTP depois que o usuário solicitou o reenvio. |
| `PHONE_VERIFICATION_BLOCKED` | O envio foi bloqueado (spam, suspeito, repetido, número inválido). |
| `PHONE_DELIVERY_DELIVERED` | A operadora confirmou a entrega pelo canal efetivamente usado. |
| `PHONE_DELIVERY_UNDELIVERABLE` | A operadora informou que a mensagem não pôde ser entregue. |
| `VALID_CODE_ENTERED` | O usuário inseriu o código OTP correto. |
| `INVALID_CODE_ENTERED` | O usuário inseriu um código OTP incorreto (conta para o limite de inserções de código). |
| `PHONE_VERIFICATION_APPROVED` | O status do recurso foi definido como `Approved`. |
| `PHONE_VERIFICATION_DECLINED` | O status do recurso foi definido como `Declined`. |
| `PHONE_VERIFICATION_IN_REVIEW` | O status do recurso foi definido como `In Review`. |
| `PHONE_VERIFICATION_EXPIRED` | A janela do OTP terminou sem um código válido. |

O payload de `details` depende da família do evento:

* **Eventos de envio** (`PHONE_VERIFICATION_MESSAGE_SENT`, `PHONE_VERIFICATION_RETRY_MESSAGE_SENT`, `PHONE_VERIFICATION_BLOCKED`): `{ status, reason, channel, actual_channel }`. `status` é `Success`, `Retry` ou `Blocked`; `reason` é `null`, a menos que o envio tenha sido bloqueado (`invalid_phone_number`, `repeated_attempts`, `suspicious`, `spam`, `unknown`); `channel` é o canal solicitado e `actual_channel` é o canal pelo qual a mensagem foi efetivamente entregue (por exemplo, um envio por WhatsApp que recorreu ao SMS).
* **Eventos de entrega** (`PHONE_DELIVERY_DELIVERED`, `PHONE_DELIVERY_UNDELIVERABLE`): `{ channel, status }` com `status` `delivered` ou `undeliverable`.
* **Eventos de checagem** (`VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`): `{ code_tried, status }` com `status` `Approved`, `Declined`, `Failed` ou `Expired or Not Found`.
* **Eventos de status final**: `null`, exceto `PHONE_VERIFICATION_DECLINED` / `PHONE_VERIFICATION_IN_REVIEW`, que trazem `{ "reason": "<risk code>" }` (por exemplo, `PHONE_NUMBER_IN_BLOCKLIST`).

A `fee` em um evento de envio é o preço total desse envio: o preço da operadora ou do WhatsApp mais a taxa de $0.02 da Didit, ou apenas a taxa de $0.02 da Didit no caso de um código por WhatsApp enviado a partir do [seu próprio número do WhatsApp Business](https://docs.didit.me/pt-br/core-technology/phone-verification/overview.md#envie-códigos-por-whatsapp-do-seu-próprio-número). Ela é o preço estimado até que a entrega seja confirmada e, depois disso, o valor efetivamente cobrado. Somente os envios `Blocked` são garantidamente gratuitos: qualquer outro envio é cobrado quando a verificação é finalizada ou expira, mesmo que a entrega nunca tenha sido confirmada ou que a mensagem não tenha podido ser entregue. Eventos de entrega, de checagem e de status sempre trazem `fee: 0`.

### Correspondências entre sessões

`matches[]` registra outras sessões na mesma aplicação em que o mesmo número foi visto, em verificações de KYC, KYB e da API independente, independentemente do status delas, além de ocorrências em listas de bloqueio configuradas nas [listas da management API](https://docs.didit.me/pt-br/management-api/lists/overview.md). Sessões que compartilham o `vendor_data` da sessão atual são excluídas (um mesmo usuário final não gera uma correspondência consigo mesmo), e o array é limitado a **5** entradas. Quando o número está na sua lista de bloqueio, mas nenhuma das sessões correspondentes está na lista de bloqueio, uma entrada sintética com `source: "list_entry"` (com todos os campos de sessão `null`) é inserida no início do array.

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

## Exemplos

### Aprovado: OTP por WhatsApp, operadora móvel

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

### Recusado: número VoIP na lista de bloqueio

O usuário inseriu um OTP válido, mas a finalização encontrou o número na lista de bloqueio da aplicação (recusa automática) e sinalizou o tipo de linha VoIP (`voip_number_action` mantido em `NO_ACTION`, por isso é registrado como `information`). Como nenhuma sessão correspondente está na lista de bloqueio, a ocorrência na lista de bloqueio aparece como uma correspondência sintética `list_entry`.

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

## Relacionados

* [Visão geral da Verificação de telefone](https://docs.didit.me/pt-br/core-technology/phone-verification/overview.md): comportamento do recurso, preços e canais compatíveis.
* [Avisos da Verificação de telefone](https://docs.didit.me/pt-br/core-technology/phone-verification/warnings-phone-verification.md): todos os códigos de risco, gatilhos de recusa e ações configuráveis.
* [Modelos de dados: verificação de telefone](https://docs.didit.me/pt-br/reference/data-models.md#verificação-de-telefone): schema canônico, campo a campo.
* [API de telefone independente](https://docs.didit.me/pt-br/standalone-apis/phone-send.md): endpoints `POST /v3/phone/send/` e [`POST /v3/phone/check/`](https://docs.didit.me/pt-br/standalone-apis/phone-check).
* [Management API: listas](https://docs.didit.me/pt-br/management-api/lists/overview.md): gerencie a lista de bloqueio de números de telefone que alimenta `matches[]` com `source: list_entry`.


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