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

# SDK Verifikasi Identitas JavaScript: KYC Web

> SDK JavaScript dari Didit untuk KYC, KYB, AML, dan liveness biometrik. Embedded, redirect, atau iframe. Mulai $0.33/KYC, gratis $10/bulan, tanpa kontrak.



Prompt Integrasi SDK JavaScript
        Salin prompt ke papan klip



      
      

\<pre>

\`Integrate Didit identity verification into my web application using the JavaScript SDK.

\## Setup
Install: npm install @didit-protocol/sdk-web
Or CDN: <script src="https://unpkg.com/@didit-protocol/sdk-web/dist/didit-sdk.umd.min.js"></script>

\## Integration Flow
1\. (Option A — UniLink) Use a fixed UniLink URL from the Didit Console (no backend needed)
2\. (Option B — API session) Backend creates a session via POST /v3/session/ → 201 response includes "url"
3\. Frontend calls DiditSdk.shared.startVerification({ url }) — the SDK opens a modal (or inline if embedded mode)
4\. On completion, the SDK invokes DiditSdk.shared.onComplete(result) with type "completed" | "cancelled" | "failed"
5\. Backend receives full signed decision via webhook (status.updated)

\## Frontend Code — Vanilla JS / TypeScript
import { DiditSdk } from '@didit-protocol/sdk-web';

DiditSdk.shared.onComplete = (result) => {
switch (result.type) {
case 'completed':
  // result.session.status: "Approved" | "Pending" | "Declined"
  console.log('Done:', result.session.sessionId, result.session.status);
  break;
case 'cancelled':
  console.log('User cancelled');
  break;
case 'failed':
  console.error('Failed:', result.error.type, result.error.message);
  break;
}
};

// Modal mode (default)
DiditSdk.shared.startVerification({
url: 'https://verify.didit.me/session/SESSION_TOKEN' // from backend OR UniLink
});

// Inline / embedded mode
DiditSdk.shared.startVerification({
url: 'https://verify.didit.me/session/SESSION_TOKEN',
configuration: { embedded: true, embeddedContainerId: 'didit-container' }
});

\## Frontend Code — React
function VerifyButton({ userId }) {
const [loading, setLoading] = useState(false);

async function handleVerify() {
setLoading(true);
const res = await fetch('/api/create-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ user_id: userId })
});
const { url } = await res.json(); // OpenAPI field is named "url"

const { DiditSdk } = await import('@didit-protocol/sdk-web');
DiditSdk.shared.onComplete = (result) => {
  if (result.type === 'completed') {
    // update UI; final, signed result arrives on backend via webhook
  }
  setLoading(false);
};
DiditSdk.shared.startVerification({ url });
}

return <button onClick={handleVerify} disabled={loading}>Verify Identity</button>;
}

\## Backend: Create Session
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "callback": "https://myapp.com/done", "vendor_data": userId }
Returns 201 (all 10 fields, per OpenAPI):
\{
"session_id": "uuid",
"session_number": 43762,
"session_token": "3FaJ9wLqX2Mz",   // 12-char URL-safe token; valid until the session expires
"url": "https://verify.didit.me/session/3FaJ9wLqX2Mz",
"vendor_data": "userId",
"metadata": null,
"status": "Not Started",
"workflow_id": "uuid",
"workflow_version": 3,
"callback": "https://myapp.com/done"
}
Pass the "url" field to DiditSdk.shared.startVerification({ url }) — never build the URL by hand.
(If the request sets "language", the URL gains a language segment: https://verify.didit.me/es/session/...)

\## SDK Surface (singleton — DiditSdk.shared)
Methods:  startVerification(options), close(), destroy()
Callbacks: onComplete(result), onStateChange(state, error?), onEvent(event)
State enum: 'idle' | 'loading' | 'ready' | 'error'

\## Rate Limits
600 session-create requests per minute per API key (falls back to bearer token, then client IP), plus a shared budget of 300 write (POST/PATCH/DELETE) requests per minute across all endpoints — the 300/min budget is exhausted first. Exceeding either returns HTTP 429 with Retry-After.

\## Environment Variables
\- DIDIT_API_KEY — backend only (Didit Console > API & Webhooks)
\- DIDIT_WORKFLOW_ID — backend only (Didit Console > Workflows)
\- Never expose the API key on the frontend — the session_token embedded in "url" is the only credential the SDK needs. It grants access to that one session's flow (valid until the session expires), so don't log or share it either.

\## Docs
\- JavaScript SDK: https://docs.didit.me/integration/web-sdks/javascript-sdk
\- Create Session API: https://docs.didit.me/sessions-api/create-session
\- Webhooks: https://docs.didit.me/integration/webhooks`

\</pre>



      
      

Tempel ke

SDK JavaScript Didit menyediakan cara terprogram untuk mengintegrasikan verifikasi ke aplikasi web Anda dengan kendali penuh atas pengalaman pengguna.***## Fitur- **API Sederhana** - Pola singleton dengan metode yang mudah digunakan
- **Integrasi Fleksibel** - Gunakan URL UniLink secara langsung atau buat sesi melalui backend
- **Responsif** - Berfungsi di browser desktop dan seluler
- **Dapat Dikustomisasi** - Opsi konfigurasi untuk gaya dan perilaku
- **Berbagai Format** - Build dalam format ESM, CommonJS, dan UMD
- **Dukungan TypeScript** - Definisi tipe lengkap disertakan
- **Mode Modal & Inline** - Pilih antara overlay modal atau embedding inline
- **Callback Event** - Event real-time untuk progres verifikasi (dimulai, langkah selesai, selesai)
- **Manajemen State** - Amati state SDK untuk UI kustom***## Instalasi### NPM/Yarn```bash theme={null}
npm install @didit-protocol/sdk-web
# or
yarn add @didit-protocol/sdk-web
```### CDN (UMD)```html theme={null}
<script src="https://unpkg.com/@didit-protocol/sdk-web/dist/didit-sdk.umd.min.js"></script>
```> [!NOTE]
>
> Rilis npm terbaru yang dipublikasikan adalah `0.5.1`.
> `0.5.0` menambahkan `DiditSdk.shared.submitEvent()` (lihat [Kirim event](#kirim-event)), dan `0.5.1` memungkinkan alur verifikasi yang di-hosting meminta ID pengguna dari dompet ID digital di dalam SDK, serta menetapkan peluncuran yang gagal ke status `error` dengan `errorMessage`-nya.
> `0.4.0` menambahkan opsi kamera yang sudah tersedia di SDK native, termasuk `defaultLivenessCamera`, yang membuka pengambilan wajah dengan kamera belakang (lihat [Opsi kamera](#opsi-kamera)).### Periksa versi yang terpasangManajer paket Anda tetap menjadi acuan utama untuk rilis yang terpasang:```bash theme={null}
npm list @didit-protocol/sdk-web
npm view @didit-protocol/sdk-web version
```Anda juga dapat memeriksa ekspor runtime:```typescript theme={null}
const { SDK_VERSION } = await import('@didit-protocol/sdk-web');

console.log(SDK_VERSION);
```Mulai dari `0.3.1`, ekspor ini dihasilkan dari versi paket di setiap format JavaScript (ESM, CommonJS, UMD, UMD yang diminifikasi) dan di deklarasi TypeScript, sehingga selalu sesuai dengan rilis yang terpasang.`0.3.0` dan sebelumnya melaporkan `0.2.1` dari ekspor ini, terlepas dari versi yang terpasang. Pada rilis tersebut, gunakan `npm list` atau lockfile Anda sebagai gantinya.***## JavaScript Murni### ES Modules / TypeScript```typescript theme={null}
import { DiditSdk } from '@didit-protocol/sdk-web';

// Set up completion callback
DiditSdk.shared.onComplete = (result) => {
  switch (result.type) {
    case 'completed':
      console.log('Verification completed!');
      console.log('Session ID:', result.session?.sessionId);
      console.log('Status:', result.session?.status);
      break;
    case 'cancelled':
      console.log('User cancelled verification');
      break;
    case 'failed':
      console.error('Verification failed:', result.error?.message);
      break;
  }
};

// Start verification with the `url` returned by POST /v3/session/ (or your UniLink)
DiditSdk.shared.startVerification({
  url: 'https://verify.didit.me/session/3FaJ9wLqX2Mz'
});
```### Tag Skrip (UMD)```html theme={null}
<script src="https://unpkg.com/@didit-protocol/sdk-web/dist/didit-sdk.umd.min.js"></script>
<script>
  const { DiditSdk } = DiditSDK;

  DiditSdk.shared.onComplete = (result) => {
    if (result.type === 'completed') {
      alert('Verification completed: ' + result.session.status);
    }
  };

  function startVerification() {
    DiditSdk.shared.startVerification({
      // You can get this link by clicking on "copy link" in the workflows view
      url: 'https://verify.didit.me/u/WORKFLOW_ID_IN_BASE_64'
    });
  }
</script>

<button onclick="startVerification()">Verify Identity</button>
```***## Contoh Framework> [card] [Contoh Web SDK](https://github.com/didit-protocol/sdk-web-examples)
>
> React, Angular, Svelte, Next.js, Nuxt, Vue, dan lainnya, dengan contoh dan dokumentasi untuk setiap framework.***## Metode IntegrasiAda dua cara untuk mengintegrasikan SDK:### Metode 1: URL UniLink (Paling Sederhana)Gunakan URL UniLink alur kerja Anda langsung dari Didit Console. Tidak diperlukan backend.```typescript theme={null}
DiditSdk.shared.startVerification({
  // You can get this link by clicking on "copy link" in the workflows view
  url: 'https://verify.didit.me/u/WORKFLOW_ID_IN_BASE_64'
});
```Dapatkan URL UniLink Anda dari [Didit Console](https://business.didit.me) → Alur Kerja Anda → Salin Tautan.**session\_id yang dihasilkan akan dikirimkan kepada Anda melalui sebuah event.**
**[Lihat referensi event di sini](#referensi-event)**### Metode 2: Sesi backend (direkomendasikan untuk produksi)Backend Anda membuat sesi melalui Didit API dan mengembalikan URL verifikasi yang di-hosting. Dengan cara ini, Anda memiliki kendali atas `vendor_data`, `callback` per sesi, dan `metadata`, serta dapat membuat sesi sebelum pengguna membuka frontend.Baca selengkapnya di [referensi API Create Session](https://docs.didit.me/id/sessions-api/create-session.md).**Backend (Node.js / Express)**```javascript theme={null}
import express from 'express';
const app = express();
app.use(express.json());

app.post('/api/create-session', async (req, res) => {
  const response = await fetch('https://verification.didit.me/v3/session/', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.DIDIT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: req.body.userId,             // links the session to your user
      callback: 'https://yourapp.com/verified', // optional — overrides workflow default
    }),
  });

  if (!response.ok) {
    return res.status(response.status).send(await response.text());
  }

  // 201 response fields (per OpenAPI): session_id, session_number, session_token, url,
  // vendor_data, metadata, status, workflow_id, workflow_version, callback
  const session = await response.json();
  res.json({ session_id: session.session_id, url: session.url });
});
```**Frontend**```typescript theme={null}
import { DiditSdk } from '@didit-protocol/sdk-web';

const res = await fetch('/api/create-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ userId: 'user-123' }),
});
const { url } = await res.json();

DiditSdk.shared.startVerification({
  url,
  configuration: {
    loggingEnabled: true,
  },
});
```> [!NOTE]
>
> Kolom respons pembuatan sesi bernama `url` (lihat [skema OpenAPI Create Session](https://docs.didit.me/id/sessions-api/create-session.md)). Teruskan langsung ke `startVerification({ url })`.***## Konfigurasi| Opsi | Tipe | Bawaan | Deskripsi |
| - | - | - | - |
| `loggingEnabled` | `boolean` | `false` | Aktifkan logging SDK untuk debugging |
| `containerElement` | `HTMLElement` | `document.body` | Elemen container kustom untuk memasang modal |
| `zIndex` | `number` | `9999` | Z-index untuk overlay modal |
| `showCloseButton` | `boolean` | `true` | Tampilkan tombol tutup pada modal |
| `showExitConfirmation` | `boolean` | `true` | Tampilkan dialog konfirmasi saat modal ditutup |
| `closeModalOnComplete` | `boolean` | `false` | Tutup modal secara otomatis saat verifikasi selesai |
| `embedded` | `boolean` | `false` | Tampilkan verifikasi secara inline, bukan sebagai overlay modal |
| `embeddedContainerId` | `string` | - | ID elemen container untuk mode embedded (wajib jika `embedded` bernilai `true`) |
| `defaultDocumentCamera` | `'front' \| 'back'` | `'back'` | Kamera yang digunakan pertama kali untuk pengambilan dokumen. Lihat [Opsi kamera](#opsi-kamera) |
| `defaultLivenessCamera` | `'front' \| 'back'` | `'front'` | Kamera yang digunakan pertama kali untuk pengambilan wajah (liveness). Lihat [Opsi kamera](#opsi-kamera) |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | Tampilkan tombol pengalih kamera selama pengambilan pada langkah dokumen |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | Tampilkan tombol pengalih kamera selama pengambilan pada langkah liveness |> [!TIP]
>
> Lihat [definisi tipe TypeScript](#tipe-typescript) lengkap di bawah untuk antarmuka `DiditSdkConfiguration`.***## Opsi kamera> [!NOTE]
>
> Opsi kamera memerlukan `@didit-protocol/sdk-web`**0.4.0** atau yang lebih baru.SDK web menyediakan empat opsi kamera yang sama seperti [SDK native](https://docs.didit.me/id/integration/native-sdks/overview.md). Secara default, pengambilan dokumen membuka kamera belakang dan pengambilan wajah (liveness) membuka kamera depan (swafoto). Kedua langkah juga menyediakan tombol pergantian kamera di dalam pengambilan, pada perangkat yang memiliki lebih dari satu kamera. Atur `defaultLivenessCamera: 'back'` untuk membuka pengambilan wajah dengan kamera belakang, misalnya di kiosk atau saat operator memegang perangkat dan mengarahkannya ke orang yang sedang diverifikasi.| Opsi | Tipe | Default | Deskripsi |
| - | - | - | - |
| `defaultDocumentCamera` | `'front' \| 'back'` | `'back'` | Lensa yang digunakan saat pertama kali masuk ke layar pengambilan dokumen |
| `defaultLivenessCamera` | `'front' \| 'back'` | `'front'` | Lensa yang digunakan saat pertama kali masuk ke layar pengambilan liveness (wajah pasif) |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | Menampilkan tombol pergantian kamera di dalam pengambilan pada layar dokumen; `false` mengunci pengguna ke `defaultDocumentCamera` |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | Menampilkan tombol pergantian kamera di dalam pengambilan pada layar liveness; `false` mengunci pengguna ke `defaultLivenessCamera` |```typescript theme={null}
// A kiosk: the operator points the device at the person, on the rear camera, with no way to switch
DiditSdk.shared.startVerification({
  url,
  configuration: {
    defaultLivenessCamera: 'back',
    showLivenessCameraSwitchButton: false
  }
});
```- Nilai lensa yang diterima adalah `'front'` dan `'back'`. Nilai lain akan diabaikan, begitu juga flag tombol pergantian yang bukan boolean.
- Jika perangkat tidak memiliki kamera yang diminta, perangkat akan tetap menggunakan kamera yang dimilikinya. Laptop yang diminta `'back'` tetap menggunakan webcam-nya. Tombol pergantian disembunyikan pada perangkat berkamera tunggal, apa pun nilai flag-nya.
- Opsi liveness berlaku untuk pemeriksaan liveness pasif. Liveness aktif tidak terpengaruh.
- SDK meneruskan opsi ke halaman verifikasi sebagai parameter kueri pada URL verifikasi: `document_camera`, `liveness_camera`, `document_camera_switch`, dan `liveness_camera_switch`. Jika Anda membuka URL verifikasi secara langsung, bukan melalui SDK, atur parameter tersebut sendiri: tambahkan `?liveness_camera=back` ke URL tanpa string kueri, `&liveness_camera=back` ke URL yang sudah memiliki parameter, atau atur dengan API `URL` agar kedua kasus tertangani:```typescript theme={null}
const verificationUrl = new URL(url);
verificationUrl.searchParams.set('liveness_camera', 'back');
verificationUrl.searchParams.set('liveness_camera_switch', 'false');
window.location.assign(verificationUrl.toString());
```***## Kirim event`DiditSdk.shared.submitEvent()` memasukkan event pengguna akhir (pendaftaran, login, login gagal, logout, reset kata sandi, MFA, perubahan perangkat) ke antrean untuk pemantauan event Didit.
Backend Anda membuat token pemantauan untuk orang tersebut, lalu SDK mengirim event dalam batch beserta sidik jari perangkat.
Jangan pernah mengirim kunci API ke peramban.```typescript theme={null}
DiditSdk.shared.submitEvent({
  monitoringToken, // minted by your backend for this person
  event: { category: "auth", actionType: "login", payload: { method: "password" } },
});
```Lihat [pengiriman event SDK](https://docs.didit.me/id/transaction-monitoring/sdk-event-submission.md) untuk token, kolom event, dan perilaku pengirimannya.***## Ukuran dan pengguliran modal> [!NOTE]
>
> Perilaku ukuran di bawah ini memerlukan **0.3.1** atau yang lebih baru. **0.3.0** dan versi sebelumnya dapat memotong alur verifikasi pada viewport desktop dan lanskap yang pendek.Mode modal menggunakan lebar maksimum 500px dan tinggi maksimum 700px. Pada viewport desktop dan lanskap yang lebih pendek, iframe mengikuti 90% dari viewport yang terlihat. Alur verifikasi digulir di dalam iframe, sehingga setiap langkah tetap dapat dijangkau sementara halaman di belakang modal tetap terkunci.SDK menggunakan `dvh` pada peramban yang mendukung unit viewport dinamis dan beralih ke `vh` pada peramban lama yang masih didukung. Pada lebar 540px atau kurang, modal memenuhi viewport yang terlihat. Tombol tutup dan konfirmasi keluar tetap berada di dalam modal.### Alur verifikasi yang didesain ulang> [!NOTE]
>
> Semua isi bagian ini berlaku mulai versi **0.5.0**, yang belum dirilis. Sampai Anda memperbarui ke versi tersebut, modal tetap menggunakan ukuran yang dijelaskan di atas.Mulai versi 0.5.0, modal menyesuaikan ukurannya dengan alur verifikasi yang didesain ulang setelah halaman melaporkan tata letaknya melalui [pesan `didit:layout`](https://docs.didit.me/id/integration/web-sdks/incontext-iframe#atur-ukuran-iframe-dari-diditlayout):| Lebar jendela | Modal (mulai versi 0.5.0) |
| - | - |
| 1024px ke atas | 960px x 660px di setiap langkah, paling besar 90% dari lebar dan tinggi jendela |
| 541px sampai 1023px | Lebar 500px dan setinggi konten halaman, paling besar 90% dari tinggi jendela |
| 540px ke bawah | Layar penuh |- **Ukuran awal, mulai versi 0.5.0:** sampai halaman melaporkan tata letaknya, dan untuk halaman yang tidak pernah melaporkannya, modal tetap menggunakan ukuran maksimum yang ada, yaitu 500px x 700px. Ukuran ini tetap pas di jendela yang pendek dan tetap layar penuh pada 540px ke bawah.
- **Tombol tutup, mulai versi 0.5.0:** lingkaran berukuran 44px di atas bilah atas halaman. Tombol ini mengikuti tema terang atau gelap pada halaman dan berpindah ke kiri pada bahasa yang ditulis dari kanan ke kiri.
- **Mode embedded, mulai versi 0.5.0:** tetap memenuhi elemen host-nya, seperti sebelumnya (lihat [Mode embedded](#mode-embedded)).
- **URL verifikasi, mulai versi 0.5.0:** SDK menambahkan `sdk_presentation` (`modal` atau `embedded`) dan, dalam modal, `sdk_close_button` (`true` atau `false`, mengikuti `showCloseButton`), sehingga halaman mengetahui cara halaman tersebut ditampilkan.
- **Event, mulai versi 0.5.0:** SDK menangani `didit:layout` sendiri dan tidak meneruskannya ke `onEvent`.Tidak ada yang perlu dikonfigurasi, dan setiap opsi yang ada tetap berfungsi.***## Mode embeddedMode embedded tidak menggunakan batas 500px x 700px pada modal. SDK mengisi area konten elemen host, sehingga berikan elemen tersebut tinggi eksplisit atau tinggi yang dapat ditentukan dengan cara lain:```html theme={null}
<div id="verification-container" style="width: 500px; height: 700px;"></div>
``````typescript theme={null}
DiditSdk.shared.startVerification({
  url: 'https://verify.didit.me/u/...',
  configuration: {
    embedded: true,
    embeddedContainerId: 'verification-container'
  }
});
```Jika host tidak memiliki tinggi yang dapat ditentukan, iframe embedded juga tidak memiliki tinggi yang dapat dipakai. Ubah ukuran host setiap kali tata letak Anda berubah; SDK akan terus mengisinya secara otomatis.***## Hasil VerifikasiSDK mengembalikan tiga jenis hasil:### SelesaiAlur verifikasi selesai (disetujui, tertunda, atau ditolak).```typescript theme={null}
{
  type: 'completed',
  session: {
    sessionId: 'session-uuid',
    status: 'Approved' | 'Pending' | 'Declined'
  }
}
```> [!NOTE]
>
> Tipe TypeScript mendeklarasikan `'Approved' | 'Pending' | 'Declined'`, tetapi nilainya diteruskan dari status sesi alur yang di-hosting, sehingga Anda juga dapat menerima status lain, seperti `In Review`. `Pending` adalah nilai cadangan SDK saat alur tidak melaporkan status apa pun. Perlakukan `status` sebagai petunjuk, dan andalkan [webhook](https://docs.didit.me/id/integration/webhooks.md) untuk keputusan final.### DibatalkanPengguna menutup modal verifikasi. `session` disertakan jika `sessionId` sudah diketahui sebelumnya (nilainya bisa `undefined` jika pengguna membatalkan sebelum iframe melaporkannya).```typescript theme={null}
{
  type: 'cancelled',
  session: {
    sessionId: 'session-uuid',
    status: 'Pending'
  }
}
```### GagalTerjadi error selama verifikasi.```typescript theme={null}
{
  type: 'failed',
  error: {
    type: 'sessionExpired' | 'networkError' | 'cameraAccessDenied' | 'unknown',
    message: 'Your verification session has expired.'
  }
}
```***## Pengelolaan StateAnda dapat memantau state SDK untuk UI kustom:```typescript theme={null}
DiditSdk.shared.onStateChange = (state, error) => {
  switch (state) {
    case 'idle':
      // Ready to start
      break;
    case 'loading':
      // Loading verification iframe
      showLoadingSpinner();
      break;
    case 'ready':
      // Verification in progress
      hideLoadingSpinner();
      break;
    case 'error':
      // Error occurred
      showError(error);
      break;
  }
};

// Check current state
console.log(DiditSdk.shared.state);

// Check if verification is presented
console.log(DiditSdk.shared.isPresented);
```***## Referensi API### DiditSdk.sharedInstans SDK singleton.### Metode| Metode | Deskripsi |
| - | - |
| `startVerification(options)` | Memulai alur verifikasi |
| `submitEvent(options)` | Memasukkan peristiwa pengguna akhir ke antrean untuk pemantauan event dengan token pemantauan |
| `close()` | Menutup modal verifikasi secara terprogram |
| `destroy()` | Menghancurkan instans SDK dan membersihkannya |### Properti| Properti | Tipe | Deskripsi |
| - | - | - |
| `state` | `DiditSdkState` | State SDK saat ini |
| `configuration` | `DiditSdkConfiguration \| undefined` | Konfigurasi aktif (ditetapkan selama verifikasi berlangsung) |
| `isPresented` | `boolean` | Apakah modal verifikasi sedang terbuka |
| `errorMessage` | `string \| undefined` | Pesan error (diisi saat state adalah `error`); peluncuran yang gagal tetap berada di `error` sampai Anda memulai lagi |### Callback| Callback | Parameter | Deskripsi |
| - | - | - |
| `onComplete` | `(result: VerificationResult)` | Dipanggil saat verifikasi selesai |
| `onStateChange` | `(state: DiditSdkState, error?: string)` | Dipanggil saat state berubah |
| `onEvent` | `(event: VerificationEvent)` | Dipanggil saat terjadi peristiwa verifikasi terperinci |***## Event TerperinciLacak progres verifikasi dengan callback `onEvent`:```typescript theme={null}
DiditSdk.shared.onEvent = (event) => {
  console.log('Event:', event.type, event.data);
};
```### Referensi Event| Event | Deskripsi | Data Payload |
| - | - | - |
| `didit:ready` | Halaman sudah siap dan sessionId tersedia | `{ sessionId }` |
| `didit:started` | Pengguna memulai verifikasi | `{ sessionId? }` |
| `didit:step_started` | Sebuah langkah verifikasi dimulai | `{ step, sessionId? }` |
| `didit:step_completed` | Sebuah langkah berhasil diselesaikan | `{ step, nextStep?, sessionId? }` |
| `didit:step_changed` | Langkah saat ini berubah | `{ step, previousStep?, sessionId? }` |
| `didit:media_started` | Pengambilan kamera/media dimulai | `{ step, mediaType }` |
| `didit:media_captured` | Foto/video diambil | `{ step, isAuto }` |
| `didit:document_selected` | Pengguna memilih jenis dokumen dan negara | `{ documentType, country }` |
| `didit:verification_submitted` | Data dikirim untuk diproses | `{ step, sessionId? }` |
| `didit:code_sent` | Kode OTP (kode sekali pakai) dikirim | `{ step, channel?, codeSize?, sessionId? }` |
| `didit:code_verified` | Kode OTP (kode sekali pakai) diverifikasi | `{ step, sessionId? }` |
| `didit:status_updated` | Status sesi berubah | `{ status, previousStep?, sessionId? }` |
| `didit:completed` | Alur verifikasi selesai | `{ sessionId?, status?, country?, documentType? }` |
| `didit:cancelled` | Pengguna membatalkan verifikasi | `{ sessionId? }` |
| `didit:error` | Terjadi kesalahan | `{ error: string, step?, sessionId? }` |
| `didit:close_request` | Pengguna meminta untuk menutup modal | (tanpa data) |### Koneksi terputusJika koneksi pengguna terputus, halaman verifikasi menutupi alur dengan layar "Tidak ada koneksi internet", alih-alih membiarkan langkah tetap dimuat.
Halaman terus memeriksa di latar belakang dan menutup layar itu dengan sendirinya begitu Didit dapat dijangkau kembali, lalu pengguna melanjutkan dari langkah yang sedang mereka jalani.
Di dalam modal atau iframe SDK, layar tersebut juga menampilkan **Keluar dari Verifikasi**: halaman kemudian mengirim `didit:error` dengan `error: "network_error"`, diikuti `didit:cancelled`, dan SDK menutup modal serta memanggil `onComplete` dengan `type: "cancelled"`.Mulai versi 0.5.0, pesan `didit:layout` dari halaman mengatur ukuran modal dan tidak diteruskan ke `onEvent`. Jika Anda menanamkan halaman dengan iframe sendiri, lihat [Ukur iframe dari `didit:layout`](https://docs.didit.me/id/integration/web-sdks/incontext-iframe#atur-ukuran-iframe-dari-diditlayout).### Nilai LangkahKolom `step` dapat berisi salah satu nilai berikut:- `document_selection` - Pemilihan jenis dokumen
- `document_front` - Sisi depan dokumen
- `document_back` - Sisi belakang dokumen
- `face` - Verifikasi wajah/Deteksi Liveness
- `email` - Verifikasi email
- `phone` - Verifikasi telepon
- `poa` - Bukti alamat
- `questionnaire` - Langkah kuesioner### Nilai SaluranKolom `channel` pada `code_sent` dapat berisi:- `email` - Kode dikirim melalui email
- `sms` - Kode dikirim melalui SMS
- `whatsapp` - Kode dikirim melalui WhatsApp### Ukuran KodeKolom `codeSize` pada `code_sent` menunjukkan panjang kode OTP (misalnya 4 atau 6 digit).***## Tipe TypeScript```typescript theme={null}
// Configuration types
interface DiditSdkConfiguration {
  /**
   * Enable SDK logging for debugging
   * @default false
   */
  loggingEnabled?: boolean;

  /**
   * Custom container element to mount the modal
   * @default document.body
   */
  containerElement?: HTMLElement;

  /**
   * Z-index for the modal overlay
   * @default 9999
   */
  zIndex?: number;

  /**
   * Show close button on modal
   * @default true
   */
  showCloseButton?: boolean;

  /**
   * Show exit confirmation dialog when closing
   * @default true
   */
  showExitConfirmation?: boolean;

  /**
   * Automatically close modal when verification completes
   * @default false
   */
  closeModalOnComplete?: boolean;

  /**
   * Render verification inline instead of modal overlay
   * @default false
   */
  embedded?: boolean;

  /**
   * Container element ID for embedded mode
   * Required when embedded is true
   */
  embeddedContainerId?: string;

  /**
   * Camera the document capture opens first.
   * @default 'back'
   */
  defaultDocumentCamera?: CameraLens;

  /**
   * Camera the face (liveness) capture opens first.
   * Applies to passive liveness; devices without a rear camera keep the front one.
   * @default 'front'
   */
  defaultLivenessCamera?: CameraLens;

  /**
   * Show the in-capture camera switcher on the document step.
   * false locks the user to defaultDocumentCamera.
   * @default true
   */
  showDocumentCameraSwitchButton?: boolean;

  /**
   * Show the in-capture camera switcher on the liveness step.
   * false locks the user to defaultLivenessCamera.
   * @default true
   */
  showLivenessCameraSwitchButton?: boolean;
}

type CameraLens = 'front' | 'back';

// Session + error types
type VerificationStatus = 'Approved' | 'Pending' | 'Declined';

interface SessionData {
  sessionId: string;
  status: VerificationStatus;
}

type VerificationErrorType =
  | 'sessionExpired'
  | 'networkError'
  | 'cameraAccessDenied'
  | 'unknown';

interface VerificationError {
  type: VerificationErrorType;
  message: string;
}

// Verification result — `session` and `error` are both optional fields
// on every result; which one is populated depends on `type`.
type VerificationResultType = 'completed' | 'cancelled' | 'failed';

interface VerificationResult {
  type: VerificationResultType;
  session?: SessionData;
  error?: VerificationError;
}

// State types
type DiditSdkState = 'idle' | 'loading' | 'ready' | 'error';

// Event types
type VerificationEventType =
  | 'didit:ready'
  | 'didit:started'
  | 'didit:step_started'
  | 'didit:step_completed'
  | 'didit:step_changed'
  | 'didit:media_started'
  | 'didit:media_captured'
  | 'didit:document_selected'
  | 'didit:verification_submitted'
  | 'didit:code_sent'
  | 'didit:code_verified'
  | 'didit:status_updated'
  | 'didit:completed'
  | 'didit:cancelled'
  | 'didit:error'
  | 'didit:close_request';

interface VerificationEventData {
  sessionId?: string;
  status?: string;
  step?: string;
  nextStep?: string;
  previousStep?: string;
  error?: string;
  country?: string;
  documentType?: string;
  isAuto?: boolean;
  mediaType?: string;
  channel?: string;
  codeSize?: number;
  [key: string]: unknown;
}

interface VerificationEvent {
  type: VerificationEventType;
  data?: VerificationEventData;
  timestamp?: number;
}

// Start verification options
interface StartVerificationOptions {
  url: string;
  configuration?: DiditSdkConfiguration;
}
```


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