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

# Laporan Verifikasi Telepon: JSON OTP & Operator

> Respons Verifikasi Telepon Didit: data operator, jenis nomor, siklus OTP, & sinyal risiko. Bayar per OTP mulai $0.02 + biaya operator.

Laporan Verifikasi Telepon mencatat seluruh hasil dari tantangan OTP telepon: kepada siapa kami mengirimkan kode, operator dan saluran mana yang menanganinya, berapa kali percobaan yang dilakukan, apakah nomor tersebut sekali pakai atau VoIP, serta setiap kecocokan lintas sesi terhadap daftar blokir Anda atau sesi pengguna lain.

Halaman ini mendokumentasikan format JSON yang dikembalikan oleh endpoint keputusan sehingga Anda dapat mengurai hasil OTP, metadata operator, dan tanda risiko untuk setiap nomor yang diverifikasi.

![Laporan verifikasi telepon Didit yang menunjukkan hasil OTP, metadata operator, dan tanda risiko](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)

## Ringkasan

Laporan telepon dibuat setiap kali node alur kerja menjalankan fitur Verifikasi Telepon. Setiap laporan mewakili satu tantangan OTP terhadap satu nomor telepon dan berisi:

* Nomor telepon yang diuraikan menjadi awalan, nomor nasional, dan format E.164 lengkap, ditambah kode negara ISO dan nama negara.
* Metadata operator (`name`, `type`) yang diidentifikasi dari jaringan tujuan.
* Tanda risiko boolean (`is_disposable`, `is_virtual`) yang diperoleh dari analisis jenis saluran telepon.
* Saluran pengiriman sebenarnya yang digunakan (`verification_method`) dan jumlah percobaan pengiriman OTP.
* Log kronologis `lifecycle[]` dari setiap pengiriman, percobaan ulang, peristiwa pengiriman, dan percobaan pemeriksaan kode.
* Array `matches[]` yang memunculkan nomor yang sama pada sesi lain — status apa pun, di seluruh KYC, KYB, dan verifikasi API mandiri — atau daftar blokir Anda.
* Array `warnings[]` — event risiko yang dikeluarkan selama verifikasi (lihat [Peringatan Verifikasi Telepon](https://docs.didit.me/id/core-technology/phone-verification/warnings-phone-verification.md)).
* Sebuah `node_id` yang mengidentifikasi node graf alur kerja mana yang menghasilkan laporan tersebut (hanya sesi V3).

Dalam alur verifikasi yang di-hosting, Didit menjalankan pertukaran OTP untuk Anda. Untuk integrasi API langsung, alur yang sama terdiri dari dua panggilan — [`POST /v3/phone/send/`](https://docs.didit.me/id/standalone-apis/phone-send) untuk mengirimkan kode dan [`POST /v3/phone/check/`](https://docs.didit.me/id/standalone-apis/phone-check) untuk memvalidasi input pengguna. OTP yang masih tertunda tetap valid selama **5 menit dari pengiriman pertama** (coba lagi tidak memperpanjang jendela waktu). Dalam sesi alur kerja, pengguna mendapatkan 2 percobaan pengiriman OTP (`phone_max_retries`) dan 2 percobaan input kode (`phone_max_check_attempts`) secara default — keduanya dapat disesuaikan per node alur kerja; setelah salah satu batas tersebut tercapai, langkah akan ditetapkan sebagai `Declined` dengan `VERIFICATION_CODE_ATTEMPTS_EXCEEDED`. API telepon mandiri mengizinkan 3 percobaan input kode per verifikasi.

## Di mana laporan ini muncul dalam respons API

Endpoint keputusan (`GET /v3/session/{sessionId}/decision/`) mengembalikan laporan telepon dengan kunci array dalam bentuk jamak **`phone_verifications`**. Array ini berisi satu entri per node Verifikasi Telepon dalam graf alur kerja — biasanya satu, tetapi alur peningkatan verifikasi dapat menghasilkan beberapa entri.

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

Nilai `null` berarti belum ada langkah Verifikasi Telepon yang dijalankan. Lakukan iterasi pada array tersebut (alih-alih membaca `phone_verifications[0]`) ketika alur kerja Anda dapat mengumpulkan lebih dari satu nomor telepon.

## Skema

Skema kanonikal kolom demi kolom tersedia di halaman [Model data](https://docs.didit.me/id/reference/data-models.md#verifikasi-telepon).

```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
}
```

### Nilai status

| Status | Arti |
| - | - |
| `Not Finished` | Pengiriman OTP telah dimulai tetapi verifikasi belum diselesaikan. |
| `Approved` | Pengguna memasukkan OTP yang valid dan tidak ada risiko yang memicu penolakan. |
| `Declined` | Peringatan penolakan otomatis dipicu (daftar blokir, risiko tinggi, batas percobaan terlampaui) atau tindakan risiko yang dikonfigurasi ke `DECLINE` cocok. |
| `In Review` | Tindakan risiko yang dikonfigurasi ke `REVIEW` mengarahkan langkah ke peninjauan manual. |
| `Expired` | Jendela OTP 5 menit telah berlalu tanpa kode yang valid — berlaku untuk verifikasi yang dibuat melalui API telepon mandiri. |

### Jenis event siklus hidup

`lifecycle[]` diurutkan secara kronologis. Setiap event memiliki `type`, `timestamp`, `details`, dan `fee` yang dapat ditagih (jika berlaku):

| Jenis event | Dimunculkan saat |
| - | - |
| `PHONE_VERIFICATION_MESSAGE_SENT` | Percobaan pengiriman OTP pertama melalui saluran yang diminta. |
| `PHONE_VERIFICATION_RETRY_MESSAGE_SENT` | Pengiriman OTP berikutnya setelah pengguna meminta pengiriman ulang. |
| `PHONE_VERIFICATION_BLOCKED` | Pengiriman diblokir (spam, mencurigakan, percobaan berulang, nomor tidak valid). |
| `PHONE_DELIVERY_DELIVERED` | Operator mengonfirmasi pengiriman pada saluran aktual yang digunakan. |
| `PHONE_DELIVERY_UNDELIVERABLE` | Operator melaporkan bahwa pesan tidak dapat dikirimkan. |
| `VALID_CODE_ENTERED` | Pengguna mengirimkan kode OTP yang benar. |
| `INVALID_CODE_ENTERED` | Pengguna mengirimkan kode OTP yang salah (dihitung dalam batas percobaan memasukkan kode). |
| `PHONE_VERIFICATION_APPROVED` | Status tingkat fitur diatur ke `Approved`. |
| `PHONE_VERIFICATION_DECLINED` | Status tingkat fitur diatur ke `Declined`. |
| `PHONE_VERIFICATION_IN_REVIEW` | Status tingkat fitur diatur ke `In Review`. |
| `PHONE_VERIFICATION_EXPIRED` | Jendela OTP berlalu tanpa kode yang valid. |

Payload `details` bergantung pada kelompok event:

* **Event pengiriman** (`PHONE_VERIFICATION_MESSAGE_SENT`, `PHONE_VERIFICATION_RETRY_MESSAGE_SENT`, `PHONE_VERIFICATION_BLOCKED`) — `{ status, reason, channel, actual_channel }`. `status` bernilai `Success`, `Retry`, atau `Blocked`; `reason` bernilai `null` kecuali pengiriman diblokir (`invalid_phone_number`, `repeated_attempts`, `suspicious`, `spam`, `unknown`); `channel` adalah saluran yang diminta dan `actual_channel` adalah saluran yang benar-benar digunakan untuk mengantarkan pesan (misalnya pengiriman WhatsApp yang dialihkan ke SMS).
* **Event pengiriman (delivery)** (`PHONE_DELIVERY_DELIVERED`, `PHONE_DELIVERY_UNDELIVERABLE`) — `{ channel, status }` dengan `status` `delivered` atau `undeliverable`.
* **Event pemeriksaan** (`VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`) — `{ code_tried, status }` dengan `status` `Approved`, `Declined`, `Failed`, atau `Expired or Not Found`.
* **Event status akhir** — `null`, kecuali `PHONE_VERIFICATION_DECLINED` / `PHONE_VERIFICATION_IN_REVIEW`, yang memuat `{ "reason": "<risk code>" }` (misalnya `PHONE_NUMBER_IN_BLOCKLIST`).

`fee` pada event pengiriman adalah total harga pengiriman tersebut: harga operator atau WhatsApp ditambah biaya Didit $0.02, atau hanya biaya Didit $0.02 untuk kode WhatsApp yang dikirim dari [nomor WhatsApp Business Anda sendiri](https://docs.didit.me/id/core-technology/phone-verification/overview.md#kirim-kode-whatsapp-dari-nomor-anda-sendiri). Ini merupakan perkiraan harga sampai pengiriman dikonfirmasi, kemudian menjadi jumlah aktual yang ditagihkan. Hanya pengiriman `Blocked` yang dijamin gratis: pengiriman lainnya akan dikenakan biaya saat verifikasi selesai atau kedaluwarsa, bahkan jika pengiriman tidak pernah dikonfirmasi atau pesan tidak dapat dikirimkan. Event pengiriman (delivery), pemeriksaan, dan status selalu memuat `fee: 0`.

### Kecocokan lintas-sesi

`matches[]` mencatat sesi lain dalam aplikasi yang sama tempat nomor yang sama terlihat — di seluruh verifikasi KYC, KYB, dan API mandiri, apa pun statusnya — ditambah kecocokan dari daftar blokir yang dikonfigurasi dalam [daftar API Manajemen](https://docs.didit.me/id/management-api/lists/overview.md). Sesi yang memiliki `vendor_data` yang sama dengan sesi saat ini dikecualikan (pengguna akhir yang sama tidak cocok dengan dirinya sendiri), dan array dibatasi hingga **5** entri. Saat nomor tersebut ada di daftar blokir Anda tetapi tidak ada sesi yang cocok yang masuk daftar blokir, entri sintetis dengan `source: "list_entry"` (semua kolom sesi bernilai `null`) akan ditambahkan di awal 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
}
```

## Contoh

### Disetujui — WhatsApp OTP, operator seluler

```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"
}
```

### Ditolak — nomor VoIP yang masuk daftar blokir

Pengguna memasukkan OTP yang valid, tetapi finalisasi menemukan nomor tersebut di daftar blokir aplikasi (penolakan otomatis) dan menandai tipe saluran VoIP-nya (`voip_number_action` dibiarkan pada `NO_ACTION`, sehingga dicatat sebagai `information`). Karena tidak ada sesi yang cocok yang masuk daftar blokir, kecocokan daftar blokir muncul sebagai kecocokan sintetis `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"
}
```

## Terkait

* [Ringkasan Verifikasi Telepon](https://docs.didit.me/id/core-technology/phone-verification/overview.md) — perilaku fitur, harga, saluran yang didukung.
* [Peringatan Verifikasi Telepon](https://docs.didit.me/id/core-technology/phone-verification/warnings-phone-verification.md) — setiap kode risiko, pemicu penolakan, dan tindakan yang dapat dikonfigurasi.
* [Model data — verifikasi telepon](https://docs.didit.me/id/reference/data-models.md#verifikasi-telepon) — skema kanonikal kolom demi kolom.
* [API telepon mandiri](https://docs.didit.me/id/standalone-apis/phone-send.md) — endpoint `POST /v3/phone/send/` dan [`POST /v3/phone/check/`](https://docs.didit.me/id/standalone-apis/phone-check).
* [API Manajemen — Daftar](https://docs.didit.me/id/management-api/lists/overview.md) — mengelola daftar blokir telepon yang mengisi `matches[]` dengan `source: list_entry`.


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