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

# Verificação de Telefone: Relatório JSON, OTP e Operadora

> Analise respostas de Verificação de telefone na Didit: dados de operadora, tipo de linha, ciclo OTP e avisos de risco. Desde $0.02/OTP + taxas.

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

Esta página documenta a estrutura JSON devolvida pelo endpoint de decisão para que possa analisar os resultados do OTP, os metadados da operadora e os sinalizadores de risco para cada número verificado.

![Relatório de verificação de telefone da Didit a mostrar o resultado do OTP, metadados da operadora e sinalizadores 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

É gerado um relatório de telefone sempre que um nó do fluxo executa a funcionalidade Verificação de telefone. Cada relatório representa um desafio de 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.
* Sinalizadores de risco booleanos (`is_disposable`, `is_virtual`) derivados da análise do tipo de linha.
* O canal de entrega efetivamente utilizado (`verification_method`) e a contagem de tentativas de envio de OTP.
* Um registo cronológico em `lifecycle[]` de cada envio, nova tentativa, evento de entrega e tentativa de verificação de código.
* Um array `matches[]` que apresenta o mesmo número noutras sessões — qualquer estado, em verificações de KYC, KYB e de API autónoma — ou na sua lista de bloqueio.
* Um array `warnings[]` — eventos de risco emitidos durante a verificação (consulte [Avisos de Verificação de telefone](https://docs.didit.me/pt/core-technology/phone-verification/warnings-phone-verification.md)).
* Um `node_id` que identifica qual o nó do grafo de fluxo que gerou o relatório (apenas em sessões V3).

Nos fluxos de verificação alojados, a Didit executa a troca de OTP por si. Para integrações diretas de API, o mesmo fluxo requer duas chamadas — [`POST /v3/phone/send/`](https://docs.didit.me/pt/standalone-apis/phone-send) para entregar o código e [`POST /v3/phone/check/`](https://docs.didit.me/pt/standalone-apis/phone-check) para validar o código introduzido pelo utilizador. Um OTP pendente é válido durante **5 minutos a partir do primeiro envio** (novas tentativas não prolongam a janela). Nas sessões de fluxo, os utilizadores têm por predefinição 2 tentativas de envio de OTP (`phone_max_retries`) e 2 tentativas de introdução do código (`phone_max_check_attempts`) — ambas configuráveis por nó do fluxo; esgotar qualquer um dos limites finaliza o passo como `Declined` com `VERIFICATION_CODE_ATTEMPTS_EXCEEDED`. A API de telefone autónoma permite 3 tentativas de introdução do código por verificação.

## Onde surge nas respostas da API

O endpoint de decisão (`GET /v3/session/{sessionId}/decision/`) devolve relatórios de telefone sob a chave de array no plural **`phone_verifications`**. O array contém uma entrada por nó de Verificação de telefone no grafo do fluxo — normalmente uma, mas fluxos de step-up podem produzir 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 nenhum passo de Verificação de telefone foi ainda executado. Itere o array (em vez de ler `phone_verifications[0]`) quando o seu fluxo puder recolher mais do que um número de telefone.

## Schema

O esquema canónico campo a campo encontra-se na página [Modelos de dados](https://docs.didit.me/pt/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 estado

| Estado | Significado |
| - | - |
| `Not Finished` | O envio do OTP foi iniciado, mas a verificação ainda não foi finalizada. |
| `Approved` | O utilizador introduziu um OTP válido e nenhum risco de recusa foi detetado. |
| `Declined` | Foi acionado um aviso de recusa automática (lista de bloqueio, alto risco, tentativas excedidas) ou uma ação de risco configurada como `DECLINE` teve correspondência. |
| `In Review` | Uma ação de risco configurada como `REVIEW` encaminhou o passo para revisão manual. |
| `Expired` | A janela de 5 minutos do OTP expirou sem nenhum código válido — aplica-se a verificações criadas através da API de telefone autónoma. |

### Tipos de eventos do ciclo de vida

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

| Tipo de evento | Emitido quando |
| - | - |
| `PHONE_VERIFICATION_MESSAGE_SENT` | Primeira tentativa de envio de OTP pelo canal solicitado. |
| `PHONE_VERIFICATION_RETRY_MESSAGE_SENT` | Envio subsequente de OTP após o utilizador solicitar um novo envio. |
| `PHONE_VERIFICATION_BLOCKED` | O envio foi bloqueado (spam, tentativas repetidas, atividade suspeita, número inválido). |
| `PHONE_DELIVERY_DELIVERED` | A operadora confirmou a entrega no canal efetivamente utilizado. |
| `PHONE_DELIVERY_UNDELIVERABLE` | A operadora comunicou que a mensagem não pôde ser entregue. |
| `VALID_CODE_ENTERED` | O utilizador submeteu o código OTP correto. |
| `INVALID_CODE_ENTERED` | O utilizador submeteu um código OTP incorreto (conta para o limite de tentativas de introdução de código). |
| `PHONE_VERIFICATION_APPROVED` | O estado ao nível da funcionalidade foi definido como `Approved`. |
| `PHONE_VERIFICATION_DECLINED` | O estado ao nível da funcionalidade foi definido como `Declined`. |
| `PHONE_VERIFICATION_IN_REVIEW` | O estado ao nível da funcionalidade foi definido como `In Review`. |
| `PHONE_VERIFICATION_EXPIRED` | A janela do OTP expirou sem um código válido. |

O payload de `details` depende da família de eventos:

* **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 que efetivamente realizou a entrega (por exemplo, um envio por WhatsApp que recorreu a SMS como alternativa).
* **Eventos de entrega** (`PHONE_DELIVERY_DELIVERED`, `PHONE_DELIVERY_UNDELIVERABLE`) — `{ channel, status }` com `status` sendo `delivered` ou `undeliverable`.
* **Eventos de validação** (`VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`) — `{ code_tried, status }` com `status` sendo `Approved`, `Declined`, `Failed` ou `Expired or Not Found`.
* **Eventos de estado final** — `null`, exceto `PHONE_VERIFICATION_DECLINED` / `PHONE_VERIFICATION_IN_REVIEW`, que incluem `{ "reason": "<risk code>" }` (por exemplo, `PHONE_NUMBER_IN_BLOCKLIST`).

O campo `fee` num evento de envio corresponde ao preço total desse envio: o preço da operadora ou do WhatsApp mais a taxa Didit de $0.02, ou apenas a taxa Didit de $0.02 para um código WhatsApp enviado a partir do [seu próprio número WhatsApp Business](https://docs.didit.me/pt/core-technology/phone-verification/overview.md#enviar-códigos-de-whatsapp-a-partir-do-seu-próprio-número). É o preço estimado até que a entrega seja confirmada, passando depois a ser o montante faturado real. Apenas os envios com `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 a mensagem não tenha podido ser entregue. Os eventos de entrega, validação e estado incluem sempre `fee: 0`.

### Correspondências entre sessões

`matches[]` regista outras sessões na mesma aplicação onde o mesmo número foi observado — em verificações de KYC, KYB e na API autónoma, independentemente do respetivo estado — além de ocorrências em listas de bloqueio configuradas nas [listas da API de gestão](https://docs.didit.me/pt/management-api/lists/overview.md). As sessões que partilham o `vendor_data` da sessão atual são excluídas (o mesmo utilizador final não faz correspondência consigo próprio) e o array está limitado a **5** entradas. Quando o número está na sua lista de bloqueio mas nenhuma das sessões correspondentes se encontra na lista de bloqueio, uma entrada sintética com `source: "list_entry"` (com todos os campos de sessão a `null`) é colocada 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

### Aprovada — 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"
}
```

### Recusada — número VoIP na lista de bloqueio

O utilizador introduziu um OTP válido, mas a finalização detetou o número na lista de bloqueio da aplicação (recusa automática) e sinalizou o tipo de linha VoIP (`voip_number_action` mantido como `NO_ACTION`, pelo que é registado como `information`). Dado que nenhuma sessão correspondente se encontra na lista de bloqueio, a ocorrência na lista de bloqueio surge 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"
}
```

## Relacionado

* [Visão geral da Verificação de telefone](https://docs.didit.me/pt/core-technology/phone-verification/overview.md) — comportamento da funcionalidade, preços, canais suportados.
* [Avisos da Verificação de telefone](https://docs.didit.me/pt/core-technology/phone-verification/warnings-phone-verification.md) — todos os códigos de risco, acionadores de recusa e ações configuráveis.
* [Modelos de dados — verificação de telefone](https://docs.didit.me/pt/reference/data-models.md#verificação-de-telefone) — esquema canónico campo a campo.
* [API de telefone autónoma](https://docs.didit.me/pt/standalone-apis/phone-send.md) — endpoints `POST /v3/phone/send/` e [`POST /v3/phone/check/`](https://docs.didit.me/pt/standalone-apis/phone-check).
* [API de gestão — Listas](https://docs.didit.me/pt/management-api/lists/overview.md) — faça a gestão da 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.