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

# Integrasi KYB: Panduan Arsitektur & Pola

> Integrasi KYB siap produksi Didit: arsitektur, sesi, alur hosted, webhook, dan keputusan. Mulai $2.00 per pemeriksaan, harga per negara & tingkat.



Prompt Integrasi KYB
        Salin prompt ke papan klip



      
      

\<pre>

\````# Goal — ship a production-ready KYB (business verification) integration

KYB runs through the same `/v3/session/` endpoint as KYC. The session's workflow determines whether it's a KYC or KYB session — pass a KYB workflow id and Didit creates a business session automatically (`session_kind: "business"`).

\## End-to-end flow

\```
You: POST /v3/session/ (KYB workflow_id, vendor_data) → session_id, url, session_token
You: deliver url to the business contact (email / your UI / iframe)
Biz: completes the hosted flow (registry confirm → Key People → documents → AML)
Didit → Webhook: status.updated with session_kind: "business"
You: GET /v3/session/{session_id}/decision/ → full KYB decision
You: branch on decision.status ("Approved" / "Declined" / "In Review" / "Resubmitted")
\```

\## Create a KYB session

\```bash
curl -X POST https://verification.didit.me/v3/session/ \
-H "x-api-key: $DIDIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "$KYB_WORKFLOW_ID",
"vendor_data": "biz-acme",
"callback": "https://myapp.com/kyb/return",
"metadata": {"plan": "growth", "country": "GBR"}
}'
\```

Recommended fields:

\- `workflow_id` — references your KYB workflow.
\- `vendor_data` — your business id; binds the session to a [Business entity](/entities/businesses/overview).
\- `callback` — where to redirect the user after completion.
\- `metadata` — JSON attached to the session for your own reporting.

\## Webhook events for KYB

\| Event | Trigger |
\|---|---|
\| `status.updated` (with `session_kind === "business"`) | KYB session status changed. Follow this event for progress. |
\| `data.updated` (with `session_kind === "business"`) | A reviewer edited registry data or Key People in the console, or the registry reported a change (registry monitoring). Not sent for document uploads or Key People submissions. |
\| `business.status.updated` | Linked Business entity status changed |
\| `business.data.updated` | Linked Business entity profile / counters changed |

Subscribe via `POST /v3/webhook/destinations/` with `webhook_version: "v3"`. Verify the `X-Signature-V2` header (HMAC-SHA256 of canonical JSON). De-dupe on `event_id`. Respond within 5 seconds.

\## KYB decision shape (V3 plural arrays)

\```bash
curl https://verification.didit.me/v3/session/$SESSION_ID/decision/ \
-H "x-api-key: $DIDIT_API_KEY"
\```

Key V3 arrays you'll iterate:

\| Array | Holds |
\|---|---|
\| `key_people_checks[]` | UBOs, shareholders, directors, officers — bucketed into `registry` (from the registry lookup) and `submitted` (what the business confirmed). Plus a `ubo_kyc_summary` rollup. |
\| `document_verifications[]` | Each item has `status`, `node_id`, `items[]` (signed `file_url` + OCR extract), `groups`, `required_groups`. |
\| `aml_screenings[]` | Company AML and per-person AML hits. |

The KYB-specific features are `KYB_REGISTRY`, `AML`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`. Statuses are the exact labels `"Not Finished"`, `"Approved"`, `"Declined"`, `"In Review"`, `"Resub Requested"`.

\## Apply-decision logic

\```ts
switch (decision.status) {
case "Approved":   await onboardBusiness(decision); break;
case "Declined":   await logRejection(collectWarnings(decision), decision); break; // warnings[] tags on each feature array
case "In Review":  await markPending(decision); break; // wait for next webhook
case "Resubmitted":await notifyBusiness(decision); break; // business needs to re-upload
case "Awaiting User": await pingChildPersonForKyc(decision); break; // child Key People KYC pending
}
\```

See /business-verification/statuses for the full state machine.

\## Resubmission flow

When a session transitions to `Resubmitted` (or a feature to `Resub Requested`, or a feature is marked for resubmission), re-deliver the same `url` — the hosted flow resumes at the resubmission step. To re-verify a specific Key Person, resubmit that person's child KYC session; the parent `kyb_key_people` re-aggregates automatically.

\## Key People child KYC

If your KYB workflow has KYC required for some roles, each person triggers a child KYC session automatically. While any child is in progress, the parent's `kyb_key_people` status is `Awaiting User`. Configure per-role required/skippable behaviour at *Workflows → [KYB workflow] → Key People*. A child session expires after the session expiration time of the KYC workflow its role is mapped to, not the KYB session's. A party whose session was deleted, or whose link expired before the person started it, is reissued with `POST /v3/session/{session_id}/kyb/parties/{party_uuid}/regenerate/`.

\## Failure modes

\| Scenario | Response |
\|---|---|
\| Invalid `workflow_id` | `400 Bad Request` |
\| Wrong workflow type (KYC instead of KYB) | Session is created but runs KYC steps — verify the workflow's `workflow_type` is `"kyb"` |
\| Duplicate `vendor_data` | A new session is created — that's by design for re-KYB |
\| Company country outside the workflow's allowed countries | The registry check raises the `KYB_COUNTRY_RESTRICTED` warning |
\| Registry provider outage during company search | `502` with `code: "kyb_registry_provider_unavailable"`. Not billed. In Didit's hosted flow, the business is automatically offered manual company entry instead of a retry-only error. |
\| Rate limit | `429` with `Retry-After` header |

\## Sources of truth

\- /sessions-api/create-session — request body schema
\- /business-verification/response-schema — KYB decision payload
\- /business-verification/statuses — feature state machine
\- /business-verification/webhooks — KYB-specific event catalog
\- /entities/businesses/data-model — Business entity schema
\- /integration/integration-prompt — canonical end-to-end prompt````

\</pre>



      
      

Tempel ke

Panduan ini merupakan pelengkap untuk [quickstart](https://docs.didit.me/id/business-verification/quickstart.md). Panduan ini membahas arsitektur, setiap keputusan integrasi, serta pola operasional yang membuat KYB dapat diandalkan di lingkungan produksi.## Arsitektur```mermaid theme={null}
sequenceDiagram
    participant You as Your platform
    participant Didit as Didit API
    participant Biz as Business contact
    participant Webhook as Your webhook endpoint

    You->>Didit: POST /v3/session/ (workflow_id, vendor_data)
    Didit-->>You: session_id, url, token
    You->>Biz: Deliver hosted verification URL (your email/flow)
    Biz->>Didit: Completes KYB hosted flow
    Didit->>Didit: Registry lookup, AML screening, OCR
    Didit->>Webhook: status.updated (session_kind: business)
    You->>Didit: GET /v3/session/{id}/decision/
    Didit-->>You: Full KYB decision payload
    You->>You: Onboard / reject / escalate based on status
```## AutentikasiSemua permintaan memerlukan header `x-api-key` dengan kunci API aplikasi Anda. Lihat [autentikasi API](https://docs.didit.me/id/getting-started/api-authentication.md) untuk rotasi kunci, pemisahan lingkungan, dan cakupan.## Pembuatan sesiEndpoint tunggal: `POST /v3/session/`. Tipe alur kerja menentukan apakah sesi tersebut berupa KYC atau KYB — tidak diperlukan tanda "business" eksplisit.**Kolom yang disarankan saat pembuatan:**| Kolom | Tujuan |
| - | - |
| `workflow_id` | Wajib — mereferensikan alur kerja KYB Anda. |
| `vendor_data` | Pengidentifikasi bisnis Anda. Menautkan sesi ke sebuah [entitas Bisnis](https://docs.didit.me/id/entities/businesses/overview.md). |
| `callback_url` | Opsional — tujuan pengalihan pengguna setelah selesai. |
| `expected_details` | Opsional — `{ company_name, registry_country, registration_number }`. Mengisi awal pencarian registri perusahaan: negara tempat perusahaan didirikan telah dipilih sebelumnya dan terkunci (`registry_country` sebagai `XX`, atau `XX-YY` untuk registri tingkat negara bagian, mis. `US-CA`), kolom nama perusahaan dan nomor registrasi diisi otomatis, serta pencarian berdasarkan data yang diberikan berjalan secara otomatis — menggabungkan kedua pengidentifikasi saat keduanya tersedia. Hanya pengisian awal — ketidakcocokan tidak memunculkan peringatan. |
| `metadata` | JSON opsional yang dilampirkan ke sesi. |Skema lengkap: [buat sesi](https://docs.didit.me/id/sessions-api/create-session.md).## Mengirimkan tautan yang di-hosting`url` respons berupa tautan verifikasi yang di-hosting. Pilihan untuk pengiriman:- Kirimkan melalui email dari platform Anda sendiri.
- Sematkan pada UI onboarding Anda sebagai tautan.
- Buka di webview dalam aplikasi (iOS / Android / React Native).Anda dapat **menyesuaikan** pengalaman yang di-hosting — logo, warna, domain, templat email — melalui [White Label](https://docs.didit.me/id/console/white-label.md).## Polling vs webhookWebhook merupakan pola yang direkomendasikan. Didit mengirimkan event penyelesaian melalui POST ke endpoint langganan Anda segera setelah pemrosesan selesai.Polling didukung untuk pengembangan atau ketika endpoint webhook Anda tidak dapat dijangkau:* Lakukan polling ke `GET /v3/session/{id}/decision/` dengan backoff eksponensial (awalnya setiap 10 detik, hingga 60 detik).
* Hentikan polling jika `status` adalah salah satu dari `"Approved"`, `"Declined"`, `"In Review"`.> [!WARNING]
>
> Melakukan polling dengan frekuensi tinggi dapat terkena [batas laju](https://docs.didit.me/id/integration/rate-limiting.md). Selalu prioritaskan webhook di lingkungan produksi.## Penanganan webhookBerlanggananlah ke event yang Anda perlukan — event yang sama mencakup KYC dan KYB, dengan `session_kind: "business"` di dalam payload untuk mengidentifikasi event sesi bisnis:- `status.updated` — status sesi berubah. Filter pada `session_kind === "business"` untuk sesi KYB.
- `data.updated` — peninjau mengedit data registri atau Pihak Kunci di konsol, atau registri melaporkan adanya perubahan. Ini tidak dikirimkan ketika pemohon mengunggah dokumen atau mengirimkan Pihak Kunci: pantau `status.updated` untuk hal tersebut. Filter `session_kind` yang sama berlaku.
- `business.status.updated` / `business.data.updated` — [entitas Bisnis](https://docs.didit.me/id/entities/businesses/overview.md) yang ditautkan berubah.Katalog event lengkap: [webhook KYB](https://docs.didit.me/id/business-verification/webhooks.md). Verifikasi tanda tangan dan semantik percobaan ulang: [referensi webhook](https://docs.didit.me/id/integration/webhooks.md).## Menangani keputusan```typescript theme={null}
switch (decision.status) {
  case 'Approved':
    await onboardBusiness(decision);
    break;
  case 'Declined':
    // The KYB decision has no single reason code: collectWarnings is your helper
    // that flattens warnings[] from registry_checks, document_verifications,
    // key_people_checks and aml_screenings
    await logRejection(collectWarnings(decision), decision);
    break;
  case 'In Review':
    // Wait for analyst decision — another webhook will fire
    await markPending(decision);
    break;
  case 'Resubmitted':
    // The business was asked to re-upload a document
    await notifyBusiness(decision);
    break;
}
```Lihat [status KYB](https://docs.didit.me/id/business-verification/statuses.md) untuk mesin status lengkap, dan [peringatan KYB](https://docs.didit.me/id/business-verification/warnings.md) untuk tag yang menjelaskan keputusan.## Alur pengiriman ulangKetika sesi Verifikasi Bisnis (KYB) bertransisi ke `Resubmitted` (atau suatu fitur ditandai untuk pengiriman ulang), bisnis tersebut perlu mengunggah data yang telah diperbaiki atau data tambahan.Anda dapat:- **Mengirimkan kembali** `url` yang sama — alur yang di-hosting akan melanjutkan ke bagian yang memerlukan pengiriman ulang.
- **Menerbitkan ulang tautan pihak kunci yang tidak aktif** — pihak yang sesi KYC anaknya dihapus atau kedaluwarsa sebelum pihak tersebut memulainya, mendapatkan sesi baru dengan [Regenerate Key People KYC Session](https://docs.didit.me/id/sessions-api/regenerate-kyb-party.md).
- **Membuka [kasus](https://docs.didit.me/id/transaction-monitoring/cases.md)** di Business Console untuk melacak komunikasi bolak-balik secara internal.## Menjalankan langkah-langkah dari frontend Anda sendiriLangkah dokumen dan Pihak Kunci juga dapat dijalankan dari server Anda dengan kunci API Anda, sehingga Anda tetap mempertahankan antarmuka pengguna sementara Didit menangani verifikasi dan keputusannya.
Setiap panggilan terkait dengan sesi KYB, memerlukan izin `write:businesses` (membaca pihak yang diekstrak juga dapat menggunakan `read:businesses` atau `read:sessions`), serta menjalankan pemeriksaan, penagihan, dan kemajuan ke langkah berikutnya dengan cara yang sama seperti halaman yang di-hosting.1) [Unggah dokumen perusahaan](https://docs.didit.me/id/sessions-api/kyb-upload-documents.md) saat sesi berada pada langkah Dokumen KYB.
2) [Baca pihak-pihak yang tercantum dalam dokumen](https://docs.didit.me/id/sessions-api/kyb-extracted-parties.md), termasuk pemegang saham dan persentase kepemilikan, lalu tampilkan kepada pemohon Anda.
3) [Buat](https://docs.didit.me/id/sessions-api/kyb-create-party-draft.md), [edit](https://docs.didit.me/id/sessions-api/kyb-update-party-draft.md), dan [hapus](https://docs.didit.me/id/sessions-api/kyb-delete-party-draft.md) [draf pihak](https://docs.didit.me/id/sessions-api/kyb-list-party-drafts.md). Draf belum dideklarasikan dan tidak dikenakan biaya.
4) [Kirim draf tersebut](https://docs.didit.me/id/sessions-api/kyb-submit-parties.md). Didit menentukan pihak mana yang harus diverifikasi, membuat sesi KYC untuk masing-masing pihak, dan mengembalikan `kyc_session_url` untuk Anda kirimkan atau sematkan.
5) Baca keputusan terkonsolidasi dari sesi, sama seperti alur yang di-hosting.Panggilan yang dilakukan saat sesi berada pada langkah lain akan menghasilkan respons `409 kyb_step_mismatch` beserta informasi langkah yang sedang aktif, dan sesi yang telah selesai akan menghasilkan respons `409 kyb_session_not_writable`.## Agregasi profil bisnisJika Anda meneruskan `vendor_data` pada saat pembuatan sesi, Didit mengagregasikan semua sesi untuk bisnis tersebut ke dalam satu [entitas Bisnis](https://docs.didit.me/id/entities/businesses/overview.md). Gunakan pemetaan `features` entitas untuk menjawab "apakah bisnis ini sudah diverifikasi sepenuhnya saat ini?" tanpa perlu mengiterasi sesi.Manfaat:- Alur re-KYB berkala ditambahkan ke profil yang sama.
- Transaksi yang dipantau terhadap `vendor_data` yang sama membawa konteks risiko bisnis tersebut.
- UBO dan pengurus yang ditautkan ke entitas Pengguna akan mengisi relasi lintas entitas.## Praktik terbaik| Praktik | Mengapa |
| - | - |
| Selalu teruskan `vendor_data` | Tanpa parameter ini, sesi menjadi tidak terkait dan tidak dapat diagregasikan. |
| Gunakan webhook, bukan polling | Latensi lebih rendah, tidak menekan batas laju. |
| Verifikasi tanda tangan webhook | Mencegah event yang dipalsukan. |
| Simpan `session_id` di sisi Anda | Diperlukan untuk mengambil keputusan dan menghasilkan PDF. |
| Tandai sesi dengan `metadata` | Menyederhanakan pelaporan dan penelusuran kesalahan. |
| Siapkan alur kerja pengujian | Gunakan alur kerja sandbox untuk pengujian integrasi sebelum produksi. |## Penanganan kesalahan| Skenario | Respons |
| - | - |
| `workflow_id` tidak valid | `400 Bad Request` |
| Sesi duplikat dengan `vendor_data` yang sama | Membuat sesi baru — ini memang sengaja dirancang demikian, karena verifikasi ulang diperkirakan terjadi. |
| Negara perusahaan di luar negara yang diizinkan dalam alur kerja | Pemeriksaan registri memunculkan peringatan `KYB_COUNTRY_RESTRICTED`. |
| Gangguan penyedia registri selama pencarian perusahaan | `POST /v3/kyb/search/` mengembalikan `502` dengan `code: "kyb_registry_provider_unavailable"`. Tidak ditagih - coba lagi, atau buat percabangan berdasarkan `code` untuk menawarkan input manual perusahaan. Dalam alur yang di-hosting Didit, bisnis diarahkan ke input manual secara otomatis alih-alih kesalahan yang hanya mengharuskan percobaan ulang. Lihat [Pencarian Registri KYB](https://docs.didit.me/id/standalone-apis/kyb-registry-search.md#menangani-gangguan-registri). |
| Batas laju | `429 Too Many Requests` dengan header `Retry-After`. |Referensi [batas laju](https://docs.didit.me/id/integration/rate-limiting.md) lengkap.## Langkah berikutnya> [card] [Webhook](https://docs.didit.me/id/business-verification/webhooks.md)
>
> Setiap event dan payload KYB.> [card] [Status](https://docs.didit.me/id/business-verification/statuses.md)
>
> Referensi mesin status.> [card] [Skema respons](https://docs.didit.me/id/business-verification/response-schema.md)
>
> Mendekode keputusan KYB.


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