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

# Referensi API Konfigurasi Fitur Alur Kerja

> Referensi semua kolom konfigurasi di POST dan PATCH /v3/workflows/ untuk membangun alur kerja linear sederhana dengan array features di Didit.

Gunakan kolom `config` berikut di dalam setiap item array `features` untuk [`POST /v3/workflows/`](https://docs.didit.me/id/management-api/workflows/create) dan [`PATCH /v3/workflows/{settings_uuid}/`](https://docs.didit.me/id/management-api/workflows/update).

```json theme={null}
{
  "workflow_label": "Standard KYC",
  "features": [
    {
      "feature": "OCR",
      "config": {
        "documents_allowed": {
          "USA": {
            "DL": {
              "enabled": 1,
              "sides": 2
            }
          }
        }
      }
    }
  ]
}
```

API alur kerja v3 membangun alur kerja linear berbasis node dari array `features` yang berurutan. Kirim fitur dalam urutan eksekusi yang tepat.

> [!NOTE]
>
> Mesin yang menjalankan suatu fitur, yaitu milik Didit atau penyedia pihak ketiga, bukan salah satu kolom config di bawah. Mesin ini dikelola melalui [Marketplace](https://docs.didit.me/id/console/marketplace.md) di konsol, yang akan mengatur `provider_key` dan `fallback_to_native` pada objek `config` fitur tersebut untuk Anda.

## Aturan validasi

* `OCR` secara default mencakup semua negara dan jenis dokumen yang didukung ketika `config.documents_allowed` dihilangkan, bernilai `null`, atau `{}`. Jika Anda mengirim objek `documents_allowed` kustom, objek tersebut harus berisi minimal satu negara yang valid dan satu jenis dokumen yang diaktifkan. Setiap konfigurasi dokumen dapat mengatur `sides` ke `1` untuk pengambilan hanya sisi depan, atau `2` untuk pengambilan sisi depan dan belakang.
* `QUESTIONNAIRE` memerlukan `config.questionnaire_uuid`.
* `KYB_DOCUMENTS` memerlukan `config.kyb_required_document_groups`.
* `SIGNATURE` menolak `signature_level: "qes"` dengan `qes_not_available` sampai tanda tangan terkualifikasi tersedia, dan menolak langkah baru dengan `signature_level: "aes"` dengan `aes_not_available` selama `signature_availability.aes` bernilai `false` pada alur kerja. Dokumennya harus sudah ada saat sesi dibuat. Jika `signature_documents_source` diatur ke `workflow`, langkah tersebut memerlukan dokumen yang diunggah di konsol, dan langkah tanpa dokumen dapat tetap berstatus draf tetapi tidak dapat diaktifkan. Jika diatur ke `session`, setiap panggilan pembuatan harus mengirim `sign.documents`.
* `FACE_MATCH` harus berada setelah `OCR` dalam permintaan alur kerja sederhana.
* `NFC` dan `DATABASE_VALIDATION` memerlukan `OCR` jika muncul dalam alur kerja yang sama. `AML` memerlukan salah satu dari `OCR`, `KYB_REGISTRY`, atau `DOCUMENT_AI` sebelumnya. Jika hanya `DOCUMENT_AI` yang berada sebelumnya, `full_name` yang akan diskrining harus dapat diisi, yaitu dari kolom Document AI di langkah sebelumnya yang sudah diberi kunci `full_name` (akan dipetakan untuk Anda), atau dari entri `config.aml_field_sources` yang eksplisit (lihat [AML](#aml)).
* Fitur sub-KYB seperti `KYB_DOCUMENTS` dan `KYB_KEY_PEOPLE` memerlukan `KYB_REGISTRY` sebelumnya dalam alur kerja.
* Alur kerja adalah alur kerja orang (KYC) atau alur kerja bisnis (KYB), tidak pernah keduanya. Alur kerja yang menggunakan fitur KYB apa pun (`KYB_REGISTRY`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`) hanya boleh dikombinasikan dengan `AML`, `DOCUMENT_AI`, `QUESTIONNAIRE`, `PHONE_VERIFICATION`, `EMAIL_VERIFICATION`, `IP_ANALYSIS`, dan `SIGNATURE`. Alur kerja tersebut tidak boleh menyertakan fitur khusus orang seperti `OCR`, `LIVENESS`, `FACE_MATCH`, `NFC`, `PROOF_OF_ADDRESS`, `DATABASE_VALIDATION`, atau `AGE_ESTIMATION`, dan alur kerja orang tidak boleh menyertakan fitur KYB. Pada alur kerja bisnis, `DOCUMENT_AI` membandingkan setiap kolom yang ditandai `is_full_name` dengan perusahaan yang telah diverifikasi, bukan dengan orang. Untuk memverifikasi orang di balik perusahaan, buat alur kerja KYC terpisah dan rujuk dari node `KYB_KEY_PEOPLE` menggunakan `kyb_ubo_verification_workflow`, `kyb_officer_verification_workflow`, atau `kyb_shareholder_verification_workflow`.
* Kolom tindakan menggunakan `DECLINE`, `REVIEW`, atau `NO_ACTION`, kecuali kolom di bawahnya menyatakan bahwa kolom tersebut dibatasi.
* Kolom skor dan ambang batas berupa angka dari `0` hingga `100`, kecuali rentang yang lebih sempit dicantumkan.

## Aturan status umum

Setiap fitur mendukung array `status_rules` opsional. Gunakan array ini untuk menimpa status fitur saat kondisi pada sebuah kolom cocok.

```json theme={null}
{
  "status_rules": [
    {
      "field": "kyc.issuing_state",
      "operator": "in",
      "value": ["VEN", "IRN"],
      "status": "In Review",
      "value_type": "literal"
    },
    {
      "field": "kyc.extra_fields.profession",
      "operator": "fuzzy_match",
      "value": "Soft. Engineer",
      "score": 80,
      "status": "Declined",
      "value_type": "literal"
    },
    {
      "field": "kyc.extra_fields.dl_class_code_b_to",
      "operator": "less_than",
      "value": "2030-01-01",
      "status": "In Review",
      "value_type": "literal"
    },
    {
      "field": "kyc.extra_fields.dl_class_code_b_from",
      "operator": "less_than",
      "value": { "direction": "past", "amount": 3, "unit": "years" },
      "status": "Declined",
      "value_type": "relative_date"
    }
  ]
}
```

| Kolom | Jenis | Deskripsi |
| - | - | - |
| `field` | string | Jalur kolom yang akan diperiksa, misalnya `kyc.issuing_state` atau `kyc.document_type`. |
| `operator` | string | Salah satu dari `equals`, `not_equals`, `greater_than`, `greater_than_or_equals`, `less_than`, `less_than_or_equals`, `contains`, `not_contains`, `in`, `not_in`, `is_empty`, `is_not_empty`, `regex`, atau `fuzzy_match`. |
| `value` | any | Nilai pembanding. Hilangkan atau kirim `null` untuk operator yang tidak memerlukan nilai. |
| `status` | string | Salah satu dari `Approved`, `Declined`, `In Review`, atau `No Action`. |
| `value_type` | string | Opsional. Secara default `literal`. Gunakan `field` untuk membandingkan dengan kolom lain, `list` untuk menyelesaikan UUID daftar Didit saat runtime, atau `relative_date` untuk membandingkan kolom tanggal dengan hari ini ditambah atau dikurangi suatu durasi. |
| `score` | number | Wajib untuk `fuzzy_match`. Skor kemiripan minimum dari `0` hingga `100`. Aturan cocok ketika kemiripan yang dihitung lebih besar atau sama dengan nilai ini (`similarity >= score`). Misalnya, `Software Engineer` dapat cocok dengan `Soft. Engineer` jika kemiripannya minimal `80`. |

Baca contoh di atas sebagai: `kyc.extra_fields.profession` cocok secara fuzzy dengan `Soft. Engineer` dengan skor minimum `80` → atur status fitur menjadi `Declined`.

Untuk Verifikasi Identitas, targetkan nilai `extra_fields` yang diekstrak, seperti `kyc.extra_fields.profession`, tanggal berlaku kelas SIM seperti `kyc.extra_fields.dl_class_code_b_from` dan `kyc.extra_fields.dl_class_code_b_to`, atau kode pembatasan dan informasi per kelas seperti `kyc.extra_fields.dl_class_code_b_notes` (kolom 12 pada SIM Inggris). Nilai-nilai ini berasal dari objek `extra_fields` pada hasil OCR; nilai-nilai tersebut bukan bagian dari `expected_details`.

> [!NOTE]
>
> `dl_class_code_*_from` dan `dl_class_code_*_to` selalu berupa tanggal ISO yang valid atau tidak ada di `extra_fields`. Didit tidak pernah mengembalikan teks OCR yang tidak terbaca pada kolom tanggal. Jika sel tabel kelas tidak dapat dibaca, kolom tersebut dihilangkan alih-alih dikirim sebagai string mentah. Karena itu, gunakan operator `is_empty` untuk mengarahkan tanggal kelas yang tidak terbaca, dan jangan berasumsi bahwa kolom tersebut selalu ada.

Untuk kolom tanggal, gunakan `value_type: "relative_date"` dengan objek nilai berbentuk `{ "direction": "past" | "future", "amount": number, "unit": "days" | "months" | "years" }`. Misalnya, `operator: "less_than"` dengan `{ "direction": "past", "amount": 3, "unit": "years" }` cocok dengan tanggal yang lebih lama dari tiga tahun sebelum hari ini.

### Bandingkan dengan langkah tertentu

Alur kerja berbasis graf dapat menjalankan fitur yang sama lebih dari satu kali, misalnya tiga langkah Verifikasi Identitas.
Dengan `value_type: "field"`, tambahkan `@<node_id>` ke nilai untuk membacanya dari langkah tertentu.
Node yang dirujuk harus berupa langkah fitur yang selalu berjalan sebelum langkah aturan itu sendiri, di setiap jalur yang menuju ke sana, atau langkah aturan itu sendiri.
Nilai tanpa akhiran tersebut dibaca dari langkah aturan itu sendiri.

```json theme={null}
{
  "status_rules": [
    {
      "field": "kyc.full_name",
      "operator": "fuzzy_match",
      "value": "kyc.full_name@ocr_1",
      "value_type": "field",
      "score": 80,
      "status": "Declined"
    }
  ]
}
```

Baca aturan ini, yang diatur pada langkah Verifikasi Identitas ketiga, sebagai: `kyc.full_name` pada langkah ini cocok secara fuzzy dengan nama lengkap yang dibaca oleh langkah `ocr_1` dengan skor minimum `80` → atur status fitur menjadi `Declined`.
Di konsol, pemilih variabel mencantumkan setiap langkah yang memenuhi syarat berdasarkan nomornya pada kanvas, dan menyimpan akhiran tersebut untuk Anda.

## OCR / Verifikasi Identitas

Nilai fitur: `OCR`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `documents_allowed` | object | Opsional. Hilangkan, kirim `null`, atau kirim `{}` untuk mengizinkan semua negara dan jenis dokumen yang didukung. Kirim kode negara ISO3 ke konfigurasi jenis dokumen hanya jika Anda ingin membatasi dokumen yang diizinkan. Setidaknya satu dokumen kustom harus memiliki `enabled: 1`. Konfigurasi dokumen dapat menyertakan `sides: 1` untuk pengambilan hanya bagian depan atau `sides: 2` untuk pengambilan bagian depan dan belakang. Jenis dokumen mencakup `P`, `ID`, `DL`, `RP`, `HIC`, `TC`, `SSC`, dan nilai lain yang didukung negara. |
| `methods` | object | Metode dari tiga [metode Verifikasi Identitas](https://docs.didit.me/id/core-technology/id-verification/verification-methods.md) yang boleh digunakan setiap negara: pengambilan dokumen, pencarian non-dokumen terhadap sumber pemerintah atau sumber resmi lain, dan dompet ID digital. Jika kunci, negara, atau metode di dalam negara dihilangkan, negara tersebut hanya menggunakan pengambilan dokumen. Setiap metode dan dompet harus ditandai tersedia untuk negara tersebut di katalog kapabilitas, atau penyimpanan akan ditolak. Lihat [Metode per negara](#metode-per-negara) di bawah. |
| `document_blur_fields_by_country` | object | Kode negara ISO3 ke nama kolom yang akan diburamkan untuk disamarkan pada gambar dokumen. |
| `image_capture_methods_allowed` | string\[] | Metode pengambilan gambar yang diizinkan. Nilai mencakup `CAMERA_SCAN` dan `UPLOAD`. |
| `duplicated_user_action` | action | Tindakan untuk pengguna duplikat. |
| `is_age_restrictions_enabled` | boolean | Mengaktifkan pemeriksaan usia minimum dan maksimum. |
| `age_restrictions_by_country` | object | Kode negara ISO3 ke konfigurasi usia dengan `minimum_age`, `maximum_age` opsional, dan `states` opsional. |
| `minimum_age` | integer | Usia minimum global, `1` sampai `120`. |
| `minimum_age_action` | action | Tindakan ketika pengguna berusia di bawah `minimum_age`. |
| `maximum_age` | integer | Usia maksimum global, `1` sampai `120`. |
| `maximum_age_action` | action | Tindakan ketika pengguna berusia di atas `maximum_age`. |
| `expiration_date_not_detected_action` | action | Tindakan ketika tanggal kedaluwarsa dokumen tidak terdeteksi. |
| `invalid_code_action` | action | Tindakan ketika barcode atau kode yang dapat dibaca mesin tidak valid. |
| `invalid_mrz_action` | action | Tindakan ketika MRZ tidak valid. |
| `inconsistent_data_action` | action | Tindakan ketika kolom dokumen yang diekstrak saling bertentangan. |
| `invalid_validation_action` | action | Tindakan ketika validasi dokumen gagal. |
| `expected_details_mismatch_action` | action | Tindakan ketika detail pengguna yang diharapkan tidak cocok dengan dokumen. |
| `image_too_blurry_action` | action | Tindakan untuk gambar dokumen yang buram. |
| `image_too_dark_action` | action | Tindakan untuk gambar dokumen yang gelap. |
| `image_too_bright_action` | action | Tindakan untuk gambar dokumen yang terlalu terang. |
| `unparsed_address_action` | action | Tindakan ketika alamat dokumen tidak dapat diurai. |
| `address_validation_enabled` | boolean | Memvalidasi alamat yang dibaca langkah ini (tercetak pada dokumen identitas) terhadap data referensi pos: memastikan alamat itu ada dan menormalkannya, serta tidak pernah mengaitkannya dengan seseorang. Hasilnya terdapat dalam objek `address_validation` milik langkah tersebut di dalam keputusan. **Dikenakan biaya \$0.10 per alamat tervalidasi**; validasi yang tidak dapat dijalankan (`unavailable`) tidak dikenakan biaya. Nonaktif secara default. |
| `address_not_verified_action` | action | Tindakan ketika Validasi Alamat tidak dapat memastikan alamat sampai ke tingkat gedung (`ADDRESS_NOT_VERIFIED`: `partially_verified` atau `not_verified`). Hanya berlaku selama `address_validation_enabled` aktif. Defaultnya `NO_ACTION`, yang hanya mencatat peringatan. |
| `document_or_personal_number_format_mismatch_action` | action | Tindakan ketika format nomor dokumen atau nomor pribadi tidak sesuai dengan pola yang diharapkan. |
| `critical_field_occlusion_action` | action | Tindakan ketika pemeriksaan penutupan (occlusion) melaporkan bahwa kolom cetak penting, yaitu nomor identitas, nama, tanggal lahir, atau tanggal kedaluwarsa, tertutup secara fisik pada dokumen yang diambil. Menutupi nomor identitas merupakan sinyal manipulasi, bukan masalah kualitas pengambilan gambar, sehingga nilai ini defaultnya `REVIEW`. Nilai yang terbaca untuk kolom yang tertutup tetap dibuang dari hasil ekstraksi dalam kedua kasus. Naikkan ke `DECLINE` jika dokumen yang disamarkan tidak boleh pernah sampai ke peninjau. |
| `document_without_portrait_action` | action | Tindakan ketika jenis dokumen yang dikenali tidak pernah memuat foto potret di sisi mana pun (sebagian izin tinggal, kartu kesehatan, sertifikat registrasi, dan keluarga dokumen lain tanpa potret yang dikenal oleh katalog). Defaultnya `REVIEW`. Pertimbangkan `DECLINE` jika Pencocokan Wajah menjadi dasar pemeriksaan identitas dalam alur kerja. |
| `is_document_selfie_portrait_match_enabled` | boolean | Mengaktifkan perbandingan potret dokumen dengan swafoto. |
| `document_selfie_portrait_match_decline_threshold` | integer | Ambang batas penolakan untuk pencocokan potret dokumen dengan swafoto. |
| `document_selfie_portrait_match_review_threshold` | integer | Ambang batas peninjauan untuk pencocokan potret dokumen dengan swafoto. |
| `document_selfie_face_search_enabled` | boolean | Menjalankan [Pencarian Wajah 1:N](https://docs.didit.me/id/core-technology/face-search/overview.md#swafoto-yang-diambil-selama-pengambilan-dokumen) pada swafoto yang diambil saat pengambilan dokumen (membutuhkan `is_document_selfie_portrait_match_enabled`): mencocokkannya dengan daftar blokir wajah dan pengguna yang sebelumnya telah diverifikasi. Swafoto hanya dibandingkan, dan templatnya tidak pernah disimpan. Aktif secara default. Nilai `false` melewati pencarian dan membuat tindakan duplikasi wajah pada swafoto dokumen tidak memiliki hasil untuk ditindaklanjuti. `face_search_enabled: false` pada langkah Deteksi Liveness juga melewati pencarian ini, karena pilihan untuk tidak ikut tersebut berlaku untuk setiap swafoto dalam sesi. |
| `document_selfie_duplicated_face_action` | action | Keputusan ketika swafoto pada pengambilan dokumen cocok, atau mungkin cocok, dengan wajah pengguna yang sudah diverifikasi dalam aplikasi ini. Defaultnya `NO_ACTION`. |
| `document_selfie_duplicated_face_name_mismatch_action` | action | Keputusan ketika swafoto pada pengambilan dokumen cocok dengan pengguna yang sudah diverifikasi dengan nama berbeda. Hanya dapat menaikkan tingkat `document_selfie_duplicated_face_action`. Defaultnya `REVIEW`. |
| `document_selfie_duplicated_face_document_mismatch_action` | action | Keputusan ketika swafoto pada pengambilan dokumen cocok dengan pengguna yang sudah diverifikasi dengan tanggal lahir berbeda pada dokumen identitasnya. Orang yang sama dengan dokumen berbeda atau dokumen yang diperbarui tidak ditandai. Hanya dapat menaikkan tingkat `document_selfie_duplicated_face_action`. Defaultnya `REVIEW`. |
| `id_verification_name_match_score_threshold` | integer | Ambang batas kecocokan nama di beberapa verifikasi identitas. |
| `id_verification_max_retry_attempts` | integer | Batas percobaan ulang untuk verifikasi identitas, `2` sampai `5`. |
| `id_document_quality_threshold` | integer | Skor kualitas pengambilan gambar minimum (`0` sampai `100`) yang harus dicapai gambar dokumen agar diterima. Pemeriksaan kualitas selalu berjalan; hanya ambang batas ini yang dapat dikonfigurasi. Defaultnya `20`, disetel agar pengambilan yang kualitasnya menurun dan berada di ambang batas (buram, gerakan, teks tidak terbaca) ditolak, sementara dokumen yang jelas lolos; naikkan nilainya untuk persyaratan pengambilan yang lebih ketat. Konsol menampilkan nilai ini pada penggeser perseptual, dengan default `20` ditampilkan sebagai 50% (seimbang). |
| `cross_org_fraud_document_action` | action | Keputusan saat dokumen ini ditandai sebagai palsu oleh organisasi lain dalam jaringan. |
| `document_audio_recording_enabled` | boolean | Rekam mikrofon selama pengambilan dokumen, sehingga peninjau dapat mendengar sesi tersebut. Nonaktif secara default. |
| `document_liveness_portrait_replace_decline_threshold` | integer | Skor penggantian potret (`0` sampai `100`, makin tinggi = makin mungkin asli) di bawah nilai ini sesi ditolak. Defaultnya `35`. Lihat [ambang batas liveness dokumen](https://docs.didit.me/id/core-technology/id-verification/warnings-id-verification.md#mengonfigurasi-ambang-batas-liveness-dokumen). |
| `document_liveness_portrait_replace_review_threshold` | integer | Skor penggantian potret di bawah nilai ini sesi masuk dalam peninjauan, jika belum ditolak. Pada `100`, hampir setiap sesi ditahan. Defaultnya `70`. Lihat [ambang batas liveness dokumen](https://docs.didit.me/id/core-technology/id-verification/warnings-id-verification.md#mengonfigurasi-ambang-batas-liveness-dokumen). |
| `document_liveness_printed_copy_decline_threshold` | integer | Skor salinan cetak (`0` sampai `100`, makin tinggi = makin mungkin asli) di bawah nilai ini sesi ditolak. Defaultnya `35`. Lihat [ambang batas liveness dokumen](https://docs.didit.me/id/core-technology/id-verification/warnings-id-verification.md#mengonfigurasi-ambang-batas-liveness-dokumen). |
| `document_liveness_printed_copy_review_threshold` | integer | Skor salinan cetak di bawah nilai ini sesi masuk dalam peninjauan, jika belum ditolak. Pada `100`, hampir setiap sesi ditahan. Defaultnya `77`. Lihat [ambang batas liveness dokumen](https://docs.didit.me/id/core-technology/id-verification/warnings-id-verification.md#mengonfigurasi-ambang-batas-liveness-dokumen). |
| `document_liveness_screen_replay_decline_threshold` | integer | Skor penangkapan layar (`0` sampai `100`, makin tinggi = makin mungkin asli) di bawah nilai ini sesi ditolak. Defaultnya `30`. Lihat [ambang batas liveness dokumen](https://docs.didit.me/id/core-technology/id-verification/warnings-id-verification.md#mengonfigurasi-ambang-batas-liveness-dokumen). |
| `document_liveness_screen_replay_review_threshold` | integer | Skor penangkapan layar di bawah nilai ini sesi masuk dalam peninjauan, jika belum ditolak. Pada `100`, hampir setiap sesi ditahan. Defaultnya `70`. Lihat [ambang batas liveness dokumen](https://docs.didit.me/id/core-technology/id-verification/warnings-id-verification.md#mengonfigurasi-ambang-batas-liveness-dokumen). |
| `id_verification_injection_attack_action` | action | Keputusan saat dokumen, atau swafoto yang diambil untuk pencarian ID, disuntikkan dan bukan diambil dari kamera perangkat itu sendiri (`INJECTION_ATTACK_DETECTED`): kamera virtual perangkat lunak, feed kamera yang dibuat oleh halaman atau oleh otomatisasi browser, kamera yang di-hook, atau alat instrumentasi yang terpasang pada aplikasi. Nilai: `DECLINE`, `REVIEW`, `NO_ACTION`. Defaultnya `DECLINE`. Sinyal yang dapat dihasilkan oleh orang asli tidak pernah memicunya. Pada Deteksi Liveness dan Pencocokan Wajah, risikonya mengikuti `frame_injection_action` sebagai gantinya. |
| `image_quality_too_low_action` | action | Keputusan saat kualitas gambar dokumen secara keseluruhan berada di bawah standar. |
| `is_image_capture_review_screen_enabled` | boolean | Tampilkan layar tinjauan kepada pengguna setelah setiap pengambilan dokumen, sehingga mereka dapat mengambil ulang foto sebelum dikirim. Nonaktif secara default. |
| `is_ocr_id_verification_data_review_enabled` | boolean | Izinkan pengguna meninjau dan memperbaiki data identitas yang diekstrak sebelum langkah selesai. Nonaktif secara default. Koreksi dinilai terhadap `ocr_id_verification_data_review_critical_fields`, dan ketidaksesuaian memicu tindakan kritis atau tindakan minor sesuai dengan kolomnya. Tinjauan tetap berjalan saat alur kerja menyertakan NFC - pembacaan chip berikutnya cukup menggantikannya. |
| `ocr_id_verification_data_review_critical_fields` | string\[] | Kolom identitas yang diekstrak mana yang dihitung sebagai kritis saat pengguna mengedit hasil OCR, sehingga ketidaksesuaian memicu tindakan kritis dan bukan tindakan minor. Bentuk: `["first_name" \| "last_name" \| "date_of_birth" \| ...]`. |
| `ocr_id_verification_data_review_critical_mismatch_action` | restricted action | Keputusan saat edit pengguna tidak sesuai dengan OCR pada kolom kritis. |
| `ocr_id_verification_data_review_minor_mismatch_action` | action | Keputusan saat edit pengguna tidak sesuai dengan OCR pada kolom non-kritis. |
| `status_rules` | array | Aturan status kustom opsional. |

> [!NOTE]
>
> Deteksi Liveness dokumen dikonfigurasi dengan enam ambang batas `document_liveness_*` di atas, bukan dengan kolom tindakan per sinyal. `portrait_replacement_action`, `printed_copy_action`, dan `screen_capture_action` adalah pengaturan tingkat akun dan **tidak** diterima dalam konfigurasi fitur alur kerja: API menghapus kunci konfigurasi yang tidak dikenal saat disimpan, sehingga mengirimkannya di sana tidak berpengaruh. Setiap sinyal memiliki ambang batas tolak dan ambang batas tinjau pada skala `0`-`100`, di mana skor yang lebih tinggi berarti dokumen makin mungkin asli.

Contoh:

```json theme={null}
{
  "feature": "OCR",
  "config": {
    "documents_allowed": {
      "USA": {
        "DL": {
          "enabled": 1,
          "sides": 2
        }
      }
    },
    "duplicated_user_action": "REVIEW",
    "image_capture_methods_allowed": ["CAMERA_SCAN", "UPLOAD"]
  }
}
```

### Metode per negara

`methods` menggunakan kode negara [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) sebagai kuncinya. Setiap negara memuat hingga tiga objek metode; apa pun yang Anda hilangkan akan mengambil nilai default-nya.

```json theme={null}
{
  "feature": "OCR",
  "config": {
    "methods": {
      "ZAF": {
        "document": { "enabled": true },
        "id_lookup": {
          "enabled": true,
          "max_attempts": 2,
          "skip_liveness_and_face_match": true,
          "on_partial_match": "fallback_to_document",
          "on_no_match": "fallback_to_document",
          "on_provider_error": "fallback_to_document"
        },
        "wallet": { "enabled": false, "providers": [], "on_failure": "fallback_to_document" }
      },
      "DNK": {
        "document": { "enabled": true },
        "id_lookup": { "enabled": true, "on_no_match": "decline" }
      }
    }
  }
}
```

`wallet.on_failure` bernilai `fallback_to_document`, `decline`, atau `retry`. `retry` (khusus dompet, pengambilan dokumen nonaktif untuk negara tersebut) membuat pengguna yang proses masuknya di langkah dompet belum selesai dapat mencoba lagi; sesi tidak pernah ditolak karenanya dan tetap terbuka hingga mereka selesai atau sesinya kedaluwarsa. Sakelar id\_lookup hanya menerima `fallback_to_document` atau `decline`.

Untuk menjaga dokumen agar tidak muncul di layar pertama dan hanya menawarkannya saat dompet atau pencarian tidak berhasil, atur `document.fallback_only`. Contoh ini menggunakan Finlandia, di mana Finnish Trust Network ditampilkan lebih dulu dan pengambilan dokumen menjadi cadangan. Finlandia juga perlu jenis dokumennya diaktifkan di `documents_allowed` (misalnya paspor dan kartu identitas) agar cadangan memiliki dokumen untuk ditawarkan.

```json theme={null}
{
  "FIN": {
    "document": { "enabled": true, "fallback_only": true },
    "wallet": { "enabled": true, "providers": ["ftn"], "on_failure": "fallback_to_document" }
  }
}
```

Kedua pencarian di atas berstatus `available` dalam katalog saat ini, sehingga konfigurasi tersebut tersimpan seperti yang tertulis. Blok dompet sengaja tidak disertakan dalam contoh ini: blok dompet hanya dapat disimpan di negara yang katalognya menandai dompet tersebut sebagai `available`, dan `wallet.enabled: true` di tempat lain akan ditolak dan menggagalkan seluruh penyimpanan, termasuk konfigurasi pencarian. Jika katalog menandai dompet sebagai `available` di suatu negara, tambahkan blok dompet tersebut ke konfigurasi negara itu:

```json theme={null}
{
  "DNK": {
    "document": { "enabled": true },
    "wallet": { "enabled": true, "providers": ["mitid"], "on_failure": "fallback_to_document" }
  }
}
```

| Kunci | Tipe | Default | Deskripsi |
| - | - | - | - |
| `<ISO3>.document.enabled` | boolean | `true` | Apakah dokumen yang difoto diterima di negara ini. Dokumen mana yang diterima tetap diatur di `documents_allowed`. |
| `<ISO3>.document.fallback_only` | boolean | `false` | Tetap mengaktifkan pengambilan dokumen, tetapi tidak menawarkannya di layar pertama. Pengguna memulai dengan dompet atau pencarian ID negara tersebut, dan hanya pengguna yang proses masuk dompetnya gagal, dibatalkan, atau mengalami waktu habis, atau yang hasil pencariannya tidak cocok (sesuai dengan sakelar `on_failure`, `on_partial_match`, `on_no_match` dan `on_provider_error` yang diatur ke `fallback_to_document`) yang diarahkan ke pengambilan dokumen. Dengan satu dompet, pengguna langsung diarahkan ke dompet tersebut. Tanpa dompet, dompet atau pencarian ditampilkan berdampingan dengan pengambilan dokumen. Ditolak dengan HTTP 400 kecuali `document.enabled` bernilai `true` dan setidaknya satu dompet atau pencarian ID di negara tersebut kembali ke pengambilan dokumen. |
| `<ISO3>.id_lookup.enabled` | boolean | `false` | Tawarkan pencarian non-dokumen terhadap sumber pemerintah atau otoritatif lain di negara ini. Ditolak jika katalog tidak menandai sumber negara sebagai `available`. |
| `<ISO3>.id_lookup.max_attempts` | integer | `1` | `1` hingga `5`. Berapa banyak pencarian **yang dijawab** yang dapat dilakukan pengguna sebelum sakelar fallback aktif. Angka yang gagal pemeriksaan format di sisi klien tidak pernah sampai ke registri, sehingga tidak dihitung dan tidak ditagih. |
| `<ISO3>.id_lookup.skip_liveness_and_face_match` | boolean | `true` | Setelah kecocokan dengan registri yang mengembalikan potret, lewati langkah Deteksi Liveness dan Pencocokan Wajah milik alur kerja, karena pencarian sudah menjalankan liveness pasif pada swafoto dan mencocokkannya dengan potret tersebut. Dinormalisasi menjadi `false` saat disimpan untuk sumber yang tidak mengembalikan potret, karena sakelar tersebut tidak berarti apa-apa di sana. |
| `<ISO3>.id_lookup.on_partial_match` | `fallback_to_document` \| `decline` | `fallback_to_document` | Apa yang terjadi ketika registri menjawab tetapi sebagian kolom tidak cocok. |
| `<ISO3>.id_lookup.on_no_match` | `fallback_to_document` \| `decline` | `fallback_to_document` | Apa yang terjadi ketika registri menjawab dan tidak memiliki catatan yang cocok. |
| `<ISO3>.id_lookup.on_provider_error` | `fallback_to_document` \| `decline` | `fallback_to_document` | Apa yang terjadi ketika registri tidak dapat dihubungi. Tidak pernah ditagih. |
| `<ISO3>.id_lookup.response_fields` | string\[] \| null | `null` | Subset opsional dari kunci kolom respons sumber. Kunci yang tidak dikenal ditolak, dan kolom wajib sumber selalu ditambahkan kembali, sehingga nilai yang disimpan selalu merupakan pilihan yang valid. Implementasi staging saat ini menerapkan pilihan ini pada output perbandingan, gender opsional, dan potret registri yang disimpan. Kolom identitas wajib tetap ada. Lihat catatan rollout dan retensi di bawah. |
| `<ISO3>.wallet.enabled` | boolean | `false` | Tawarkan masuk dengan dompet ID digital di negara ini. |
| `<ISO3>.wallet.providers` | string\[] | `[]` | ID dompet katalog yang diterima negara ini, berupa daftar izin, bukan peringkat. Urutan yang Anda kirim dinormalisasi ke urutan katalog. Setidaknya satu dompet wajib ada saat `enabled` bernilai `true`. Dompet yang tidak ditawarkan di negara tersebut, atau yang belum tersedia, ditolak. |
| `<ISO3>.wallet.on_failure` | `fallback_to_document` \| `decline` \| `retry` | `fallback_to_document` | Apa yang terjadi ketika masuk dibatalkan, kehabisan waktu, atau gagal. `retry` membuat pengguna tetap di langkah dompet untuk mencoba lagi (khusus dompet). Opsi ini ditolak bersama `document.fallback_only`. |

Validasi yang diterapkan API saat disimpan:

* Kode negara yang tidak dikenal, kunci yang tidak dikenal di dalam sebuah negara, atau kunci yang tidak dikenal di dalam sebuah metode akan ditolak. Tidak ada yang dibuang diam-diam.
* Negara yang tidak mengaktifkan satu metode pun akan ditolak, karena tidak ada yang bisa melakukan verifikasi di sana.
* Dompet atau pencarian hanya bisa kembali ke pengambilan dokumen jika pengambilan dokumen diaktifkan untuk negara tersebut. `fallback_to_document` di negara yang `document.enabled`-nya `false` akan ditolak saat runtime, karena tidak ada tujuan untuk kembali.
* `document.fallback_only: true` ditolak dengan HTTP 400 kecuali `document.enabled` bernilai `true` dan setidaknya satu dompet atau pencarian ID di negara tersebut kembali ke pengambilan dokumen.

> [!WARNING]
>
> Implementasi staging saat ini menerapkan `id_lookup.response_fields` pada output perbandingan, gender opsional, dan potret registri yang disimpan. Kolom identitas wajib tetap menjadi bagian dari catatan verifikasi. Ini bukan jaminan bahwa setiap payload penyedia perantara dikecualikan dari pemrosesan. Rollout produksi untuk perubahan ini belum diverifikasi. Pastikan perilakunya di lingkungan target Anda sebelum mengandalkan pemilihan kolom untuk kebutuhan retensi.

Baca katalog kapabilitas sebelum Anda menulis `methods`, melalui tab **Negara** di konsol, atau dengan alat MCP [`didit_workflow_get_id_verification_methods_catalog`](https://docs.didit.me/id/integration/mcp/tools). Perilaku, cakupan, dan penagihan dijelaskan di [Metode Verifikasi Identitas](https://docs.didit.me/id/core-technology/id-verification/verification-methods.md).

## NFC / ePassport

Nilai fitur: `NFC`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `allow_nfc_skip` | boolean | Memungkinkan pengguna melewati NFC jika dokumen mereka mendukung pembacaan chip. |
| `skip_nfc_action` | tindakan | Tindakan saat pengguna melewati NFC. |
| `unverified_chip_action` | tindakan | Tindakan saat verifikasi chip gagal. |
| `trust_anchor_missing_action` | tindakan | Keputusan saat hash grup data pada chip masih utuh, tetapi rantai sertifikat tidak dapat diverifikasi karena trust anchor CSCA dari negara penerbit belum dimuat. |
| `jpki_request_attributes` | boolean | Kartu My Number Jepang ([JPKI](https://docs.didit.me/id/core-technology/nfc-verification/overview.md#japan-my-number-card-jpki), hanya SDK native): juga membaca sertifikat tanda tangan, yang memerlukan PIN tanda tangan kartu dan memuat nama, tanggal lahir, jenis kelamin, dan alamat pemegang kartu, untuk dibandingkan dengan data verifikasi identitas. Default `true`. `false` hanya membaca sertifikat autentikasi pengguna (PIN 4 digit), yang membuktikan kartu dan PIN tetapi tidak memuat data pemegang kartu. |
| `jpki_certificate_invalid_action` | tindakan | Keputusan saat sertifikat Kartu My Number tidak terhubung ke otoritas sertifikasi JPKI, berada di luar masa berlaku, atau bukan sertifikat kartu dengan jenis yang diminta (`JPKI_CERTIFICATE_INVALID`). Default `DECLINE`. |
| `jpki_signature_invalid_action` | tindakan | Keputusan saat tanda tangan Kartu My Number atas tantangan sekali pakai tidak dapat diverifikasi, sehingga kepemilikan kartu dan pengetahuan atas PIN-nya tidak terbukti (`JPKI_SIGNATURE_INVALID`). Default `DECLINE`. |
| `jpki_certificate_revoked_action` | tindakan | Keputusan saat pemeriksaan pencabutan melaporkan sertifikat Kartu My Number telah dicabut (`JPKI_CERTIFICATE_REVOKED`). Default `DECLINE`. |
| `jpki_revocation_unchecked_action` | tindakan | Keputusan saat Kartu My Number telah diverifikasi tetapi tidak ada jawaban pemeriksaan pencabutan, sehingga kartu yang dicabut tidak dapat dikesampingkan (`JPKI_REVOCATION_UNCHECKED`). Default `REVIEW`. |
| `jpki_inconsistent_data_action` | tindakan | Keputusan saat nama, tanggal lahir, jenis kelamin, atau alamat dalam sertifikat tanda tangan Kartu My Number berbeda dengan data verifikasi identitas dari kartu yang sama (`JPKI_AND_OCR_DATA_NOT_SAME`). Default `REVIEW`. |
| `status_rules` | array | Aturan status kustom opsional. |

## Deteksi Liveness

Nilai fitur: `LIVENESS`.

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `face_liveness_method` | string | Salah satu dari `ACTIVE_3D`, `FLASHING`, atau `PASSIVE`. |
| `face_liveness_mode` | string | Penggantian mode liveness. |
| `face_liveness_flash_mode` | string | Mode flash untuk metode `ACTIVE_3D` dan `FLASHING`. `"0"` (tidak ketat, default) memverifikasi bahwa warna yang berkedip di layar terpantul pada wajah pengguna; `"1"` (ketat) juga mewajibkan pantulan sesuai dengan urutan warna kedipan yang tepat, lebih kuat terhadap serangan replay dan injeksi video, tetapi dengan lebih banyak penolakan keliru. |
| `face_liveness_score_decline_threshold` | integer | Ambang batas penolakan. |
| `face_liveness_score_review_threshold` | integer | Ambang batas peninjauan. |
| `face_liveness_possible_duplicated_face_action` | action | Tindakan saat wajah mungkin terduplikasi. |
| `face_liveness_multiple_faces_action` | action | Tindakan saat beberapa wajah terdeteksi. |
| `face_liveness_video_anomaly_action` | action | Tindakan saat rekaman yang tersimpan berisi urutan gerakan yang berulang. Default `NO_ACTION`; `REVIEW` dan `DECLINE` dapat mengeskalasi verifikasi yang telah diputuskan secara asinkron. Frame diam yang jarang atau berulang saja tidak memicunya. |
| `face_liveness_attack_face_match_action` | action | Tindakan saat wajah liveness cocok dengan wajah dari sesi sebelumnya di aplikasi ini milik pengguna lain yang pengambilannya dinilai sebagai serangan liveness dengan keyakinan tinggi (peringatan `FACE_MATCHES_LIVENESS_ATTACK`). Menerima `NO_ACTION` atau `REVIEW`; `DECLINE` diterima tetapi diterapkan sebagai `REVIEW`, karena pengguna asli bisa ditolak sekali secara keliru lalu lolos. Default `NO_ACTION`. |
| `race_map_similarity_thresholds` | object | Ambang batas kemiripan per demografi. |
| `face_privacy_mode_enabled` | boolean | Mengaktifkan mode privasi untuk aset wajah. |
| `face_quality_review_threshold` | integer | Ambang batas peninjauan untuk kualitas gambar wajah. |
| `face_quality_decline_threshold` | integer | Ambang batas penolakan untuk kualitas gambar wajah. Harus kurang dari atau sama dengan ambang batas peninjauan. |
| `face_luminance_min_threshold` | integer | Ambang batas luminans minimum. Harus lebih rendah dari `face_luminance_max_threshold`. |
| `face_luminance_min_action` | action | Tindakan saat luminans terlalu rendah. |
| `face_luminance_max_threshold` | integer | Ambang batas luminans maksimum. |
| `face_luminance_max_action` | action | Tindakan saat luminans terlalu tinggi. |
| `face_liveness_max_attempts` | integer | Total pengajuan liveness per sesi, `1` sampai `3`. Default `3` berarti satu percobaan awal ditambah dua coba lagi. Mengatur `1` tidak menonaktifkan coba lagi untuk kegagalan kualitas pengambilan: ketika setiap peringatan pada percobaan terkait dengan kondisi lingkungan (`LOW_FACE_LUMINANCE`, `HIGH_FACE_LUMINANCE`, `LOW_FACE_QUALITY`, `HIGH_FACE_OCCLUSION`, `NO_FACE_DETECTED`), pengguna selalu mendapatkan percobaan kedua dengan umpan balik yang dapat ditindaklanjuti. |
| `cross_org_fraud_face_action` | action | **Tidak digunakan lagi dan tidak lagi diterapkan.** Ini memperlakukan wajah seolah membawa putusan penipuan, yang tidak dapat dilakukan oleh identitas biometrik yang stabil. Tetap diterima agar alur kerja yang ada tetap tervalidasi. Gunakan `cross_org_identity_claim_pattern_action`. |
| `cross_org_identity_claim_pattern_action` | action | Putusan saat organisasi lain dalam jaringan mencatat event klaim identitas untuk orang yang sama, di mana identitas yang diklaim tidak cocok. Hanya peninjauan atau tidak ada tindakan; Penolakan yang diatur di sini diturunkan menjadi Peninjauan. Lihat [Klaim identitas lintas organisasi](https://docs.didit.me/id/core-technology/liveness/cross-organization-identity-claims.md). |
| `external_capture_device_action` | action | Putusan saat perangkat pengambilan eksternal terdeteksi. |
| `face_audio_recording_enabled` | boolean | Merekam mikrofon selama pengambilan swafoto, sehingga peninjau dapat mendengar sesi. Nonaktif secara default. |
| `face_search_enabled` | boolean | Menjalankan [Pencarian Wajah 1:N](https://docs.didit.me/id/core-technology/face-search/overview.md#menonaktifkan-pencarian-wajah-otomatis) otomatis pada swafoto: mencocokkannya dengan pengguna yang telah diverifikasi sebelumnya, daftar blokir dan daftar izin wajah, serta menyimpan templat biometriknya untuk pencocokan selanjutnya. Aktif secara default. `false` melewati pencarian, tidak menyimpan templat wajah untuk langkah ini, dan membuat tindakan wajah terduplikasi tidak memiliki apa pun untuk ditindaklanjuti. |
| `face_liveness_uncertain_retry_enabled` | boolean | Hanya untuk liveness aktif pada SDK native. Saat aktif, pengambilan yang skor livenessnya lebih besar dari `face_liveness_score_decline_threshold` dan lebih kecil dari `face_liveness_score_review_threshold` tidak pernah diputuskan, apa pun putusan yang dilampirkan mesin padanya: orang tersebut diberi tahu bahwa hasilnya tidak jelas dan diminta mengambil ulang, setiap kali, di luar anggaran `face_liveness_max_attempts` (yang tetap berlaku untuk pengambilan yang tidak dapat diberi skor oleh mesin). Nonaktif secara default; alur web mengabaikannya. |
| `face_liveness_duplicated_face_name_mismatch_action` | action | Putusan saat wajah duplikat ditemukan dengan nama yang berbeda. |
| `face_liveness_duplicated_face_document_mismatch_action` | action | Putusan saat wajah duplikat ditemukan dan dokumen identitas pengguna yang cocok menunjukkan tanggal lahir yang berbeda. Orang yang sama dengan dokumen yang berbeda atau diperbarui tidak ditandai. Default `REVIEW`. |
| `frame_injection_action` | action | Putusan saat frame video yang disuntikkan terdeteksi. |
| `screen_capture_action` | action | Putusan saat swafoto adalah foto dari layar. |
| `virtual_camera_action` | action | Putusan saat umpan kamera virtual terdeteksi. |
| `status_rules` | array | Aturan status kustom opsional. |

## Pencocokan Wajah

Nilai fitur: `FACE_MATCH`.

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `face_match_score_decline_threshold` | integer | Ambang batas penolakan. |
| `face_match_score_review_threshold` | integer | Ambang batas peninjauan. |
| `face_match_max_attempts` | integer | Total pengajuan pencocokan wajah per sesi, `1` sampai `3`. Default `3` berarti satu percobaan awal ditambah dua kali coba lagi. |
| `face_match_not_computed_action` | tindakan terbatas | Keputusan saat tidak ada skor pencocokan wajah yang dapat dihasilkan (foto potret atau swafoto tidak ada). |
| `face_match_eyes_covered_action` | tindakan | Keputusan saat area mata tertutup pada swafoto. Default-nya `NO_ACTION`, yang mencatat bukti tanpa mengubah hasil Pencocokan Wajah. Sinyal ini masih dikalibrasi, sehingga hanya dicatat sampai area tersebut dilaporkan sudah terkalibrasi: jika Anda menetapkan `REVIEW` atau `DECLINE` sekarang, nilai tersebut berlaku mulai saat itu. |
| `face_match_mouth_covered_action` | tindakan | Keputusan saat area mulut tertutup pada swafoto. Default `NO_ACTION` yang sama dan catatan kalibrasi yang sama seperti `face_match_eyes_covered_action`. |
| `face_match_face_covered_action` | tindakan | Keputusan saat wajah secara keseluruhan tertutup pada swafoto. Default `NO_ACTION` yang sama dan catatan kalibrasi yang sama seperti `face_match_eyes_covered_action`. |
| `status_rules` | array | Aturan status kustom opsional. |

## Estimasi Usia

Nilai fitur: `AGE_ESTIMATION`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `enable_id_verification_fallback` | boolean | Menjalankan Verifikasi Identitas saat estimasi usia berada di rentang borderline. |
| `minimum_age_threshold` | integer | Usia minimum yang diterima, `1` sampai `100`. |
| `borderline_minimum_age_threshold` | integer | Batas bawah rentang borderline, `1` sampai `100`. |
| `borderline_maximum_age_threshold` | integer | Batas atas rentang borderline, `1` sampai `100`. |
| `face_liveness_method` | string | Salah satu dari `ACTIVE_3D`, `FLASHING`, atau `PASSIVE`. |
| `face_liveness_flash_mode` | string | Mode kilatan untuk metode `ACTIVE_3D` dan `FLASHING`. `"0"` (tidak ketat, default) memverifikasi bahwa warna yang dikilaskan di layar terpantul pada wajah pengguna; `"1"` (ketat) juga mewajibkan pantulan sesuai dengan urutan warna yang dikilaskan secara persis. |
| `face_liveness_score_decline_threshold` | number | Ambang batas tolak untuk pemeriksaan liveness yang digunakan oleh estimasi usia. |
| `face_liveness_score_review_threshold` | number | Ambang batas peninjauan untuk pemeriksaan liveness yang digunakan oleh estimasi usia. |
| `face_liveness_possible_duplicated_face_action` | action | Tindakan saat wajah mungkin duplikat. |
| `face_liveness_multiple_faces_action` | action | Tindakan saat terdeteksi lebih dari satu wajah. |
| `face_liveness_video_anomaly_action` | action | Tindakan saat rekaman yang tersimpan berisi urutan gerakan yang berulang. Default `NO_ACTION`; `REVIEW` dan `DECLINE` dapat mengeskalasi verifikasi yang telah diputuskan secara asinkron. Bingkai diam yang jarang atau berulang saja tidak memicunya. |
| `face_liveness_attack_face_match_action` | action | Tindakan saat wajah pada pemeriksaan liveness cocok dengan wajah dari sesi sebelumnya di aplikasi ini milik pengguna lain yang pengambilannya sebelumnya dinilai sebagai serangan liveness dengan keyakinan tinggi (peringatan `FACE_MATCHES_LIVENESS_ATTACK`). Menerima `NO_ACTION` atau `REVIEW`; `DECLINE` diterima tetapi diterapkan sebagai `REVIEW`, karena pengguna asli bisa ditolak sekali secara keliru lalu lolos. Default `NO_ACTION`. |
| `face_privacy_mode_enabled` | boolean | Mengaktifkan mode privasi untuk aset wajah. |
| `face_quality_review_threshold` | integer | Ambang batas peninjauan untuk kualitas wajah. |
| `face_quality_decline_threshold` | integer | Ambang batas tolak untuk kualitas wajah. |
| `face_luminance_min_threshold` | integer | Ambang batas luminansi minimum. |
| `face_luminance_min_action` | action | Tindakan saat luminansi terlalu rendah. |
| `face_luminance_max_threshold` | integer | Ambang batas luminansi maksimum. |
| `face_luminance_max_action` | action | Tindakan saat luminansi terlalu tinggi. |
| `face_liveness_max_attempts` | integer | Total pengajuan liveness per sesi, `1` sampai `3`. Default `3` berarti satu percobaan awal ditambah dua percobaan ulang. Mengatur `1` tidak menonaktifkan coba lagi untuk kegagalan kualitas pengambilan: jika setiap peringatan pada percobaan bersifat lingkungan (`LOW_FACE_LUMINANCE`, `HIGH_FACE_LUMINANCE`, `LOW_FACE_QUALITY`, `HIGH_FACE_OCCLUSION`, `NO_FACE_DETECTED`), pengguna selalu mendapat percobaan kedua dengan umpan balik yang dapat ditindaklanjuti. |
| `external_capture_device_action` | action | Keputusan saat perangkat pengambilan eksternal terdeteksi. |
| `face_audio_recording_enabled` | boolean | Merekam mikrofon selama pengambilan swafoto, sehingga peninjau dapat mendengar sesi tersebut. Nonaktif secara default. |
| `face_search_enabled` | boolean | Menjalankan [Pencarian Wajah 1:N](https://docs.didit.me/id/core-technology/face-search/overview.md#menonaktifkan-pencarian-wajah-otomatis) otomatis pada swafoto: mencocokkannya dengan pengguna yang telah diverifikasi sebelumnya, daftar blokir dan daftar izin wajah, lalu menyimpan templat biometriknya untuk pencocokan berikutnya. Aktif secara default. `false` melewati pencarian, tidak menyimpan templat wajah untuk langkah ini, dan membuat tindakan wajah duplikat tidak memiliki apa pun untuk ditindak. |
| `face_liveness_uncertain_retry_enabled` | boolean | Hanya untuk liveness aktif pada SDK native. Jika aktif, pengambilan yang skor liveness-nya berada secara ketat di antara `face_liveness_score_decline_threshold` dan `face_liveness_score_review_threshold` tidak pernah diputuskan, apa pun keputusan yang dilampirkan mesin padanya: pengguna diberi tahu bahwa hasilnya tidak jelas dan diminta mengambil ulang, setiap kali, di luar anggaran `face_liveness_max_attempts` (yang tetap berlaku untuk pengambilan yang tidak dapat diberi skor oleh mesin). Nonaktif secara default; alur web mengabaikannya. |
| `face_liveness_duplicated_face_name_mismatch_action` | action | Keputusan saat wajah duplikat ditemukan dengan nama yang berbeda. |
| `face_liveness_duplicated_face_document_mismatch_action` | action | Keputusan saat wajah duplikat ditemukan dan dokumen identitas pengguna yang cocok menunjukkan tanggal lahir yang berbeda. Orang yang sama dengan dokumen yang berbeda atau yang diperbarui tidak ditandai. Default `REVIEW`. |
| `frame_injection_action` | action | Keputusan saat bingkai video yang disisipkan terdeteksi. |
| `screen_capture_action` | action | Keputusan saat swafoto berupa foto dari layar. |
| `virtual_camera_action` | action | Keputusan saat umpan kamera virtual terdeteksi. |
| `status_rules` | array | Aturan status kustom opsional. |

## Verifikasi Telepon

Nilai fitur: `PHONE_VERIFICATION`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `code_size` | integer | Ukuran OTP, `4` sampai `8`. |
| `phone_max_retries` | integer | Jumlah maksimum percobaan pengiriman ulang, `1` sampai `5`. |
| `phone_max_check_attempts` | integer | Jumlah maksimum percobaan pengecekan OTP, `1` sampai `5`. |
| `phone_verification_countries` | object | Kode negara ISO2 ke konfigurasi kanal. Contoh: `{ "US": { "sms": { "enabled": true } } }`. |
| `disposable_number_action` | action | Tindakan untuk nomor sekali pakai. |
| `voip_number_action` | action | Tindakan untuk nomor VoIP. |
| `duplicated_phone_number_action` | action | Tindakan untuk nomor telepon yang duplikat. |
| `high_risk_phone_action` | action | Tindakan saat penyedia pengiriman memblokir pengiriman OTP. Hanya `DECLINE` atau `REVIEW`; default `DECLINE`. Diterapkan hanya jika setiap blokir pada langkah memiliki `risk_factors` yang persis `["device_attribute"]`; faktor risiko lain, campuran apa pun yang menyertakannya, atau tanpa faktor risiko sama sekali akan menghasilkan penolakan, terlepas dari pengaturan ini. |
| `phone_shared_device_mode` | boolean | Mengizinkan mode verifikasi telepon pada perangkat bersama. |
| `phone_enrichment_enabled` | boolean | Mengaktifkan pengayaan intelijen telepon (risiko jenis saluran, indeks kepercayaan, operator, riwayat porting / SIM-swap, skor risiko penipuan). **Dikenakan biaya \$0.05 per verifikasi** di luar harga verifikasi telepon. |
| `phone_intelligence_score_action` | action | Tindakan saat skor risiko penipuan telepon sama dengan atau lebih tinggi dari `phone_intelligence_score_threshold`. |
| `phone_intelligence_score_threshold` | integer | Skor risiko penipuan (`0`–`100`, makin tinggi makin berisiko) yang memicu `phone_intelligence_score_action`. Default `80`. |
| `phone_type_risk_action` | action | Tindakan saat nomor ditandai sebagai jenis telepon berisiko tinggi. |
| `recent_port_action` | action | Tindakan saat nomor baru saja diport (sinyal SIM-swap / porting). |
| `low_phone_trust_action` | action | Tindakan saat indeks kepercayaan telepon sama dengan atau lebih rendah dari `phone_trust_index_threshold`. |
| `phone_trust_index_threshold` | integer | Indeks kepercayaan (`0`–`100`, makin rendah makin berisiko) yang jika sama dengan atau lebih rendah, menerapkan `low_phone_trust_action`. Default `30`. |
| `phone_social_enabled` | boolean | Mengaktifkan pemeriksaan jejak sosial: platform perpesanan, media sosial, e-commerce, dan profesional mana saja tempat nomor terverifikasi terdaftar. **Dikenakan biaya \$0.05 per verifikasi** di luar harga verifikasi telepon, terlepas dari `phone_enrichment_enabled`. |
| `phone_no_social_presence_action` | action | Tindakan saat pemeriksaan jejak sosial menemukan nomor tidak terdaftar di platform mana pun yang dicakupnya, yang merupakan sinyal identitas sintetis yang umum. Default `NO_ACTION`. |
| `cross_org_fraud_phone_action` | action | Keputusan saat nomor ini ditandai sebagai penipuan oleh organisasi lain dalam jaringan. |
| `status_rules` | array | Aturan status kustom opsional. |

Verifikasi Telepon dinonaktifkan hingga organisasi Anda melakukan isi saldo pertama.

> [!NOTE]
>
> Pengayaan intelijen telepon adalah add-on opsional. Saat `phone_enrichment_enabled` bernilai `true`, setiap verifikasi telepon yang selesai diperkaya dengan intelijen telepon dan **ditagih \$0.05 per permintaan** di luar biaya verifikasi telepon standar. Tindakan berbasis skor hanya berlaku setelah skor pengayaan tersedia; tindakan indeks kepercayaan, jenis telepon, dan porting diterapkan segera setelah pengayaan berjalan.
>
> Pemeriksaan jejak sosial adalah add-on kedua yang terpisah. Saat `phone_social_enabled` bernilai `true`, setiap verifikasi telepon yang selesai juga melaporkan platform online tempat nomor tersebut terdaftar - platform perpesanan, media sosial, e-commerce, dan layanan profesional - dan **ditagih \$0.05 per permintaan**. Fitur ini dapat diaktifkan dengan atau tanpa `phone_enrichment_enabled`: kedua add-on ditetapkan harga dan ditagih secara independen. Pencarian yang tidak menemukan nomor di platform mana pun yang dicakupnya adalah jawaban yang valid dan tetap ditagih, serta memicu `phone_no_social_presence_action`. Gunakan `phone.social_profiles_registered` (jumlah platform tempat nomor terdaftar) untuk bercabang berdasarkan hasil di dalam graf alur kerja.

## Verifikasi Email

Nilai fitur: `EMAIL_VERIFICATION`.

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `email_code_size` | integer | Ukuran OTP, `4` sampai `8`. |
| `email_max_retries` | integer | Jumlah maksimum percobaan pengiriman ulang, `1` sampai `5`. |
| `email_max_check_attempts` | integer | Jumlah maksimum percobaan pemeriksaan OTP, `1` sampai `5`. |
| `email_alphanumeric_code` | boolean | Menggunakan kode email alfanumerik. |
| `breached_email_action` | action | Tindakan untuk email yang mengalami kebocoran data. |
| `disposable_email_action` | action | Tindakan untuk email sekali pakai. |
| `duplicated_email_action` | action | Tindakan untuk email yang duplikat. |
| `only_corporate_emails_allowed` | boolean | Menolak alamat email non-korporat. |
| `email_enrichment_enabled` | boolean | Mengaktifkan pengayaan intelijen email (keterkiriman, reputasi domain, paparan kebocoran data, skor risiko penipuan). **Dikenakan biaya \$0.05 per verifikasi** di luar harga verifikasi email. |
| `email_intelligence_score_action` | action | Tindakan saat skor risiko penipuan email berada pada atau di atas `email_intelligence_score_threshold`. |
| `email_intelligence_score_threshold` | integer | Skor risiko penipuan (`0`–`100`, makin tinggi makin berisiko) yang memicu `email_intelligence_score_action`. Default `80`. |
| `recent_email_breach_action` | action | Tindakan saat email muncul dalam kebocoran data terkini yang diketahui. |
| `frequent_email_breach_action` | action | Tindakan saat email muncul di banyak kebocoran data yang diketahui. |
| `email_social_enabled` | boolean | Mengaktifkan pemeriksaan jejak sosial: platform email, media sosial, profesional, e-commerce, dan hiburan tempat alamat yang diverifikasi terdaftar. **Dikenakan biaya \$0.05 per verifikasi** di luar harga verifikasi email, terlepas dari `email_enrichment_enabled`. |
| `email_no_social_presence_action` | action | Tindakan saat pemeriksaan jejak sosial mendapati alamat tidak terdaftar di satu pun platform yang dicakupnya, yang merupakan sinyal umum identitas sintetis. Default `NO_ACTION`. |
| `cross_org_fraud_email_action` | action | Hasil saat alamat ini ditandai sebagai penipuan oleh organisasi lain dalam jaringan. |
| `status_rules` | array | Aturan status kustom opsional. |

> [!NOTE]
>
> Pengayaan intelijen email adalah tambahan opsional. Saat `email_enrichment_enabled` bernilai `true`, setiap verifikasi email yang selesai diperkaya dengan intelijen email dan **ditagihkan \$0.05 per permintaan** di samping biaya verifikasi email standar. Tindakan berbasis skor berlaku setelah skor pengayaan tersedia; tindakan kebocoran data berlaku segera setelah pengayaan dijalankan.
>
> Pemeriksaan jejak sosial adalah tambahan kedua yang terpisah. Saat `email_social_enabled` bernilai `true`, setiap verifikasi email yang selesai juga melaporkan platform daring tempat alamat tersebut terdaftar, yaitu layanan email, media sosial, layanan profesional, e-commerce, dan hiburan, dan **ditagihkan \$0.05 per permintaan**. Fitur ini dapat diaktifkan dengan atau tanpa `email_enrichment_enabled`, karena harga dan penagihan kedua tambahan ini dilakukan secara terpisah. Pencarian yang tidak menemukan alamat di satu pun platform yang dicakupnya tetap merupakan jawaban yang valid dan dapat ditagihkan, dan akan memicu `email_no_social_presence_action`. Gunakan `email.social_profiles_registered` (jumlah platform tempat alamat terdaftar) untuk bercabang berdasarkan hasil di graf alur kerja.

## Validasi Database

Nilai fitur: `DATABASE_VALIDATION`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `database_validation_countries` | object | Kode negara ISO3 ke `{ "services": ["service_id"] }`. Gunakan ID layanan dari katalog Validasi Database. |
| `database_validation_partial_match_action` | action | Tindakan saat validasi database mengembalikan kecocokan sebagian. |
| `database_validation_no_match_action` | action | Tindakan saat validasi database tidak mengembalikan kecocokan. |
| `database_validation_not_applicable_action` | action | Tindakan saat validasi database tidak dapat dijalankan karena dokumen tidak memuat pengenal yang dibutuhkan layanan yang dikonfigurasi (misalnya paspor tanpa nomor identitas nasional). Default-nya `NO_ACTION`. |
| `database_validation_field_sources` | object | Tempat untuk membaca input database yang tidak dapat diisi oleh langkah mana pun sebelumnya dalam graf. `source` menyebutkan produsernya dan `key` menyebutkan nilai di dalamnya: kunci kolom Document AI untuk `document_ai`, ID node kuesioner untuk `questionnaire`, dan `expected_details.<field>` atau `metadata.<key>` untuk `expected_data`. Pencocokan kunci yang persis dengan langkah upstream diselesaikan secara otomatis dan sengaja tidak disimpan, sehingga mengganti nama kolom Document AI tidak membuat pemetaan usang tersimpan di konfigurasi. Entri yang tidak valid ditolak dengan `400` yang menyebutkan kolom input-nya. Bentuk: `{"<db_validation_input_field>": {"source": "document_ai"\|"questionnaire"\|"expected_data", "key": "<docai field key>\|<questionnaire node id>\|expected_details.<field>\|metadata.<key>"}}`. |
| `status_rules` | array | Aturan status kustom opsional. |

Contoh:

```json theme={null}
{
  "feature": "DATABASE_VALIDATION",
  "config": {
    "database_validation_countries": {
      "BRA": {
        "services": ["SERVICE_ID_FROM_CATALOG"]
      }
    },
    "database_validation_field_sources": {
      "tax_id": {
        "source": "expected_data",
        "key": "expected_details.document_number"
      }
    },
    "database_validation_no_match_action": "REVIEW",
    "database_validation_partial_match_action": "REVIEW"
  }
}
```

> [!WARNING]
>
> `database_validation_countries` adalah yang membuat langkah ini benar-benar berfungsi. Fitur `DATABASE_VALIDATION`
> yang disimpan tanpa kolom ini tetap diterima, tetapi tidak menjalankan pemeriksaan apa pun, jadi selalu kirim setidaknya satu
> negara dengan setidaknya satu ID layanan.

ID layanan yang tidak dapat dijalankan oleh langkah ini ditolak dengan `400` yang menyebutkan ID tersebut dan alasannya, dan tidak ada yang disimpan.
Ini mencakup ID yang tidak ada di katalog, ID yang termasuk negara lain, layanan yang belum tersedia, dan layanan yang hanya tersedia melalui endpoint mandiri [`POST /v3/database-validation/`](https://docs.didit.me/id/core-technology/database-validation/overview).
Layanan yang inputnya tidak disediakan oleh langkah mana pun sebelumnya ditolak dengan cara yang sama, dengan daftar input yang hilang.
Layanan yang sudah ada di alur kerja tersimpan tetapi tidak lagi dapat dijalankan akan dihapus saat Anda menyimpannya kembali.

Misalnya, alur kerja Argentina ini membaca nomor DNI dan jenis kelamin dari Verifikasi Identitas lalu memeriksanya terhadap RENAPER tanpa swafoto:

```json theme={null}
{
  "workflow_label": "Argentina DNI check",
  "features": [
    {"feature": "OCR"},
    {
      "feature": "DATABASE_VALIDATION",
      "config": {"database_validation_countries": {"ARG": {"services": ["arg_renaper_data"]}}}
    }
  ]
}
```

Gunakan `arg_renaper` sebagai gantinya, setelah langkah `LIVENESS`, untuk juga mencocokkan swafoto dengan foto yang dimiliki RENAPER.
Lihat [RENAPER](https://docs.didit.me/id/api-reference/database-validation/argentina/renaper.md) untuk skor Pencocokan Wajah dan ambang batasnya.

## Verifikasi Bank

Nilai fitur: `BANK_VERIFICATION`.

Pengguna memverifikasi rekening bank, dan pemilik rekening yang dilaporkan bank dibandingkan dengan identitas yang sudah ditetapkan oleh langkah sebelumnya dalam alur kerja. Pengguna memilih salah satu dari dua metode: masuk ke bank mereka (`open_banking`), atau pemeriksaan rekening (`account_lookup`), yaitu mereka memasukkan detail rekening dan bank mengonfirmasi nama pemilik rekening tersebut. `bank_method_order` dan `methods` di setiap negara menentukan metode apa saja yang ditawarkan suatu negara dan mana yang tampil pertama; lihat [Metode verifikasi bank](https://docs.didit.me/id/core-technology/bank-verification/verification-methods.md). Langkah ini menghasilkan bukti berupa skor kecocokan nama pemilik, perbandingan yang menghasilkan skor tersebut, dan kode alasan. Kunci `bank_*_action` mengubah bukti itu menjadi status.

Dua hal menentukan apakah node melakukan sesuatu sama sekali. `bank_countries` adalah daftar izin, sehingga map kosong tidak menawarkan bank apa pun dan tidak menjalankan pemeriksaan apa pun. Nama pemilik rekening perlu dibandingkan dengan sesuatu: tambahkan langkah `OCR`, `DATABASE_VALIDATION` atau `QUESTIONNAIRE` sebelum node ini, kirim `expected_details` saat membuat sesi, atau petakan kolom sendiri dengan `bank_field_sources`. Tanpa salah satu dari itu, kepemilikan hanya bisa bernilai `unknown`, dan `bank_reference_identity_missing_action` yang menentukan hasilnya.

> [!NOTE]
>
> Verifikasi Bank masih dalam tahap peluncuran, jadi node `BANK_VERIFICATION` hanya diterima pada akun yang telah mengaktifkannya. Di akun lain, penyimpanan ditolak dan pesan penolakannya menyebutkan hal tersebut. Rute yang menjalankan langkah ini juga tidak diatur di sini: pasangan `provider_key` dan `fallback_to_native` diatur untuk Anda oleh [Marketplace](https://docs.didit.me/id/console/marketplace.md) di konsol.

### Menghubungkan rekening

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `bank_countries` | object | Negara mana saja tempat pengguna boleh menghubungkan rekening bank. Berupa daftar izin: map kosong berarti node tidak menawarkan apa pun dan tidak menjalankan apa pun. `institutions` mempersempit pemilih ke ID institusi tertentu, sedangkan `"all"` menawarkan setiap bank yang mendukung verifikasi identitas di negara tersebut. Negara yang tidak dilayani rute mana pun dari node tetap disimpan: negara itu hanya menawarkan cadangannya dan opsi Lanjutkan tanpa bank Anda, lihat [Saat pengguna tidak dapat memverifikasi](https://docs.didit.me/id/core-technology/bank-verification/fallbacks.md). Kode yang tidak menyebutkan negara ditolak saat disimpan. `methods` menetapkan metode apa dari masuk ke bank (`open_banking`) dan pemeriksaan rekening (`account_lookup`) yang ditawarkan negara tersebut, dan dalam urutan apa, menggantikan `bank_method_order`: pengguna mulai dari metode pertama dan ditawari metode kedua sebagai cadangan. Negara yang aktif dan `methods`-nya menyebut metode yang tidak dilayani rute mana pun di negara itu ditolak saat disimpan, begitu pula negara yang dilayani sebuah rute tetapi `methods`-nya tidak menyisakan satu metode pun. Bentuk: `{"<ISO3>": {"enabled": true\|false, "institutions": ["<institution_id>", ...]\|"all", "methods"?: ["open_banking"\|"account_lookup", ...]}}`. |
| `bank_method_order` | string\[] | Dua metode yang ditawarkan langkah ini, dan urutannya, di setiap negara yang tidak menetapkan `methods` sendiri: `open_banking` (masuk ke bank: pengguna masuk di bank mereka, dan hanya metode ini yang membaca saldo, transaksi, dan pendapatan) dan `account_lookup` (pemeriksaan rekening: tanpa masuk, hanya kepemilikan). Di setiap negara, pengguna mulai dari metode pertama yang dilayani sebuah rute di sana dan ditawari metode lainnya sebagai cadangan; metode yang tidak dilayani rute mana pun di suatu negara dilewati di negara tersebut. Minimal satu metode. Jika permintaan penyimpanan tidak mengirim metode apa pun, permintaan tersebut akan menggunakan `["open_banking", "account_lookup"]`, kecuali jika mengirim `bank_open_banking_enabled` atau `bank_account_lookup_enabled`, yang kemudian menetapkannya. |
| `bank_scopes` | object | Hal-hal yang diminta untuk dibagikan dengan persetujuan pengguna. `ownership` adalah hal yang diverifikasi produk dan tidak dapat dimatikan. `identifiers` menampilkan IBAN atau nomor rekening; `balances`, `transactions` dan `income` membaca data keuangan riil, masing-masing ditagihkan secara terpisah, dan ditolak saat disimpan kecuali aplikasi Anda memiliki hak akses data keuangan. Hanya masuk ke bank yang membaca data; negara yang menawarkan pemeriksaan rekening tidak ditolak, dan pengguna yang memverifikasi lewat pemeriksaan rekening lolos tanpa data tersebut, yang dicantumkan hasilnya di `financial_data.not_collected`. Cakupan yang nonaktif tidak pernah diminta, jadi bank tidak pernah menampilkannya di layar persetujuannya. Nilai default-nya hanya `ownership`. Bentuk: `{"ownership": true, "identifiers": true\|false, "balances": true\|false, "transactions": true\|false, "income": true\|false}`. |
| `bank_eligible_account_types` | string\[] | Jenis rekening yang boleh dipilih pengguna: `checking`, `current`, `savings`, `business` atau `other`. Kartu kredit, pinjaman dan rekening investasi tidak pernah memenuhi syarat karena tidak membuktikan kepemilikan rekening pembayaran. Nilai default-nya adalah current dan checking. |
| `bank_account_selection` | string | `user` memungkinkan pengguna memilih rekening terhubung mana yang akan diverifikasi; `auto` memilih rekening pertama yang memenuhi syarat. |
| `bank_require_oauth_only` | boolean | Hanya menawarkan institusi yang dapat dijangkau melalui OAuth atau aplikasi-ke-aplikasi, tidak pernah layar lama untuk memasukkan kredensial. Di pasar yang sudah menjadikan OAuth satu-satunya rute melalui open banking, pengaturan ini tidak mengubah apa pun. |
| `bank_max_attempts` | integer | Berapa kali pengguna boleh mencoba masuk ke bank, dari `1` sampai `5`; setoran mikro atau unggahan laporan mutasi juga menghabiskan satu percobaan. Pemeriksaan rekening memiliki `bank_account_check_max_attempts` sendiri. Setelah setiap cara untuk memverifikasi pengguna yang masih ditawarkan, termasuk unggahan laporan mutasi, menghabiskan percobaannya tanpa koneksi yang berhasil, `bank_attempts_exhausted_action` yang menentukan hasilnya. |
| `bank_connection_timeout_minutes` | integer | Berapa lama koneksi yang sudah dimulai tetap terbuka sebelum percobaan ditinggalkan, dari `5` sampai `60` menit. |
| `bank_allow_skip` | boolean | Sudah digantikan oleh `bank_continue_without_bank`: sekarang pengguna selalu dapat melanjutkan tanpa bank. Untuk satu rilis, nilai ini dibaca dari penyimpanan yang tidak mengirim `bank_continue_without_bank`: `true` menetapkan `from_start`, nilai lainnya menetapkan `when_needed`. Setiap penyimpanan menulis nilai ini kembali: `true` untuk `from_start`, `false` untuk `when_needed`. |

### Saat pengguna tidak dapat memverifikasi

Pengguna selalu dapat melanjutkan tanpa bank, dan langkah ini tidak pernah membuat mereka terhenti. Lihat [Saat orang tidak dapat memverifikasi bank mereka](https://docs.didit.me/id/core-technology/bank-verification/fallbacks.md).

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `bank_continue_without_bank` | string | Saat langkah menampilkan **Continue without your bank**. `when_needed`, nilai default, menampilkannya setelah tidak ada metode yang berhasil untuk negara atau bank pengguna, ketika bank mereka tidak dapat dihubungi dan tidak ada metode lain yang dapat memverifikasi mereka, misalnya karena pemeriksaan rekening juga tidak dapat menghubungi bank, atau ketika mereka menyatakan tidak memiliki layanan perbankan daring. `from_start` juga menampilkannya di layar pertama. Opsi ini tidak dapat dimatikan. Penyimpanan yang tidak mengirim key ini maupun `bank_allow_skip` akan menggunakan `when_needed`. |
| `bank_statement_standalone_enabled` | boolean | Bersama `bank_statement_enabled`, tawarkan juga unggah rekening koran saat tidak ada percobaan bank, di negara mana pun, termasuk negara yang tidak dilayani oleh rute login bank maupun pemeriksaan rekening. Fitur ini kemudian ditagih tersendiri sebagai `bank_statement_upload`, sebesar USD 0.20 per rekening koran yang dievaluasi sebelum tarif kontrak atau harga khusus Anda: lihat [Harga](https://docs.didit.me/id/core-technology/bank-verification/fallbacks.md#harga). Sesi sandbox dapat menguji fitur ini tanpa penagihan. Aktif secara default. |

Yang terjadi pada sesi ketika pengguna melanjutkan ditentukan oleh `bank_unsupported_action`, `bank_attempts_exhausted_action` atau `bank_skipped_action`, bergantung pada alasan pengguna melanjutkan, kecuali percobaan yang dievaluasi sebelumnya sudah menetapkan langkah tersebut: lihat [Tindakan keputusan](#tindakan-keputusan).

### Membandingkan pemegang rekening

| Kolom konfigurasi | Jenis | Deskripsi |
| - | - | - |
| `bank_reference_identity` | string | Langkah sebelumnya yang menyediakan identitas yang dibandingkan dengan pemegang rekening: `kyc` (Verifikasi Identitas), `database_validation`, `expected_details` (data yang Anda kirim saat membuat sesi), `questionnaire`, atau `auto` untuk menggunakan langkah mana pun yang dihasilkan oleh alur kerja. Langkah yang benar-benar menyediakan identitas tersebut dikembalikan pada hasil sebagai `reference_identity_source`. |
| `bank_field_sources` | object | Lokasi membaca kolom identitas referensi ketika tidak ada langkah sebelumnya dalam graf yang dapat mengisinya. KUNCI pada peta adalah salah satu dari `full_name`, `first_name`, `last_name`, `address`; `source` mengidentifikasi penghasil dan `key` mengidentifikasi nilai di dalamnya: kunci kolom Document AI untuk `document_ai`, ID node kuesioner untuk `questionnaire`, dan `expected_details.<field>` atau `metadata.<key>` untuk `expected_data`. Nilai di bawah `expected_details.` hanya boleh menyebut kolom yang benar-benar dibawa oleh payload pembuatan sesi: `address`, `country`, `date_of_birth`, `first_name`, `gender`, `id_country`, `identification_number`, `ip_address`, `last_name`, `nationality` atau `poa_country`. Entri yang tidak valid ditolak saat disimpan, bukan diabaikan. Bentuk: `{"full_name"\|"first_name"\|"last_name"\|"address": {"source": "document_ai"\|"questionnaire"\|"expected_data", "key": "<docai field key>\|<questionnaire node id>\|expected_details.<field>\|metadata.<key>"}}`. |
| `bank_name_match_threshold` | integer | Jika skornya sama dengan atau lebih tinggi dari skor ini, nama pemegang rekening dianggap cocok. `50` hingga `100`, default `85`. |
| `bank_partial_match_floor` | integer | Di bawah skor ini, nama pemegang rekening dianggap tidak cocok. `0` hingga `99`, default `70`. Rentang di antara batas bawah dan ambang batas adalah kecocokan parsial, sehingga batas bawah harus benar-benar lebih kecil daripada ambang batas, jika tidak penyimpanan ditolak. Nilai `null` yang eksplisit berarti "gunakan default" di sini, itulah sebabnya ambang batas `50` tanpa batas bawah ditolak: nilai itu diperiksa sebagai `50` terhadap batas bawah default `70`. |
| `bank_require_address_match` | boolean | Juga mewajibkan alamat pemegang rekening cocok. Nama yang mencapai ambang batas, tetapi alamatnya mendapat skor di bawah ambang batas, turun menjadi kecocokan parsial. Institusi yang tidak mengembalikan alamat membebaskan persyaratan ini; sesi yang tidak memiliki alamat sendiri untuk dibandingkan tidak dibebaskan, dan berakhir sebagai kecocokan parsial. Nonaktif secara default. |
| `bank_use_provider_score` | boolean | Juga baca skor nama pemegang rekening milik institusi, dan biarkan skor itu menentukan ketika lebih tinggi daripada skor Didit, atau ketika Didit tidak memiliki nama pemegang rekening untuk dinilai. Hasil yang diputuskan dengan cara itu melaporkan `provider_only` sebagai metode pencocokannya, dan koneksi yang tidak mengembalikan skor tersebut mencatat peringatan `provider_score_unavailable`. Aktif secara default. |
| `bank_show_match_result_to_user` | boolean | Tampilkan hasil kepemilikan kepada pengguna di dalam alur verifikasi. Jika dimatikan, hasil hanya dicatat pada sesi dan tidak pernah ditampilkan kepada mereka. |

### Pemeriksaan rekening

Kunci-kunci ini hanya berlaku untuk pemeriksaan rekening. Login bank tetap menggunakan kecocokan dekat dan `bank_max_attempts`-nya sendiri.

| Kolom konfigurasi | Jenis | Deskripsi |
| - | - | - |
| `bank_account_check_accept_close_match` | boolean | Aktif (default), nama yang dinilai bank di antara `bank_partial_match_floor` dan `bank_name_match_threshold` dianggap kecocokan dekat: pengguna mengonfirmasi nama yang dimiliki bank ketika `bank_suggest_holder_name` aktif, dan keputusan ditentukan oleh `bank_partial_match_action`. Jika nonaktif, kecocokan dekat itu dianggap tidak cocok (`OWNER_NAME_MISMATCH`, diputuskan oleh `bank_no_match_action`) dan menghabiskan satu percobaan. |
| `bank_account_check_max_attempts` | integer | Berapa kali pengguna dapat melakukan pemeriksaan rekening, `1` hingga `5`, `3` jika tidak diatur: berapa kali mereka dapat mengetik detail rekening untuk pemeriksaan yang dijawab oleh bank. Hitungan ini terpisah dari `bank_max_attempts`. Pemeriksaan yang ditolak berdasarkan detail yang diketik (IBAN tidak valid) atau yang tidak dapat dijawab oleh bank tidak menghabiskan percobaan apa pun. |

### Data keuangan

`bank_expected_currencies` berfungsi dengan persetujuan `ownership` default saja. Tiga kunci lainnya membaca data keuangan sungguhan, sehingga masing-masing memerlukan cakupan persetujuan yang sesuai di `bank_scopes`, dan penyimpanan ditolak tanpanya.

| Kolom konfigurasi | Jenis | Deskripsi |
| - | - | - |
| `bank_expected_currencies` | string\[] | Mata uang ISO 4217 yang diharapkan digunakan oleh rekening. Kosong berarti apa pun; ketidaksesuaian dilaporkan melalui `bank_currency_mismatch_action`. |
| `bank_min_balance` | number | Saldo tersedia minimum, dalam mata uang rekening itu sendiri. Di bawahnya, `bank_low_balance_action` dipicu. Memerlukan cakupan `balances`. `0` adalah batas nyata dan tidak sama dengan membiarkan kunci ini tidak diisi: rekening dengan saldo negatif memicu tindakan tersebut. Tindakan itu default ke `NO_ACTION`, yang membiarkan keputusan tidak berubah, sehingga menolak rekening dengan saldo negatif juga memerlukan `bank_low_balance_action: "DECLINE"`. |
| `bank_transactions_history_days` | integer | Seberapa jauh ke belakang riwayat transaksi dibaca, `30` sampai `365` hari. Defaultnya `90`. Memerlukan scope `transactions`. |
| `bank_refresh_enabled` | boolean | Mengambil ulang data keuangan akun setelah langkah sudah diputuskan, selama persetujuan bank masih berlaku. Memerlukan setidaknya salah satu scope `balances`, `transactions` atau `income`. Persetujuan yang berakhir setelahnya diatur oleh `bank_consent_expired_action`. |

### Yang disimpan

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `bank_store_full_identifiers` | boolean | Menyimpan identifier akun dalam bentuk tidak disamarkan, bukan dalam bentuk disamarkan. Memerlukan scope `identifiers`. Bahkan dalam kondisi ini, bentuk yang tidak disamarkan hanya dikembalikan ke pemanggil yang memiliki izin baca verifikasi bank. |
| `bank_store_raw_owner_data` | boolean | Menyimpan detail pemegang rekening yang dikembalikan oleh institusi bersama bukti kepemilikan. Jika nonaktif, hanya perbandingannya yang disimpan: skor, metode pencocokan, dan kode alasan. |

### Tindakan keputusan

Setiap kunci di sini menerima `DECLINE`, `REVIEW` atau `NO_ACTION` kecuali ditandai sebagai terbatas, dan kembali ke default di bawah saat Anda menghilangkannya atau mengirim `null`. Tidak ada yang bukan bukti kepemilikan positif yang disetujui secara default, dan hanya bukti yang terbukti menentang pengguna yang menghasilkan penolakan.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `bank_no_match_action` | tindakan terbatas | Keputusan saat pemilik rekening terbukti bukan orang yang diverifikasi, yaitu skor nama terbaik berada di bawah `bank_partial_match_floor`. Gunakan `DECLINE` atau `REVIEW`. Defaultnya `DECLINE`. |
| `bank_partial_match_action` | tindakan | Keputusan saat nama pemegang rekening berada di antara `bank_partial_match_floor` dan `bank_name_match_threshold`. Defaultnya `REVIEW`, dan tidak pernah menyetujui secara default. |
| `bank_not_verifiable_action` | tindakan | Keputusan saat institusi berhasil terhubung tetapi tidak mengembalikan identitas pemegang untuk dibandingkan. Defaultnya `REVIEW`. |
| `bank_unknown_action` | tindakan | Keputusan saat bukti tidak dapat diambil setelah percobaan ulang, yaitu kegagalan sementara. Defaultnya `REVIEW`. |
| `bank_reference_identity_missing_action` | tindakan | Keputusan saat tidak ada langkah sebelumnya yang menghasilkan identitas untuk membandingkan pemegang, sehingga kepemilikan hanya dapat bernilai `unknown`. Defaultnya `REVIEW`. |
| `bank_joint_account_action` | tindakan | Keputusan saat rekening memiliki lebih dari satu pemegang. Defaultnya `NO_ACTION`. |
| `bank_business_account_action` | tindakan | Keputusan saat institusi mengklasifikasikan pemegang sebagai bisnis, bukan orang. Defaultnya `REVIEW` pada alur kerja individu, dan `NO_ACTION` pada alur kerja bisnis (KYB) ketika sesi memang mengharapkan pemegang bisnis. |
| `bank_unsupported_action` | tindakan | Keputusan saat pengguna melanjutkan tanpa bank karena tidak ada metode yang dapat memverifikasi negara atau bank mereka: tidak ada rute masuk bank atau pemeriksaan rekening yang melayani negara tersebut, atau bank yang mereka pilih tidak dapat digunakan pada langkah ini. Hasilnya kemudian memiliki `continued_without_bank` bernilai true dan `NOT_COVERED` dalam kode alasannya. Defaultnya `REVIEW`. |
| `bank_skipped_action` | tindakan terbatas | Keputusan saat pengguna memilih Lanjutkan tanpa bank Anda padahal ada cara untuk memverifikasi. Hasilnya kemudian memiliki `continued_without_bank` bernilai true dan `SKIPPED` dalam kode alasannya. Gunakan `DECLINE` atau `REVIEW`. Defaultnya `REVIEW`. |
| `bank_attempts_exhausted_action` | tindakan terbatas | Keputusan saat pengguna telah menghabiskan percobaan dari setiap cara verifikasi yang masih ditawarkan kepadanya, termasuk unggahan rekening koran (`bank_max_attempts`, dan `bank_account_check_max_attempts` jika negara tersebut menawarkan pemeriksaan rekening), tanpa koneksi yang berhasil, juga saat mereka kemudian melanjutkan tanpa bank. Gunakan `DECLINE` atau `REVIEW`. Defaultnya `DECLINE`. |
| `bank_consent_expired_action` | tindakan | Keputusan saat persetujuan bank berakhir setelah langkah sudah diputuskan. Hanya bermakna dengan `bank_refresh_enabled`. Defaultnya `NO_ACTION`. |
| `bank_currency_mismatch_action` | tindakan | Keputusan saat mata uang rekening tidak termasuk dalam `bank_expected_currencies`. Defaultnya `NO_ACTION`. |
| `bank_country_mismatch_action` | tindakan | Keputusan saat negara institusi berbeda dengan negara yang diharapkan atau negara dokumen. Defaultnya `NO_ACTION`. |
| `bank_low_balance_action` | tindakan | Keputusan saat saldo yang tersedia berada di bawah `bank_min_balance`. Memerlukan scope `balances`. Defaultnya `NO_ACTION`. |
| `status_rules` | array | Aturan status kustom opsional. |

### Kontrol tambahan

Kunci-kunci ini bersifat opsional. Setiap kunci tindakan menerima `DECLINE`, `REVIEW` atau `NO_ACTION`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `bank_abandoned_action` | tindakan | Keputusan saat langkah berakhir tanpa kecocokan karena orang tersebut meninggalkan proses di bank mereka dan tidak pernah kembali (percobaan mengalami batas waktu). |
| `bank_account_age_action` | tindakan | Keputusan saat rekening lebih baru daripada `bank_account_age_days`, yang merupakan pola mule yang umum. |
| `bank_account_age_days` | integer | Rekening yang riwayatnya dimulai kurang dari jumlah hari ini dianggap baru, 1 sampai 365, dengan default 30. Dibaca dari riwayat transaksi, sehingga hanya dengan scope `transactions`. |
| `bank_account_lookup_enabled` | boolean | Sudah tidak digunakan: gunakan `bank_method_order` dan `bank_countries.<ISO3>.methods`. Dibaca selama satu rilis dari konfigurasi yang disimpan tanpa mengirim `bank_method_order`: dengan `bank_open_banking_enabled`, kunci ini menetapkan urutan, yaitu pemeriksaan rekening setelah masuk bank jika aktif, dan dihilangkan jika nonaktif atau tidak diatur. Setiap penyimpanan menuliskannya kembali untuk menunjukkan apakah ada negara yang menawarkan pemeriksaan rekening. |
| `bank_account_type_action` | tindakan | Keputusan saat rekening yang diverifikasi adalah rekening tabungan. |
| `bank_address_match_threshold` | integer | Pada skor ini atau lebih tinggi, alamat pemegang dianggap cocok, 50 sampai 100, dengan default 70. Hanya dibaca dengan `bank_require_address_match`. |
| `bank_address_mismatch_action` | tindakan | Keputusan saat alamat pemegang berbeda, yang menjadikan hasilnya kecocokan yang mendekati. Hanya dengan `bank_require_address_match`. |
| `bank_auto_add_countries` | boolean | Menawarkan rute untuk setiap negara yang dapat dilayani node ini, termasuk negara yang ditambahkan setelah node disimpan, kecuali negara yang dinonaktifkan oleh `bank_countries`. Nonaktif saat kunci tidak ada, sehingga cakupan node yang sudah ada tidak pernah meluas dengan sendirinya. |
| `bank_cash_flow_action` | tindakan | Keputusan saat uang masuk lalu langsung keluar lagi, atau banyak transfer kecil masuk (arus kas pass-through). Membutuhkan scope `transactions`. |
| `bank_dob_match_enabled` | boolean | Bandingkan tanggal lahir pemegang rekening, jika bank membagikannya, dengan tanggal lahir yang telah diverifikasi. Ketidakcocokan tidak pernah mengubah hasil kepemilikan: ia memicu `bank_dob_mismatch_action`. Aktif secara default. |
| `bank_dob_match_threshold` | integer | Pada atau di atas skor ini tanggal lahir dianggap cocok, dari 50 hingga 100, dengan default 70. Tanggal hanya sama atau tidak sama, sehingga skornya 100 atau 0. |
| `bank_dob_mismatch_action` | tindakan | Keputusan saat tanggal lahir pemegang rekening berbeda. Hanya berlaku dengan `bank_dob_match_enabled`. |
| `bank_email_match_enabled` | boolean | Bandingkan email yang tercatat di bank dengan email terverifikasi sesi. Ketidakcocokan memicu `bank_email_mismatch_action`. Nonaktif secara default. |
| `bank_email_match_threshold` | integer | Pada atau di atas skor ini email dianggap cocok, dari 50 hingga 100, dengan default 70. |
| `bank_email_mismatch_action` | tindakan | Keputusan saat email pemegang rekening berbeda. Hanya berlaku dengan `bank_email_match_enabled`. |
| `bank_evidence_retention_days` | integer | Hapus bukti bank sejumlah hari ini setelah keputusan: 30, 90, 365 atau 1825. Null menyimpannya bersama sesi. Yang dihapus: detail pemegang rekening, identitas pembanding, pengenal rekening, data keuangan, dan rekening koran yang diunggah; koneksi yang masih aktif dicabut. Keputusan, skor, dan kode alasan tetap disimpan. Menghapus sesi menghapus semuanya, mana pun yang lebih dulu terjadi. |
| `bank_fallback_used_action` | tindakan | Keputusan saat rekening diverifikasi dengan setoran mikro atau unggahan rekening koran. |
| `bank_match_any_holder` | boolean | Rekening bersama atau rekening kepemilikan bersama dianggap cocok saat SALAH SATU pemegang yang tercantum cocok dengan orang tersebut. Nonaktif: hanya pemegang pertama yang dicantumkan bank yang dapat cocok. Aktif secara default. |
| `bank_microdeposits_enabled` | boolean | Tawarkan setoran mikro sebagai alternatif: dua setoran kecil masuk ke rekening, lalu orang tersebut memasukkan nominalnya. Hanya ditawarkan di negara yang rutenya dapat mengirimkannya, setelah percobaan verifikasi bank berbayar dalam sesi yang sama. Termasuk tanpa biaya tambahan; pelanggan membayar harga rute sekali. Sesi sandbox dapat mengujinya tanpa penagihan. Pemegang rekening adalah nama yang diverifikasi oleh sesi, yang dinyatakan orang tersebut sebagai nama pemegang rekening, sehingga rekening yang terverifikasi mencatat peringatan `holder_declared`. Aktif secara default. |
| `bank_mule_score_action` | tindakan | Keputusan saat skor mule berada pada atau di atas `bank_mule_score_threshold`. |
| `bank_mule_score_threshold` | integer | Pada atau di atas skor mule ini, dari 0 hingga 100, `bank_mule_score_action` dipicu; default-nya 70. Skor menggabungkan rekening baru, arus kas pass-through, saldo yang terkuras, dan banyak transfer kecil masuk, yang dibaca dari riwayat transaksi (scope `transactions`). |
| `bank_open_banking_enabled` | boolean | Tidak digunakan lagi: gunakan `bank_method_order` dan `bank_countries.<ISO3>.methods`. Untuk satu rilis, nilai ini dibaca dari penyimpanan yang tidak mengirim `bank_method_order`: dengan `bank_account_lookup_enabled`, nilai ini menetapkan urutan, yaitu masuk bank saat aktif atau tidak diatur. Setiap penyimpanan menuliskannya kembali sebagai penanda apakah ada negara yang menawarkan akses masuk ke bank. |
| `bank_phone_match_enabled` | boolean | Bandingkan nomor telepon yang tercatat di bank dengan nomor telepon yang diverifikasi dalam sesi. Ketidakcocokan memicu `bank_phone_mismatch_action`. Nonaktif secara default. |
| `bank_phone_match_threshold` | integer | Pada atau di atas skor ini telepon dianggap cocok, dari 50 hingga 100, dengan default 70. |
| `bank_phone_mismatch_action` | tindakan | Keputusan saat nomor telepon pemegang rekening berbeda. Hanya berlaku dengan `bank_phone_match_enabled`. |
| `bank_popular_mode` | string | `auto` (default) mengurutkan bank populer berdasarkan yang paling sering dihubungkan oleh orang di negara tersebut; `manual` sebagai gantinya menampilkan `popular_institutions` setiap negara dari `bank_countries`, sesuai urutannya. |
| `bank_statement_document_checks_action` | tindakan | Keputusan saat rekening koran yang diunggah memuat bukti pengeditan atau manipulasi. Default-nya `REVIEW`. |
| `bank_statement_enabled` | boolean | Tawarkan unggahan rekening koran sebagai alternatif: rekening koran dari 3 bulan terakhir, diperiksa untuk mendeteksi manipulasi atau perubahan, yang nama pemegangnya dicocokkan seperti pada verifikasi rekening bank. Termasuk tanpa biaya tambahan setelah percobaan verifikasi bank berbayar dalam sesi yang sama. Dengan `bank_statement_standalone_enabled`, opsi ini juga ditawarkan tanpa percobaan bank sebelumnya, di negara mana pun, dan kemudian ditagih tersendiri. Sesi sandbox dapat mengujinya tanpa penagihan. Nonaktif secara default. |
| `bank_suggest_holder_name` | boolean | Saat terdapat kecocokan yang mendekati, tampilkan kepada orang tersebut nama yang digunakan bank untuk rekening tersebut, lalu minta mereka mengonfirmasi bahwa itu miliknya atau menghubungkan rekening lain. Jawaban mereka dicatat sebagai `holder_confirmation`; konfirmasi mengakhiri langkah pada `bank_partial_match_action`. Aktif secara default. |
| `fallback_to_native` | boolean | Apakah koneksi marketplace yang tidak dapat dibangun dialihkan ke rute native Didit. Nonaktif secara default: fallback diam-diam akan menghabiskan saldo Didit Anda untuk sesi yang Anda harapkan berjalan dengan kontrak penyedia Anda sendiri. Koneksi fallback dicatat sebagai `credential_source = native` dan ditagih dengan harga native. |
| `provider_key` | string | Rute mana yang menjalankan langkah. Kosong (default) berarti Verifikasi Bank native Didit, produk yang tidak bergantung pada penyedia, yang diarahkan Didit ke vendor open banking regional yang melayani negara dan institusi pengguna, dengan kontrak serta penagihan Didit. Sebuah nilai menamai penyedia MARKETPLACE yang kredensialnya telah dihubungkan oleh aplikasi ini: sesi kemudian berjalan, ditagih, dan dicabut di akun penyedia Anda, dan Didit hanya membebankan biaya platform marketplace. Penyedia yang belum terhubung ditolak saat disimpan. |

Contoh objek `config`, untuk akun yang Verifikasi Bank-nya aktif dan rute yang Anda pilih mencakup negara yang Anda cantumkan:

```json theme={null}
{
  "bank_method_order": ["open_banking", "account_lookup"],
  "bank_countries": {
    "ESP": { "enabled": true, "institutions": "all" }
  },
  "bank_scopes": { "ownership": true },
  "bank_eligible_account_types": ["checking", "current"],
  "bank_name_match_threshold": 85,
  "bank_partial_match_floor": 70,
  "bank_partial_match_action": "REVIEW",
  "bank_no_match_action": "DECLINE"
}
```

> [!WARNING]
>
> `bank_countries` adalah yang membuat langkah ini berfungsi, dan nilainya diperiksa terhadap rute tempat node berjalan, bukan terhadap daftar global. Negara yang rutenya tidak dapat memastikan kepemilikan rekening akan ditolak saat disimpan dan disebutkan dalam pesan error, jadi baca error tersebut alih-alih berasumsi bahwa negara itu diterima dan akan dilewati saat dijalankan.

## AML

Nilai fitur: `AML`.

Untuk skrining orang KYC, gunakan kolom berikut:

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `is_aml_ongoing_monitoring_enabled` | boolean | Mengaktifkan pemantauan AML berkelanjutan. |
| `aml_score_approve_threshold` | integer | Ambang batas persetujuan. |
| `aml_score_review_threshold` | integer | Ambang batas peninjauan. |
| `aml_match_score_threshold` | integer | Ambang batas skor kecocokan untuk kemungkinan kecocokan. |
| `aml_name_weight` | integer | Bobot nama. Jika salah satu bobot AML diisi, bobot nama, tanggal lahir, dan negara harus berjumlah `100`. |
| `aml_dob_weight` | integer | Bobot tanggal lahir. |
| `aml_country_weight` | integer | Bobot negara. |
| `create_cases_on_hit` | boolean | Membuka kasus secara otomatis saat skrining menghasilkan temuan, alih-alih membiarkan temuan tersebut ditriase dari sesi. Nonaktif secara default. |
| `case_blueprint` | uuid | Cetak biru kasus yang digunakan untuk membangun kasus yang dibuat otomatis. Hanya berlaku dengan `create_cases_on_hit`; default akun digunakan jika tidak diisi. |
| `status_rules` | array | Aturan status kustom opsional. |

Untuk skrining perusahaan KYB, gunakan kolom berikut:

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `kyb_score_approve_threshold` | integer | Ambang batas persetujuan AML perusahaan. |
| `kyb_score_review_threshold` | integer | Ambang batas peninjauan AML perusahaan. |
| `kyb_enable_ongoing_monitoring` | boolean | Mengaktifkan pemantauan AML berkelanjutan KYB. |
| `kyb_company_aml_match_score_threshold` | integer | Ambang batas skor kecocokan AML perusahaan. |
| `kyb_company_aml_name_weight` | integer | Bobot nama perusahaan. Bobot AML perusahaan harus berjumlah `100` jika diisi. |
| `kyb_company_aml_dob_weight` | integer | Bobot tanggal pendirian atau tanggal lahir. |
| `kyb_company_aml_country_weight` | integer | Bobot negara. |

### Skrining entitas yang diekstrak oleh langkah Document AI

Langkah AML biasanya membaca siapa yang diskrining dari langkah `OCR` (orang) atau langkah `KYB_REGISTRY` (perusahaan). Alur kerja yang hanya memiliki langkah ekstraksi `DOCUMENT_AI` untuk dokumen tidak terstandar seperti sertifikat pajak atau akta pendirian tidak memiliki keduanya, sehingga alur kerja tersebut harus menyatakan dari mana setiap input skrining berasal.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `aml_field_sources` | object | Tempat membaca entitas yang diskrining oleh langkah ini. `source` menyebut penghasilnya dan `key` menyebut nilai di dalamnya: kunci kolom Document AI untuk `document_ai`, ID node kuesioner untuk `questionnaire`, dan `expected_details.<field>` atau `metadata.<key>` untuk `expected_data`. KUNCI peta adalah salah satu dari empat input skrining, yaitu `full_name`, `date_of_birth`, `nationality`, dan `document_number`, yang untuk perusahaan dibaca sebagai nama hukum, tanggal pendirian, negara, dan nomor registrasi. Kolom Document AI yang sudah diberi kunci sebagai salah satu dari empat input tersebut dipetakan otomatis dan sengaja tidak disimpan, sehingga mengganti namanya tidak akan membekukan pemetaan yang sudah usang. Pemetaan eksplisit mengungguli pemetaan otomatis maupun dokumen identitas, dan pemetaan yang tidak menghasilkan nilai saat dijalankan membiarkan input kosong, tidak kembali ke sumber lain. Pada alur kerja bisnis (KYB), perusahaan yang dikembalikan oleh langkah `KYB_REGISTRY` bersifat otoritatif: hanya pemetaan eksplisit yang dapat menimpa salah satu inputnya, pemetaan otomatis tidak diterapkan di atas catatan registri, dan jika tidak ada langkah registri, pemetaan adalah seluruh identitas. Bentuk: `{"full_name"\|"date_of_birth"\|"nationality"\|"document_number": {"source": "document_ai"\|"questionnaire"\|"expected_data", "key": "<docai field key>\|<questionnaire node id>\|expected_details.<field>\|metadata.<key>"}}`. |
| `aml_entity_type` | string | `person` atau `company`. Default-nya `person` pada alur kerja individu (KYC) dan `company` pada alur kerja bisnis (KYB). Atur `company` untuk melakukan skrining terhadap bisnis yang disebutkan dalam dokumen yang diunggah tanpa langkah `KYB_REGISTRY`: penyedia mencari di catatan perusahaan dan skor kecocokan dihitung berdasarkan perusahaan. |
| `aml_incomplete_data_action` | tindakan | Keputusan ketika skrining dijalankan dengan data identitas yang tidak lengkap (nama, tanggal lahir, dan negara). `REVIEW` adalah default. `NO_ACTION` melanjutkan dengan data yang berkurang untuk alur kerja yang secara sadar hanya memiliki nama. Skrining tetap berjalan dan log data parsial tetap dicatat dalam kedua kasus; pengaturan ini hanya menentukan pengaruhnya terhadap status. |

Contoh: melakukan skrining terhadap perusahaan yang disebutkan dalam *acta constitutiva* Meksiko, tanpa dokumen identitas di mana pun dalam alur kerja:

```json theme={null}
{
  "feature": "AML",
  "config": {
    "aml_entity_type": "company",
    "aml_field_sources": {
      "full_name": { "source": "document_ai", "key": "razon_social" },
      "document_number": { "source": "document_ai", "key": "rfc" },
      "date_of_birth": { "source": "document_ai", "key": "fecha_constitucion" },
      "nationality": { "source": "document_ai", "key": "pais" }
    },
    "aml_incomplete_data_action": "REVIEW"
  }
}
```

> [!WARNING]
>
> Tanpa langkah `OCR` dan `KYB_REGISTRY` sebelumnya, langkah `AML` harus dapat mengisi
> `full_name`, karena tidak ada pencarian oleh penyedia tanpa nama. Alur kerja yang tidak memetakan apa pun, atau
> memetakan kunci Document AI yang tidak diekstrak oleh langkah hulu mana pun, akan ditolak saat disimpan, alih-alih disimpan dan dibiarkan
> tanpa skrining apa pun. Presisi AML langsung bergantung pada berapa banyak pengidentifikasi yang Anda berikan: skrining yang hanya menggunakan nama
> menghasilkan volume positif palsu yang tinggi.

## Analisis Perangkat & IP

Nilai fitur: `IP_ANALYSIS`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `ip_mismatch_action` | action | Tindakan ketika geolokasi IP tidak sesuai dengan data yang diharapkan. |
| `ip_location_not_determined_action` | action | Keputusan ketika tidak ada alamat IP yang mengidentifikasi pengguna akhir yang tercatat, sehingga sesi tidak memiliki lokasi IP sama sekali: negara, kota, ISP, koordinat, dan zona waktu tidak tersedia, dan `ip_geofencing_by_country`, perbandingan negara dokumen, serta pemeriksaan VPN/pusat data tidak dapat dijalankan. Defaultnya adalah `NO_ACTION`, yang tetap menampilkan peringatan `IP_LOCATION_NOT_DETERMINED` pada sesi tanpa mengubah keputusannya; atur `REVIEW` atau `DECLINE` jika sesi yang tidak memiliki lokasi tidak boleh lolos. |
| `vpn_detection_action` | action | Tindakan ketika penggunaan VPN atau proxy terdeteksi. |
| `expected_ip_mismatch_action` | action | Tindakan ketika IP tidak sesuai dengan IP yang diharapkan. |
| `duplicated_ip_action` | action | Tindakan ketika IP digunakan kembali secara mencurigakan. |
| `duplicated_device_action` | action | Tindakan ketika sidik jari perangkat persisten yang sama digunakan kembali di beberapa sesi dengan nilai `vendor_data` yang berbeda. |
| `recovered_device_action` | action | Tindakan ketika pemulihan sidik jari v2 menautkan sesi ke perangkat yang pernah terlihat sebelumnya dengan keyakinan tinggi setelah ID perangkat persisten berubah. |
| `is_ip_geofencing_enabled` | boolean | Mengaktifkan pembatasan geofencing IP. Jika `false`, `ip_geofencing_by_country` tetap disimpan tetapi tidak diterapkan. |
| `ip_geofencing_by_country` | object | Aturan lokasi IP per negara, dengan kunci berupa kode negara ISO-3: `{"USA": {"allowed": true, "states": {"California": {"allowed": false}}}}`. Entri negara bagian/wilayah menggantikan status negara; negara yang tidak tercantum diizinkan. |
| `ip_geofencing_action` | action | Tindakan ketika IP sesi berada di negara atau negara bagian/wilayah yang tidak diizinkan. Defaultnya adalah `DECLINE`. |
| `automation_detected_action` | action | Keputusan ketika sesi tampak dijalankan oleh otomatisasi, bukan oleh manusia. |
| `cross_org_fraud_device_action` | action | Keputusan ketika perangkat ini ditandai sebagai penipuan oleh organisasi lain dalam jaringan. |
| `cross_org_fraud_ip_action` | action | Keputusan ketika IP ini ditandai sebagai penipuan oleh organisasi lain dalam jaringan. |
| `device_app_tampered_action` | action | Keputusan ketika biner aplikasi host tampak telah dimodifikasi. |
| `device_blocklist_action` | action | Keputusan ketika perangkat berada dalam daftar blokir organisasi. |
| `device_debugger_action` | action | Keputusan ketika debugger terpasang pada aplikasi host. |
| `device_emulator_action` | action | Keputusan ketika perangkat adalah emulator, bukan perangkat keras asli. |
| `device_hooking_action` | action | Keputusan ketika hooking atau instrumentasi saat runtime terdeteksi. |
| `device_integrity_missing_action` | action | Keputusan ketika tidak ada atestasi integritas perangkat dari platform yang dikembalikan. |
| `device_rooted_action` | action | Keputusan ketika perangkat di-root atau di-jailbreak. |
| `multiple_devices_action` | action | Keputusan ketika sesi dijalankan dari lebih dari satu perangkat. |
| `device_liveness_attack_history_action` | action | Tindakan ketika perangkat yang sama (dicocokkan berdasarkan ID perangkat persisten) pernah digunakan dalam sesi sebelumnya oleh pengguna lain yang rekaman deteksi liveness-nya dinilai sebagai serangan (peringatan `DEVICE_LINKED_TO_LIVENESS_ATTACK`). Defaultnya adalah `NO_ACTION`. |
| `device_model_inconsistency_action` | action | Tindakan ketika perangkat yang sama (dicocokkan berdasarkan ID perangkat persisten) dilaporkan sebagai model perangkat yang berbeda dalam sesi sebelumnya (peringatan `DEVICE_MODEL_INCONSISTENT`). Defaultnya adalah `NO_ACTION`. |
| `status_rules` | array | Aturan status kustom opsional. |

Contoh:

```json theme={null}
{
  "feature": "IP_ANALYSIS",
  "config": {
    "vpn_detection_action": "REVIEW",
    "duplicated_device_action": "REVIEW",
    "recovered_device_action": "REVIEW",
    "is_ip_geofencing_enabled": true,
    "ip_geofencing_by_country": {
      "USA": { "allowed": true, "states": { "California": { "allowed": false } } },
      "RUS": { "allowed": false, "states": null }
    },
    "ip_geofencing_action": "DECLINE"
  }
}
```

Gunakan `recovered_device_action` secara terpisah dari `duplicated_device_action` jika Anda ingin memantau perangkat hasil pemulihan berkeyakinan tinggi sebelum menolaknya secara otomatis. Ini berguna selama peluncuran karena kecocokan perangkat hasil pemulihan dirancang untuk mendeteksi jaringan penipuan, tetapi tetap perlu dikalibrasi terhadap lalu lintas Anda sendiri.

## Verifikasi lokasi

Nilai fitur: `GEOLOCATION`.

Memeriksa lokasi orang tersebut saat melakukan verifikasi, dari posisi perangkat atau lokasi IP koneksinya, terhadap area yang diizinkan dan diblokir, lokasi IP, serta alamat dokumen.
Lihat [Verifikasi lokasi](https://docs.didit.me/id/core-technology/location-verification/overview.md) untuk cara langkah ini berperilaku dan [laporannya](https://docs.didit.me/id/core-technology/location-verification/report-location-verification.md) untuk kolom keputusan.
Tempatkan setelah Verifikasi Identitas atau Bukti Alamat jika Anda ingin jarak ke alamat dokumen, karena jarak hanya diukur saat alamat tersimpan.
Jika `geolocation_position_source` tidak diatur, jarak ke lokasi IP memerlukan langkah Analisis Perangkat & IP dalam alur kerja yang sama.
Semua kunci bersifat opsional: langkah dengan `config` kosong meminta perangkat untuk posisi dengan akurasi hingga 250 m, tidak lebih dari 120 detik, memberi orang tersebut 3 percobaan, dan tidak menerapkan aturan area.

Setiap temuan memiliki kunci tindakan sendiri, dan kunci tindakan yang tidak Anda atur mengikuti default dari `geolocation_preset` yang Anda pilih, atau default per kunci yang tercantum di bawah jika Anda tidak memilih preset.
Lokasi yang tidak pasti atau ditolak secara default menjadi `REVIEW`, dan tidak pernah `DECLINE`, karena izin yang ditolak atau radius yang besar bukan bukti penipuan.
Tindakan yang Anda atur secara eksplisit selalu didahulukan daripada preset.
Tantangan yang diputar ulang (`LOCATION_REPLAY_DETECTED`) dan atestasi perangkat yang gagal (`LOCATION_INTEGRITY_FAILED`) selalu ditolak dan tidak memiliki kunci tindakan.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `geolocation_position_source` | string | Asal posisi. `device_and_ip` meminta posisi perangkat dan membandingkannya dengan lokasi IP dari koneksi tempat posisi itu dikirim (pencarian intelijen IP jika IP tersebut belum tersimpan dalam cache). Jika tidak diatur (default), posisi perangkat tetap diminta dan, seperti sebelum kunci ini ada, dibandingkan dengan lokasi IP yang diamati oleh langkah Analisis Perangkat & IP pada sesi tersebut, sehingga tidak ada jarak tanpa langkah itu dan koneksi tidak pernah dicari. Pengecualiannya adalah node yang bertindak berdasarkan temuan VPN, proxy, atau Tor (tindakannya sendiri atau presetnya): node itu mencari koneksi untuk temuan tersebut dan membandingkan perangkat dengannya, sama persis seperti `device_and_ip`. `device_only` tidak pernah membandingkan dengan lokasi IP dan hanya mencari koneksi untuk temuan tersebut. `ip_only` tidak pernah meminta orang tersebut dan menilai lokasi IP koneksi, pada tingkat kota dengan radius 50 km, tanpa aturan akurasi, kebaruan, atau pemberian izin lokasi perkiraan; dengan `geolocation_areas`, kota pesisir dinilai di dalam negaranya kecuali negara lain berada dalam radius tersebut. Pada node yang meminta posisi perangkat, percobaan tanpa posisi perangkat dinilai sebagai penolakan atau kegagalan yang memang demikian: lokasi IP tidak pernah menggantikannya. |
| `geolocation_preset` | string | Default untuk setiap tindakan node ini yang tidak diatur. `licensing`: di luar area, di area yang diblokir, VPN, Tor, atau emulator ditolak; proxy dan temuan lainnya ditinjau, dan atestasi perangkat yang tidak ada tetap Tidak ada tindakan. `fraud_screening`: sama, kecuali yang ditolak oleh Licensing diteruskan ke peninjauan. Null mempertahankan default lama. Tindakan yang diatur secara eksplisit selalu didahulukan. |
| `geolocation_accuracy_mode` | string | Apa yang diminta dari perangkat. `precise` meminta sistem operasi untuk posisi presisi, dan orang yang hanya memberi izin posisi perkiraan diminta lagi selama percobaan masih tersisa, lalu dinilai oleh `geolocation_approximate_action`; `approximate_allowed` menerima izin lokasi perkiraan tanpa penilaian tersebut. `geolocation_max_accuracy_radius_m` berlaku dalam kedua kasus. `precise` jika tidak diatur. |
| `geolocation_max_accuracy_radius_m` | integer | Radius ketidakpastian maksimum, dalam meter, yang masih memungkinkan posisi perangkat dianggap valid. Dari 10 hingga 50000 meter; 250 jika tidak diatur. Posisi dengan radius ketidakpastian yang lebih besar, atau yang tidak melaporkan radius, mengikuti `geolocation_low_accuracy_behavior` dan dinilai oleh `geolocation_low_accuracy_action`. Node `ip_only` tidak memiliki radius perangkat dan tidak pernah menerapkannya. |
| `geolocation_max_accuracy_radius_unit` | string | Satuan yang ditampilkan konsol untuk `geolocation_max_accuracy_radius_m`. Hanya untuk tampilan: nilai yang disimpan selalu dalam meter, tidak ada aturan yang bergantung padanya, dan data langkah hanya meneruskannya agar klien dapat menampilkan satuan yang sama. |
| `geolocation_low_accuracy_behavior` | string | Perlakuan terhadap posisi yang lebih lebar dari `geolocation_max_accuracy_radius_m`, atau yang tidak memiliki radius: `ask_again` (default) meminta orang tersebut mencoba lagi selama percobaan masih tersisa; `fail` mengakhiri langkah pada percobaan pertama. |
| `geolocation_max_age_seconds` | integer | Usia posisi perangkat, dalam detik, saat server menerimanya. Dari 5 hingga 3600 detik; 120 jika tidak diatur. Posisi yang lebih lama diminta lagi selama percobaan masih tersisa, lalu dinilai oleh `geolocation_stale_fix_action`. |
| `geolocation_timeout_seconds` | integer | Berapa lama, dalam detik, klien membiarkan perangkat mencari posisi pada setiap percobaan; server meneruskannya dalam data langkah dan tidak menegakkannya sendiri. Dari 5 hingga 120 detik; 20 jika tidak diatur. Percobaan yang tidak menemukan posisi tepat waktu dikirim sebagai `timeout`, diminta lagi selama percobaan masih tersisa, lalu dinilai oleh `geolocation_unavailable_action`. |
| `geolocation_max_attempts` | integer | Berapa banyak percobaan yang diperoleh orang tersebut pada node ini. Dari 1 hingga 5 percobaan; 3 jika tidak diatur. Percobaan yang masih dapat diubah oleh orang tersebut (penolakan, posisi yang lebar, usang, atau perkiraan, atau temuan area atau anonimizer yang ditindaklanjuti node) diminta lagi selama percobaan masih tersisa, dan percobaan terakhir menentukan langkah. Posisi tiruan, atau emulator yang ditindaklanjuti node, mengakhiri langkah pada percobaan yang melaporkannya. |
| `geolocation_allow_qr_handoff` | boolean | Menawarkan untuk melanjutkan di ponsel dengan kode QR selama langkah masih terbuka (`allow_qr_handoff` dalam data langkah, `can_handoff` pada setiap jawaban submit). SDK native sudah berjalan di ponsel dan tidak pernah menampilkan kode tersebut. Aktif secara default. |
| `geolocation_allow_skip` | boolean | Mengizinkan orang tersebut melanjutkan tanpa lokasi kapan saja, dari layar pengantar atau layar coba lagi (`skipped: true`). Pelewatan mengakhiri langkah dan dinilai oleh `geolocation_unavailable_action`, kecuali jika pelewatan tersebut menjawab penolakan pada `geolocation_refusal_path` `continue_without_location`; dalam hal itu, pelewatan dicatat sebagai penolakan tersebut. Nonaktif secara default. |
| `geolocation_deep_link_enabled` | boolean | Diteruskan ke klien sebagai `deep_link_enabled` dalam data langkah: menawarkan opsi untuk membuka aplikasi milik pelanggan sendiri sebagai gantinya. Server tidak menerapkan aturan apa pun padanya. Nonaktif secara default. |
| `geolocation_refusal_path` | string | Jalur lanjutan yang ditawarkan ketika akses lokasi ditolak. `retry_then_handoff` (default) meminta izin lagi selama percobaan masih tersisa dan menawarkan pengalihan ke telepon; `continue_without_location` membiarkan pengguna melanjutkan sambil mencatat penolakan; `end_session` mengakhiri langkah dan sesi pada penolakan pertama, dan membutuhkan `geolocation_permission_denied_action` bernilai Review atau Decline serta alur kerja yang berakhir dengan keputusan Ditolak, Dalam Peninjauan, atau Final. Sesi ditentukan berdasarkan langkah-langkah yang telah dijalankan dan tidak pernah menghasilkan keputusan Approved: pada alur kerja yang tidak dapat berakhir dengan keputusan tersebut, sistem memilih akhir lain yang tidak menyetujui (ditolak untuk dalam peninjauan, dalam peninjauan untuk ditolak). |
| `is_geolocation_geofencing_enabled` | boolean | Mengaktifkan aturan area: `geolocation_areas`, atau `geolocation_geofencing_by_country` yang lebih lama, hanya berlaku selama nilai ini true, dan hanya dengan begitu data langkah mencantumkan `available_areas`. Nonaktif secara default. Jika aktif, daftar `geolocation_areas` memerlukan minimal satu area yang diizinkan. |
| `geolocation_areas` | array | Area yang diizinkan dan diblokir, diterapkan selama `is_geolocation_geofencing_enabled` bernilai true. Hanya posisi di dalam area yang diizinkan yang lolos, dan area yang diblokir selalu mengalahkan area yang diizinkan. Posisi dihitung berdasarkan seluruh lingkaran akurasinya: lingkaran yang memotong tepi yang menentukan hasil bersifat tidak ditentukan, tidak pernah di luar. Negara atau wilayah berakhir di tempat daratan lain dimulai, tidak pernah di garis pantainya, dan posisi yang menurut garis batas tidak berada di daratan mana pun (tepi laut atau dermaga yang terpotong oleh garis pantai yang disederhanakan) bersifat tidak ditentukan untuk setiap negara atau wilayah dalam radius posisi tersebut ditambah 12 mil laut. `id` adalah nilai yang dirujuk oleh aturan cabang dan `geolocation.inside_areas` / `geolocation.blocked_areas`. `kind` menentukan bentuknya: seluruh `country` (ISO 3166-1 alpha-3 dengan garis batas yang dipublikasikan; wilayah yang oleh garis batas digambarkan sebagai bagian dari negara lain harus menggunakan `region`, misalnya Réunion sebagai `FR-RE` milik Prancis, atau Bonaire, Sint Eustatius dan Saba sebagai `NL-BQ1` sampai `NL-BQ3`), `region` (kode ISO 3166-2 dari satu negara dengan batas yang dipublikasikan), `circle` (1 sampai 500 km), atau `polygon` (3 sampai 200 titik, berupa cincin yang sisi-sisinya tidak pernah saling berpotongan atau bersentuhan). Maksimal 50 area, id harus unik, dan minimal satu area yang diizinkan selama geofencing aktif. Tidak dapat dikombinasikan dengan `geolocation_geofencing_by_country`. |
| `geolocation_geofencing_by_country` | object | Aturan izin dan blokir negara serta wilayah untuk posisi perangkat itu sendiri, hanya diterapkan selama `is_geolocation_geofencing_enabled` bernilai true. Bentuknya sama dengan `ip_geofencing_by_country` pada Analisis IP, kecuali bahwa kunci `states` menggunakan kode ISO 3166-2 (`US-NJ`), bukan nama negara bagian, karena posisi dipetakan ke subdivisi, bukan ke label kota dari penyedia. Negara yang tidak tercantum diizinkan. Menyimpan aturan wilayah untuk negara yang tidak memiliki batas ISO 3166-2 yang dipublikasikan akan ditolak, bukan diabaikan tanpa pemberitahuan. |
| `geolocation_ip_distance_km` | integer | Jarak maksimum, dalam kilometer, antara posisi perangkat dan lokasi IP, setelah kedua radius ketidakpastian dikurangkan, sebelum `geolocation_ip_distance_action` berlaku. 200 jika kunci dihilangkan; null menonaktifkan perbandingan. Hanya node dengan `geolocation_position_source` bernilai `device_and_ip` atau tidak diatur yang membandingkan; kunci tersebut menentukan lokasi IP mana yang dibandingkan. |
| `geolocation_ip_distance_unit` | string | Satuan yang ditampilkan konsol untuk `geolocation_ip_distance_km`. Hanya untuk tampilan: nilai yang disimpan selalu dalam kilometer dan tidak ada aturan yang bergantung padanya. |
| `geolocation_document_distance_km` | integer | Jarak maksimum, dalam kilometer, antara posisi (lokasi IP pada node `ip_only`) dan alamat yang ditentukan oleh `geolocation_document_distance_basis` sebelum `geolocation_document_distance_action` berlaku. Tidak diatur atau null (default) berarti nonaktif. |
| `geolocation_document_distance_unit` | string | Satuan yang ditampilkan konsol untuk `geolocation_document_distance_km`. Hanya untuk tampilan: nilai yang disimpan selalu dalam kilometer dan tidak ada aturan yang bergantung padanya. |
| `geolocation_document_distance_basis` | string | Alamat yang menjadi dasar pengukuran `geolocation_document_distance_km`: `document` (default: alamat pada dokumen identitas, lalu bukti alamat), hanya `proof_of_address`, atau `declared` (`expected_details.address` yang diberikan saat pembuatan sesi, yang telah digeokode). |
| `geolocation_travel_tolerance_enabled` | boolean | Mengecualikan jarak dari alamat jika orang yang sama (`vendor_data` yang sama) pernah terlihat dalam radius `geolocation_travel_usual_area_km` dari alamat tersebut dalam `geolocation_travel_max_days` hari terakhir. Tidak pernah menoleransi VPN, posisi palsu, area yang diblokir, atau berada di luar area yang diizinkan. Hanya posisi yang diukur oleh perangkat yang dihitung sebagai terlihat di sana: penentuan posisi yang dipalsukan atau disimulasikan, emulator, atau atestasi yang gagal tidak pernah dihitung. |
| `geolocation_travel_usual_area_km` | integer | Radius di sekitar alamat yang dihitung sebagai area biasa orang tersebut. Dari 10 sampai 500 km; 100 jika tidak diatur. |
| `geolocation_travel_max_days` | integer | Berapa lama setelah terlihat di area biasa, posisi yang jauh masih dianggap perjalanan. Dari 1 sampai 90 hari; 14 jika tidak diatur. |
| `geolocation_consecutive_mismatch_count` | integer | Picu LOCATION\_CONSECUTIVE\_MISMATCHES ketika pemeriksaan ini dan pemeriksaan sebelumnya dari orang yang sama (`vendor_data` yang sama) berada di luar area yang diizinkan, di area yang diblokir, atau terlalu jauh dari alamat, sebanyak jumlah ini secara berturut-turut. Pemeriksaan yang tidak membandingkan apa pun tidak memperpanjang maupun memutus rangkaian, begitu pula posisi yang tidak diukur oleh perangkat (penentuan posisi yang dipalsukan atau disimulasikan, emulator, atestasi yang gagal). Dari 2 sampai 10; null (default) berarti nonaktif. |
| `geolocation_approximate_action` | tindakan | Keputusan ketika pengguna memberikan lokasi perkiraan sementara `geolocation_accuracy_mode` meminta lokasi presisi. Default-nya `REVIEW`. |
| `geolocation_blocked_area_action` | tindakan | Keputusan ketika posisi, beserta seluruh lingkaran akurasinya, berada di dalam area yang diblokir dari `geolocation_areas`. Default-nya Decline. |
| `geolocation_consecutive_mismatch_action` | tindakan | Keputusan saat `geolocation_consecutive_mismatch_count` ketidakcocokan berturut-turut tercapai. Defaultnya Review. |
| `geolocation_document_distance_action` | tindakan | Keputusan saat posisi perangkat lebih jauh dari alamat dokumen daripada `geolocation_document_distance_km`. Alamat di-geocode secara kasar, sehingga ini merupakan sinyal yang lemah. Defaultnya `REVIEW`. |
| `geolocation_emulator_action` | tindakan | Keputusan saat aplikasi yang membagikan lokasi melaporkan berjalan di emulator. Browser tidak dapat melaporkannya. Kecuali diatur ke Tidak ada tindakan, langkah ini berakhir pada percobaan tersebut: memeriksa ulang tidak dapat mengubah perangkat. Tidak ada tindakan kecuali diatur atau preset menentukan lain. |
| `geolocation_geofence_undetermined_action` | tindakan | Keputusan saat posisi tidak dapat ditempatkan di dalam atau di luar pagar karena lingkaran akurasinya menyentuh batas. Ketidakpastian tidak pernah dilaporkan sebagai berada di luar. Defaultnya `REVIEW`. |
| `geolocation_geofencing_action` | tindakan | Keputusan saat posisi perangkat, beserta seluruh lingkaran ketidakpastiannya, berada di luar `geolocation_geofencing_by_country`. Defaultnya `DECLINE`. |
| `geolocation_integrity_missing_action` | tindakan | Keputusan saat klien native mengirimkan posisi tanpa token atestasi perangkat. Defaultnya Tidak ada tindakan; klien web dicatat sebagai tidak didukung, bukan hilang, karena browser tidak dapat melakukan atestasi. |
| `geolocation_ip_distance_action` | tindakan | Keputusan saat jarak antara posisi perangkat dan lokasi IP sesi lebih jauh daripada `geolocation_ip_distance_km`, setelah kedua radius ketidakpastian dikurangkan. Defaultnya `REVIEW`. |
| `geolocation_low_accuracy_action` | tindakan | Keputusan saat tidak ada percobaan yang mencapai presisi yang disyaratkan: posisi terbaik memiliki radius ketidakpastian lebih lebar daripada `geolocation_max_accuracy_radius_m`, atau tidak melaporkan radius sama sekali. Posisi tanpa radius tidak pernah dihitung memenuhi batas. Defaultnya `REVIEW`. |
| `geolocation_mock_location_action` | tindakan | Keputusan saat sistem operasi melaporkan posisi sebagai simulasi, bukan hasil pengukuran (Android mock provider, iOS simulated-by-software). Defaultnya `REVIEW`. |
| `geolocation_permission_denied_action` | tindakan | Keputusan saat pengguna menolak atau menutup permintaan lokasi pada setiap percobaan yang diizinkan. Defaultnya Review: penolakan adalah pilihan, bukan sinyal penipuan. |
| `geolocation_proxy_action` | tindakan | Keputusan saat koneksi yang membagikan lokasi melalui proxy terbuka, anonim, atau proxy relay privat. Tidak ada tindakan kecuali diatur atau preset menentukan lain. |
| `geolocation_stale_fix_action` | tindakan | Keputusan saat posisi diukur lebih dari `geolocation_max_age_seconds` sebelum server menerimanya. Defaultnya `REVIEW`. |
| `geolocation_tor_action` | tindakan | Keputusan saat koneksi yang membagikan lokasi adalah node keluar Tor. Tidak ada tindakan kecuali diatur atau preset menentukan lain. |
| `geolocation_unavailable_action` | tindakan | Keputusan saat tidak ada posisi yang dapat diperoleh: layanan lokasi mati atau dibatasi, sistem penentuan posisi tidak mengembalikan apa pun, percobaan melewati batas waktu, pengguna melewati langkah ini, atau klien terlalu lama untuk mendukungnya. Defaultnya `REVIEW`. |
| `geolocation_vpn_action` | tindakan | Keputusan saat koneksi yang membagikan lokasi adalah VPN komersial. Kecuali diatur ke Tidak ada tindakan, pengguna diminta mematikannya dan memeriksa ulang selama percobaan masih tersisa. Tidak ada tindakan kecuali diatur atau preset menentukan lain. |
| `status_rules` | array | Aturan status kustom opsional. Anda dapat menargetkan kolom `geolocation.*` yang tercantum di [Laporan verifikasi lokasi](https://docs.didit.me/id/core-technology/location-verification/report-location-verification.md#kolom-untuk-aturan-status-dan-cabang). |

### Bentuk area

Setiap item di `geolocation_areas` memiliki `id` (1 hingga 64 karakter dari `A-Z a-z 0-9 _ -`, unik dalam daftar), `label` opsional (hingga 80 karakter), `type` berupa `allowed` atau `blocked`, dan `kind` yang menentukan bentuknya.

| `kind` | Field tambahan | Arti |
| - | - | - |
| `country` | `country` (ISO 3166-1 alpha-3) | Seluruh negara yang memiliki batas wilayah yang dipublikasikan. |
| `region` | `country`, `regions` (kode ISO 3166-2 dari negara tersebut) | Satu atau lebih subdivisi dari satu negara dengan batas yang dipublikasikan. |
| `circle` | `center` (`latitude`, `longitude`), `radius_km` (1 hingga 500) | Setiap titik dalam radius dari pusat. |
| `polygon` | `points` (3 hingga 200 item berupa `latitude`, `longitude`) | Cincin tertutup yang sisi-sisinya tidak pernah saling memotong atau bersentuhan. |

Daftar berisi paling banyak 50 area dan memerlukan setidaknya satu area `allowed` selama `is_geolocation_geofencing_enabled` bernilai `true`.
`geolocation_areas` dan `geolocation_geofencing_by_country` tidak dapat dikirim bersamaan, dan `geolocation_refusal_path: "end_session"` memerlukan `geolocation_permission_denied_action` bernilai `REVIEW` atau `DECLINE`.
API menolak area yang tidak akan pernah cocok, seperti region dari negara tanpa batas yang dipublikasikan, alih-alih menyimpannya.

Contoh:

```json theme={null}
{
  "feature": "GEOLOCATION",
  "config": {
    "geolocation_position_source": "device_and_ip",
    "geolocation_preset": "licensing",
    "geolocation_max_accuracy_radius_m": 250,
    "geolocation_max_attempts": 3,
    "is_geolocation_geofencing_enabled": true,
    "geolocation_areas": [
      { "id": "spain", "label": "Spain", "type": "allowed", "kind": "country", "country": "ESP" },
      { "id": "ceuta-melilla", "type": "blocked", "kind": "region", "country": "ESP", "regions": ["ES-CE", "ES-ML"] }
    ],
    "geolocation_ip_distance_km": 200,
    "geolocation_ip_distance_action": "REVIEW",
    "geolocation_vpn_action": "DECLINE"
  }
}
```

## Bukti Alamat

Nilai fitur: `PROOF_OF_ADDRESS`.

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `poa_documents_allowed` | objek | Konfigurasi tipe dokumen POA per kode negara ISO3. Setidaknya satu tipe dokumen yang valid harus diaktifkan. |
| `poa_languages_allowed` | objek | Kode bahasa ISO 639-1 ke `0` atau `1`. Setidaknya satu bahasa harus diaktifkan. |
| `poa_name_or_address_mismatch_action` | tindakan | Tindakan ketika nama atau alamat tidak cocok dengan data yang diharapkan. |
| `poa_document_issues_action` | tindakan | Tindakan ketika dokumen memiliki masalah kualitas atau ekstraksi. |
| `poa_max_attempts_exceeded_action` | tindakan terbatas | Tindakan ketika pengguna melampaui batas percobaan ulang. Gunakan `DECLINE` atau `REVIEW`. |
| `poa_document_authenticity_action` | tindakan terbatas | Tindakan ketika pemeriksaan keaslian gagal. Gunakan `DECLINE` atau `REVIEW`. |
| `poa_document_unproven_text_replacement_action` | tindakan | Tindakan ketika kolom teks dikosongkan dan diketik ulang dengan font lain, dan file tidak memuat bukti apakah isinya berubah (`POA_DOCUMENT_UNPROVEN_TEXT_REPLACEMENT`). |
| `poa_unsupported_document_type_action` | tindakan | Tindakan ketika tipe dokumen tidak didukung. |
| `poa_unsupported_language_action` | tindakan | Tindakan ketika bahasa dokumen tidak didukung. |
| `poa_issuer_not_identified_action` | tindakan | Tindakan ketika penerbit dokumen tidak teridentifikasi. |
| `poa_issue_date_not_detected_action` | tindakan | Tindakan ketika tanggal terbit tidak ada. |
| `poa_unparsable_or_invalid_address_action` | tindakan | Tindakan ketika alamat tidak valid atau tidak dapat diurai. |
| `address_validation_enabled` | boolean | Memvalidasi alamat yang dibaca langkah ini (tercetak pada bukti alamat; hanya unggahan yang lolos pemeriksaan dokumen yang divalidasi) terhadap data referensi pos: memastikan alamat tersebut ada dan menormalkannya, dan tidak pernah mengaitkannya dengan seseorang. Hasilnya menjadi objek `address_validation` pada langkah keputusan. **Dikenakan biaya \$0.10 per alamat yang divalidasi**; validasi yang tidak dapat dijalankan (`unavailable`) tidak dikenakan biaya. Nonaktif secara default. |
| `address_not_verified_action` | tindakan | Tindakan ketika Validasi Alamat tidak dapat memastikan alamat hingga ke gedungnya (`ADDRESS_NOT_VERIFIED`: `partially_verified` atau `not_verified`). Hanya berlaku selama `address_validation_enabled` aktif. Defaultnya `NO_ACTION`, yang hanya mencatat peringatan. |
| `poa_name_match_score_threshold` | integer | Ambang batas skor kecocokan nama. |
| `poa_max_retry_attempts` | integer | Batas coba lagi, `2` hingga `5`. |
| `status_rules` | array | Aturan status kustom opsional. |

## Kuesioner

Nilai fitur: `QUESTIONNAIRE`.

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `questionnaire_uuid` | UUID | Wajib. Gunakan `questionnaire_id` yang dikembalikan oleh `POST /v3/questionnaires/`. |
| `review_questionnaire_manually` | boolean | Mengirim respons kuesioner ke peninjauan manual. |
| `status_rules` | array | Aturan status kustom opsional. Anda dapat menargetkan kolom `questionnaire.answers.<question_id>`. |

## Registri KYB

Nilai fitur: `KYB_REGISTRY`.

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `kyb_accepted_countries` | objek | Daftar izin negara ISO3 warisan untuk pencarian registri bisnis. Digantikan oleh `kyb_registry_countries_config`; masih dapat dibaca, dan masih diturunkan darinya untuk alur kerja yang sudah ada, tetapi bukan lagi cara untuk mengonfigurasi alur kerja baru. |
| `kyb_manual_company_action` | tindakan | Tindakan ketika perusahaan memerlukan penanganan manual. |
| `kyb_registry_fields_config` | objek | Visibilitas dan status wajib setiap kolom untuk formulir registri di alur yang di-hosting. Lihat di bawah. |
| `kyb_registry_countries_config` | objek | Perutean registri per negara, dalam bentuk `{"<ISO2>": {"enabled": bool, "tier": "basic" \| "shareholders" \| "ubo"}}`. Setiap negara yang diaktifkan memilih tingkat data yang dikenakan biaya saat perusahaan dipilih (`basic` adalah tingkat Lite), dan hanya tingkat yang ditandai tersedia untuk negara tersebut oleh [endpoint harga](https://docs.didit.me/id/getting-started/kyb-registry-pricing.md) yang dapat diaktifkan. Setidaknya satu negara harus diaktifkan: pemeriksaan registri yang tidak mencari di mana pun akan ditolak. Perusahaan yang dimasukkan secara manual ditagih terpisah dan tidak menggunakan konfigurasi ini. |
| `kyb_registry_monitoring_enabled` | boolean | Pertahankan rekaman registri perusahaan di bawah pemantauan berkelanjutan setelah hasil Shareholders atau UBO: perubahan status, pejabat, kepemilikan, atau alamat mengembalikan sesi ke peninjauan dan memicu webhook. Hanya tersedia jika penyedia registri menawarkan pemantauan. USD 2.00 per perusahaan per tahun, dapat dibatalkan kapan saja. Nonaktif secara default. |
| `kyb_vat_invalid_action` | tindakan | Tindakan ketika nomor VAT perusahaan gagal validasi EU VIES. Defaultnya `REVIEW`. |
| `kyb_vat_unverified_action` | tindakan | Tindakan ketika nomor VAT tidak dapat divalidasi karena VIES tidak tersedia. Defaultnya `NO_ACTION`. |
| `status_rules` | array | Aturan status kustom opsional. |

`kyb_registry_fields_config` memetakan setiap kunci kolom yang dapat dikonfigurasi ke `{"enabled": bool, "required": bool}`. `enabled: false` menyembunyikan kolom, `enabled: true, required: false` menampilkannya sebagai opsional, dan `enabled: true, required: true` membuatnya wajib saat pengiriman. `company_name`, `country_code`, dan `region` selalu ditampilkan dan wajib, dan tidak dapat dikonfigurasi. Jika objek dihilangkan, bernilai `null`, atau berupa `{}`, default berlaku: hanya `incorporation_date` yang wajib dan setiap kolom lain bersifat opsional.

```json theme={null}
{
  "kyb_registry_fields_config": {
    "registration_number": { "enabled": true, "required": true },
    "incorporation_date": { "enabled": true, "required": true },
    "vat_number": { "enabled": true, "required": false },
    "control_scheme": { "enabled": false, "required": false }
  }
}
```

Kunci kolom yang dapat dikonfigurasi: `registration_number`, `incorporation_date`, `legal_address`, `vat_number`, `alternative_names`, `tax_number`, `company_type`, `legal_entity_identifier`, `location_of_registration`, `nature_of_business`, `registered_capital_amount`, `registered_capital_currency`, `website`, `email`, `phone`, `control_scheme`. Lihat [konfigurasi kolom formulir registri yang dapat dikonfigurasi](https://docs.didit.me/id/business-verification/company-data.md#kolom-formulir-registri-yang-dapat-dikonfigurasi) untuk perilaku pengguna akhir dan [validasi VAT dan ID pajak](https://docs.didit.me/id/business-verification/company-data.md#validasi-vat-dan-id-pajak) untuk cara `vat_number` dan `tax_number` diperiksa.

## Dokumen KYB

Nilai fitur: `KYB_DOCUMENTS`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `kyb_required_document_groups` | objek atau array | Wajib. Grup dokumen KYB yang wajib. |
| `kyb_document_subtype_config` | objek | Pengaktifan subtipe per dokumen dan konfigurasi usia. |
| `kyb_document_tampering_action` | tindakan terbatas | Tindakan saat manipulasi terdeteksi. Gunakan `DECLINE` atau `REVIEW`. |
| `kyb_document_unproven_text_replacement_action` | tindakan | Tindakan saat kolom teks dokumen perusahaan dikosongkan dan diketik ulang dengan font lain, sementara berkas tidak memuat bukti apakah isinya berubah (`KYB_DOCUMENT_UNPROVEN_TEXT_REPLACEMENT`). |
| `kyb_document_critical_mismatch_action` | tindakan terbatas | Tindakan untuk ketidaksesuaian dokumen yang kritis. Gunakan `DECLINE` atau `REVIEW`. |
| `kyb_document_non_critical_mismatch_action` | tindakan | Tindakan untuk ketidaksesuaian dokumen yang tidak kritis. |
| `kyb_document_age_action` | tindakan | Tindakan saat aturan usia dokumen tidak terpenuhi. |
| `kyb_document_max_retry_attempts` | integer | Batas coba lagi untuk dokumen KYB. |
| `kyb_document_max_attempts_exceeded_action` | tindakan terbatas | Tindakan saat jumlah percobaan maksimum terlampaui. Gunakan `DECLINE` atau `REVIEW`. |
| `status_rules` | array | Aturan status kustom opsional. |

## Pihak Kunci KYB

Nilai fitur: `KYB_KEY_PEOPLE`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `kyb_ubo_ownership_threshold` | integer | Ambang batas kepemilikan UBO, `0` sampai `100`. |
| `kyb_shareholder_ownership_threshold` | integer | Ambang batas kepemilikan pemegang saham, `0` sampai `100`. Nilainya tidak boleh lebih tinggi dari `kyb_ubo_ownership_threshold`. |
| `kyb_key_people_ownership_required` | boolean | Mewajibkan persentase kepemilikan pada setiap pihak kunci yang dikirimkan. Diterapkan saat pengiriman dan ditampilkan ke UI yang di-hosting, yang menandai kolom tersebut sebagai wajib. Default `false`. |
| `kyb_require_ubo_kyc` | boolean | Mewajibkan UBO menyelesaikan alur kerja verifikasi orang. |
| `kyb_ubo_verification_workflow` | UUID | Wajib jika `kyb_require_ubo_kyc` bernilai `true`. Harus mengacu pada alur kerja non-KYB dalam aplikasi yang sama. |
| `kyb_require_officer_kyc` | boolean | Mewajibkan pejabat perusahaan menyelesaikan verifikasi orang. |
| `kyb_shareholder_verification_workflow` | UUID | Alur kerja verifikasi orang untuk pemegang saham. |
| `kyb_officer_verification_workflow` | UUID | Alur kerja verifikasi orang untuk pejabat perusahaan. |
| `kyb_require_corporate_ubo_kyb` | boolean | Mewajibkan UBO korporasi menyelesaikan KYB. |
| `kyb_corporate_ubo_verification_workflow` | UUID | Wajib jika `kyb_require_corporate_ubo_kyb` bernilai `true`. Harus mengacu pada alur kerja KYB dalam aplikasi yang sama. |
| `kyb_reject_if_ubo_rejected` | boolean | Menolak bisnis jika verifikasi UBO yang wajib ditolak. |
| `kyb_wait_for_all_ubos` | boolean | Menunggu semua verifikasi UBO yang wajib selesai sebelum memutuskan sesi KYB. |
| `kyb_role_config` | objek atau array | Konfigurasi per peran. Setiap peran KYC yang wajib harus menyertakan `verification_workflow`. |
| `kyb_reuse_verified_individuals` | boolean | Menggunakan kembali individu yang sudah terverifikasi jika memungkinkan. |
| `kyb_notify_parties_by_email` | boolean | Mengirimkan notifikasi email kepada pihak kunci yang diundang. |
| `kyb_key_people_company_fields` | objek | Detail perusahaan yang dikumpulkan untuk pihak kunci KORPORASI. Bentuk daftar deskriptor dan aturan yang sama dengan `kyb_key_people_person_fields`. Bentuk: `[{"key": "<field key>", "label": "<label>", "type": "text"\|"number"\|"date"\|"phone"\|"email", "required": true\|false, "custom": true\|false}]`. |
| `kyb_key_people_document_mismatch_action` | tindakan | Keputusan saat dokumen pihak kunci tidak sesuai dengan detail yang dideklarasikan untuknya. |
| `kyb_key_people_person_fields` | objek | Detail pribadi mana yang dikumpulkan untuk pihak kunci individu, sebagai DAFTAR TERURUT deskriptor kolom (bukan peta). `key` wajib diisi dan tidak boleh kosong; `type` harus salah satu dari text, number, date, phone atau email; `custom` menandai kolom yang ditambahkan oleh pelanggan, bukan salah satu kolom bawaan. Bentuk: `[{"key": "<field key>", "label": "<label>", "type": "text"\|"number"\|"date"\|"phone"\|"email", "required": true\|false, "custom": true\|false}]`. |
| `kyb_key_people_prefill_from_registry` | boolean | Isi otomatis daftar pihak kunci dari hasil registri perusahaan, sehingga pelanggan cukup mengonfirmasi dan memperbaiki, tanpa harus mengetik setiap pejabat dan pemegang saham. |
| `status_rules` | array | Aturan status kustom opsional. |

## Document AI

Nilai fitur: `DOCUMENT_AI`.

Meminta satu atau beberapa dokumen dari pengguna dan mengekstrak kolom bernama yang Anda tentukan dengan model visi. Setiap kolom yang dikonfigurasi menjadi nilai yang dapat dicabangkan, yaitu `document_ai.<key>`, dan hasil langkah ini adalah `document_ai.status`.

| Kolom konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `document_ai_documents` | array | Wajib. Dokumen yang akan diminta (maksimal `3`). Setiap entri adalah objek dokumen (lihat di bawah). |
| `document_ai_unreadable_document_action` | action | Tindakan ketika dokumen tidak dapat dibaca atau tidak ada data yang dapat diekstrak. |
| `document_ai_missing_required_fields_action` | action | Tindakan ketika kolom wajib tidak dapat diekstrak. |
| `document_ai_document_tampering_action` | restricted action | Tindakan ketika dokumen menunjukkan tanda-tanda manipulasi. Gunakan `DECLINE` atau `REVIEW`. |
| `document_ai_name_mismatch_action` | action | Tindakan ketika nama lengkap yang diekstrak tidak cocok dengan identitas terverifikasi. Memerlukan kolom yang ditandai dengan `is_full_name`. |
| `document_ai_unsupported_file_action` | action | Tindakan ketika tipe file yang diunggah tidak didukung. |
| `document_ai_max_attempts_exceeded_action` | restricted action | Tindakan ketika pengguna melampaui batas percobaan ulang. Gunakan `DECLINE` atau `REVIEW`. |
| `document_ai_name_match_score_threshold` | integer | Skor minimum (`0`–`100`) agar nama lengkap yang diekstrak dianggap cocok dengan identitas terverifikasi. Jika di bawah nilai ini, `document_ai_name_mismatch_action` berlaku. |
| `document_ai_max_retry_attempts` | integer | Batas coba lagi, `2` sampai `5`. |
| `status_rules` | array | Aturan status kustom opsional. Anda dapat menargetkan kolom `document_ai.<key>`. |

Setiap entri dalam `document_ai_documents` adalah sebuah dokumen:

| Kolom dokumen | Tipe | Deskripsi |
| - | - | - |
| `document_key` | string | Wajib. Pengenal tetap untuk dokumen, unik dalam langkah ini. |
| `title` | string | Wajib. Judul yang ditampilkan kepada pengguna. |
| `description` | string | Wajib. Petunjuk yang ditampilkan kepada pengguna tentang apa yang harus diunggah. |
| `title_i18n` | object | Opsional. Kode lokal untuk judul terjemahan (misalnya `{ "es": "Comprobante de fondos" }`). |
| `description_i18n` | object | Opsional. Kode lokal untuk deskripsi terjemahan. |
| `fields` | array | Wajib. Kolom yang akan diekstrak (minimal satu). Kunci kolom harus unik dalam dokumen. |

Setiap entri dalam `fields` sebuah dokumen adalah sebuah kolom:

| Kolom | Tipe | Deskripsi |
| - | - | - |
| `key` | string | Wajib. Kunci JSON tetap untuk nilai yang diekstrak, unik dalam dokumen. Percabangan menggunakan `document_ai.<key>`. |
| `name` | string | Wajib. Label kolom yang dapat dibaca manusia. |
| `name_i18n` | object | Opsional. Kode lokal untuk nama kolom terjemahan. |
| `instruction` | string | Opsional. Petunjuk yang memberi tahu model secara tepat apa yang harus diekstrak untuk kolom ini. |
| `type` | string | Tipe kolom: `text`, `number`, atau `date`. Default-nya `text`. |
| `required` | boolean | Menentukan apakah kolom harus ada. Default-nya `false`. Jika `true` dan nilainya tidak ada, `document_ai_missing_required_fields_action` berlaku. |
| `is_full_name` | boolean | Opsional, default-nya `false`. Menandai kolom yang nilainya adalah nama lengkap pemegang dokumen, dibandingkan dengan identitas terverifikasi (nama dari verifikasi identitas, atau detail yang diharapkan pada sesi). **Paling banyak satu kolom per dokumen** boleh diatur `true`, dan kolom ini **tidak wajib**. Dokumen boleh tidak menandai kolom mana pun, dan dalam kasus itu tidak ada perbandingan nama yang dijalankan untuk dokumen tersebut. Hanya kolom `text` yang dapat menjadi nama lengkap. |

Contoh:

```json theme={null}
{
  "feature": "DOCUMENT_AI",
  "config": {
    "document_ai_documents": [
      {
        "document_key": "proof_of_funds",
        "title": "Proof of Funds",
        "description": "Upload a recent bank statement.",
        "title_i18n": { "es": "Comprobante de fondos" },
        "fields": [
          {
            "key": "account_holder",
            "name": "Account holder",
            "instruction": "The full name of the account holder as printed on the statement.",
            "type": "text",
            "required": true,
            "is_full_name": true
          },
          {
            "key": "closing_balance",
            "name": "Closing balance",
            "instruction": "The closing balance amount.",
            "type": "number",
            "required": false
          }
        ]
      }
    ],
    "document_ai_missing_required_fields_action": "REVIEW",
    "document_ai_name_mismatch_action": "REVIEW",
    "document_ai_name_match_score_threshold": 80
  }
}
```

## Tanda Tangan Elektronik

Nilai fitur: `SIGNATURE`.

Memungkinkan orang yang telah diverifikasi, atau pihak kunci perusahaan, menandatangani dokumen, pada level Simple (bawaan) atau Advanced (AES). Letakkan setelah langkah yang memverifikasi penandatangan: Verifikasi Identitas, dan Verifikasi Email atau Verifikasi Telepon untuk kodenya. Lihat [Tanda Tangan Elektronik](https://docs.didit.me/id/core-technology/electronic-signature/overview.md).

| Field konfigurasi | Tipe | Deskripsi |
| - | - | - |
| `signature_documents` | array | Dokumen yang diunggah ke alur kerja ini di konsol, sesuai urutan yang dilihat penandatangan, dalam bentuk `[{"uuid", "title", "file_name", "pages", "size_bytes"}]`. Hanya nilai `uuid` dan urutannya yang dibaca; sisanya diambil dari file yang tersimpan. Maksimal 20 dokumen dan 50 MB secara total. Bawaan `[]`. |
| `signature_documents_source` | string | Asal dokumen: `workflow` (bawaan), `session` (`sign.documents` pada [buat sesi](https://docs.didit.me/id/sessions-api/create-session.md#dokumen-tanda-tangan-elektronik)) atau `both` (dokumen alur kerja didahulukan). |
| `signature_require_read_to_end` | boolean | Penandatangan harus membaca sampai akhir setiap dokumen tanpa kolom sebelum menyetujuinya. Bawaan `true`. |
| `signature_consent_per_document` | boolean | Penandatangan menyetujui setiap dokumen tanpa kolom secara terpisah. Untuk dokumen dengan kolom, kolom terpandu dan persetujuan akhir menggantikannya. Bawaan `true`. |
| `signature_signer` | string | Siapa yang menandatangani: `verified_person` (bawaan, KYC), atau untuk KYB `legal_representative` (pihak kunci dengan peran `representative` atau `authorized_signatory`) atau `key_people` (setiap pihak kunci individu yang memiliki sesi KYC). |
| `signature_level` | string | `simple` (bawaan): tanpa verifikasi identitas, email, telepon, atau kode; penandatangan mengetik namanya dan menandatangani melalui tautan sesi. `aes`: memerlukan verifikasi identitas yang disetujui dan email atau telepon yang terverifikasi, serta kode sekali pakai. `simple` ditolak untuk penandatangan `legal_representative` dan `key_people` dengan `signature_simple_requires_verified_person`. Selama `signature_availability.aes` bernilai `false` pada alur kerja, menyimpan langkah `aes` baru mengembalikan `400` dengan `aes_not_available`. `qes` segera hadir: menyimpannya mengembalikan `400` dengan `qes_not_available`. |
| `signature_format` | string | `pades` (bawaan). `xades` dan `cades` ditolak untuk AES dengan `signature_format_not_supported`. |
| `signature_otp_channel` | string | Tujuan kode sekali pakai: `email` (bawaan) atau `sms`. Kode hanya dikirim ke kontak yang telah diverifikasi sebelumnya dalam sesi. |
| `signature_email_signed_copy` | boolean | Kirimkan salinan dokumen yang sudah ditandatangani kepada penandatangan melalui email. Memerlukan email yang terverifikasi. Bawaan `true`. |
| `signature_evidence_page` | boolean | Tambahkan halaman bukti ke setiap PDF yang sudah ditandatangani. Bawaan `true`. |
| `signature_link_validity_days` | integer | Berapa lama tautan penandatanganan tetap berlaku, `1` sampai `30` hari sejak sesi dibuat. Bawaan `7`. |
| `signature_declined_action` | action | Keputusan saat penandatangan menolak. Tidak ada biaya yang dikenakan. Bawaan `REVIEW`. |
| `signature_otp_failed_action` | action | Keputusan setelah 3 kode salah atau lebih dari 5 kode yang diminta. Bawaan `DECLINE`. |
| `signature_name_mismatch_action` | action | Keputusan saat nama yang dinyatakan pihak kunci tidak cocok dengan nama terverifikasinya. Bawaan `DECLINE`. |
| `signature_identity_not_verified_action` | action | Keputusan saat penandatangan tidak memiliki bukti identitas yang disetujui. Bawaan `DECLINE`. |
| `signature_document_changed_action` | action | Keputusan saat dokumen tidak lagi cocok dengan SHA-256 yang dicatat saat ditampilkan. Bawaan `DECLINE`. |
| `status_rules` | array | Aturan status kustom opsional. Anda dapat menargetkan `signature.status`, `signature.level`, dan `signature.format`. |

Kolom pada dokumen alur kerja ditempatkan di editor templat konsol. Untuk dokumen sesi, kirimkan di `sign.documents[].fields`, dan kirimkan nilai kolom `api.<key>` di `sign.field_values`. Lihat [Buat sesi](https://docs.didit.me/id/sessions-api/create-session.md#dokumen-tanda-tangan-elektronik).

Contoh, untuk dokumen yang dikirim pada setiap sesi:

```json theme={null}
{
  "feature": "SIGNATURE",
  "config": {
    "signature_documents_source": "session",
    "signature_signer": "verified_person",
    "signature_level": "aes",
    "signature_otp_channel": "email",
    "signature_link_validity_days": 14,
    "signature_declined_action": "REVIEW"
  }
}
```


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