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

# Verifikasi Identitas Iframe: KYC Web Tertanam

> Tanamkan KYC, KYB, AML, dan liveness di situs Anda via iframe. Sesi UniLink tanpa kode atau API. Mulai $0.33 per KYC penuh, gratis $10/bulan, tanpa kontrak.



Prompt Integrasi Iframe
        Salin prompt ke papan klip



      
      

\<pre>

\`Embed Didit identity verification into my web page using an iframe.

\## Two Options

\### Option A: UniLink (no backend — fastest setup)
Copy your UniLink URL from Didit Console > Workflows > Copy Link.
It looks like: https://verify.didit.me/u/<BASE64_WORKFLOW_ID>
Embed it directly:

\<iframe
src="https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64"
style="width: 100%; height: 700px; border: none; border-radius: 12px;"
allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
/>

No backend needed. Results appear in your Didit Console dashboard.

\### Option B: API session (full control)
1\. Backend creates session: POST /v3/session/ → response includes "url"
2\. Frontend embeds that "url" as the iframe src
3\. Listen for postMessage events from the iframe (event.origin === 'https://verify.didit.me', or your white-label domain)
4\. Backend receives the full, signed decision via webhook (status.updated)

\## postMessage contract (key events — full table below)
Every message is an object: { type: "didit:<event>", data: { ... }, timestamp: <ms epoch> }
Completion event: type === "didit:completed", data: { sessionId, status }
Other events: didit:ready { sessionId }, didit:started, didit:step_started { step },
didit:step_completed { step, nextStep }, didit:step_changed { step, previousStep },
didit:status_updated { status }, didit:error { error, step }, didit:cancelled, didit:close_request,
didit:layout { contentHeight, colorScheme: "light" | "dark", dir: "ltr" | "rtl" }
The payload is NESTED under event.data.data (event.data is the envelope).
For your own iframe, add sdk_presentation=embedded with the URL API to receive didit:layout.

\## Iframe size (redesigned flow)
\- Window 1024px and wider: 960px by 660px (at most 90% of the window)
\- Window 541px to 1023px: 500px wide, height = didit:layout contentHeight (700px until the first message, at most 90% of the window height)
\- Window 540px and below: full screen

\## Frontend Code (Option B — React)
function VerificationIframe({ verificationUrl }) {
useEffect(() => {
function handleMessage(event) {
  if (event.origin !== 'https://verify.didit.me') return; // use your white-label domain if configured
  const { type, data } = event.data || {};
  if (type === 'didit:completed') {
    // data.sessionId, data.status: "Approved" | "Declined" | "In Review" // open string — other session statuses possible in edge flows
    // Trust the webhook on your backend for the canonical decision.
  }
}
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);

return (
\<iframe
  src={verificationUrl}
  style={{ width: '100%', height: '700px', border: 'none', borderRadius: '12px' }}
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
/>
);
}

\## Required client-side permissions
If you front your site with a reverse proxy (nginx, Cloudflare, etc.) make sure it does not
strip the Permissions-Policy / Feature-Policy headers — camera and microphone access must be
allowed for your origin or the iframe will be unable to start the camera.

\## Required iframe Permissions
allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
camera: document and face capture. microphone: optional audio during video capture.
geolocation: the location step. clipboard-write: the copy buttons.
digital-credentials-get: sharing a digital ID from a wallet such as Google Wallet.

\## 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, "vendor_data": userId }
201 response fields (all 10, per OpenAPI):
\{ "session_id", "session_number", "session_token", "url", "vendor_data", "metadata",
"status", "workflow_id", "workflow_version", "callback" }
Use response.url as the iframe src — never build the URL from session_token by hand.

\## Rate Limits
600 session-create requests per minute per API key (falls back to bearer token, then client IP), plus a shared 300 write-requests/minute budget across all endpoints. HTTP 429 with Retry-After when exceeded.

\## Environment Variables
\- DIDIT_API_KEY (backend only)
\- DIDIT_WORKFLOW_ID (backend only)

\## Docs
\- Iframe guide: https://docs.didit.me/integration/web-sdks/incontext-iframe
\- Create Session: https://docs.didit.me/sessions-api/create-session
\- Webhooks: https://docs.didit.me/integration/webhooks`

\</pre>



      
      

Tempel ke

Tanamkan alur verifikasi Didit langsung ke aplikasi Anda menggunakan iframe. Cara ini memberikan pengalaman yang mulus tanpa mengarahkan pengguna keluar dari situs Anda.## Ringkasan| Fitur | UniLink (Tanpa Backend) | Sesi API (Dengan Backend) |
| - | - | - |
| Waktu pengaturan | \< 1 menit | 5-10 menit |
| Backend diperlukan | ❌ Tidak | ✅ Ya |
| `vendor_data` kustom | ❌ Tidak | ✅ Ya |
| `metadata` kustom | ❌ Tidak | ✅ Ya |
| Callback per sesi | ❌ Tidak | ✅ Ya |
| Pelacakan sesi | ❌ Tidak | ✅ Ya |***## Iframe UniLink (Tanpa Backend)Cara tercepat untuk memulai: cukup salin dan tempel URL UniLink Anda.### Yang Anda Perlukan1) Alur kerja Didit (dibuat di [Didit Console](https://business.didit.me))
2) URL UniLink Anda (klik **Copy Link** pada alur kerja Anda)### Implementasi```html theme={null}
<iframe 
  src="https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64"
  style="width: 100%; height: 700px; border: none;" 
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
></iframe>
```> ⚠️ **Wajib**: Atribut `allow` wajib ada agar kamera dapat diakses selama deteksi liveness.### Manfaat Utama- **Pengaturan kurang dari 1 menit**: Tanpa backend, tanpa kunci API
- **Tanpa konfigurasi tambahan**: URL callback diatur di pengaturan alur kerja
- **Ideal untuk MVP**: Langsung bisa digunakan***## Iframe Sesi API (Dengan Backend)Untuk integrasi lanjutan yang memerlukan kustomisasi per sesi.### Kapan Menggunakannya- Mengirim `vendor_data` atau `metadata` kustom per sesi
- Mengatur URL callback yang berbeda per sesi
- Melacak sesi di sisi server sebelum verifikasi dimulai
- Mengaitkan sesi dengan ID pengguna Anda### Implementasi**Langkah 1: Buat sesi (backend)**Respons pembuatan sesi menggunakan kolom bernama **`url`**. Gunakan nilai tersebut sebagai `src` iframe.```javascript theme={null}
// Node.js / Express
app.post('/api/create-verification', async (req, res) => {
  const { userId } = req.body;

  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: userId,
      callback: 'https://yourapp.com/verification-callback',
      metadata: { source: 'web-app', timestamp: Date.now() },
    }),
  });

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

  // 201 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({ sessionId: session.session_id, verificationUrl: session.url });
});
```**Langkah 2: Tanamkan dalam iframe (frontend)**```html theme={null}
<iframe 
  id="didit-verification"
  src="" <!-- Set dynamically from API response -->
  style="width: 100%; height: 650px; border: none;" 
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
></iframe>

<script>
  async function startVerification() {
    const response = await fetch('/api/create-verification', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: 'user-123' })
    });
    
    const { verificationUrl } = await response.json();
    document.getElementById('didit-verification').src = verificationUrl;
  }
</script>
```***## Mendengarkan Event (postMessage)Halaman verifikasi mengirim event ke jendela induk. Setiap pesan memiliki struktur berikut:```typescript theme={null}
{
  type: 'didit:<event>',   // e.g. 'didit:completed'
  data: { /* payload */ }, // event-specific; may be undefined
  timestamp: 1718000000000 // ms epoch
}
```Payload-nya **bersarang**. Baca `event.data.data.sessionId`, bukan `event.data.sessionId`:```javascript theme={null}
window.addEventListener('message', (event) => {
  // Use your white-label domain here if you have one configured
  if (event.origin !== 'https://verify.didit.me') return;

  const { type, data } = event.data || {};

  if (type === 'didit:ready') {
    console.log('Session ID:', data.sessionId); // available as soon as the page loads
  }
  if (type === 'didit:completed') {
    console.log('Done:', data.sessionId, data.status); // e.g. "Approved" | "Declined" | "In Review"
    // UI hint only — the canonical decision arrives on your backend via webhook
  }
});
```Event utama: `didit:ready` (`{ sessionId }`), `didit:started`, `didit:step_started` / `didit:step_completed` / `didit:step_changed` (`{ step, ... }`), `didit:status_updated` (`{ status }`), `didit:completed` (`{ sessionId, status }`), `didit:cancelled`, `didit:error` (`{ error, step? }`), `didit:close_request`, dan `didit:layout` (`{ contentHeight, colorScheme, dir }`, lihat [di bawah](#atur-ukuran-iframe-dari-diditlayout)). [Referensi event JavaScript SDK](https://docs.didit.me/id/integration/web-sdks/javascript-sdk.md#referensi-event) mencantumkan event verifikasi yang tersedia sebagai callback bertipe. Mulai versi 0.5.0, SDK menangani pesan tata letak secara internal dan tidak meneruskannya ke `onEvent`.### Atur ukuran iframe dari `didit:layout`Halaman verifikasi memberi tahu seberapa besar ruang yang dibutuhkannya melalui pesan `didit:layout`. Pesan ini dikirim saat halaman dimuat dan setiap kali tinggi konten, tema, atau arah teks berubah:```typescript theme={null}
{
  type: 'didit:layout',
  data: {
    contentHeight: 612,    // CSS px
    colorScheme: 'light',  // 'light' | 'dark'
    dir: 'ltr'             // 'ltr' | 'rtl'
  },
  timestamp: 1718000000000
}
```| Kolom | Tipe | Deskripsi |
| - | - | - |
| `contentHeight` | `number` | Tinggi alami konten halaman dalam piksel CSS, termasuk bilah atas |
| `colorScheme` | `'light' \| 'dark'` | Tema tempat halaman ditampilkan. Dengan White Label, warna latar belakang Anda yang menentukan, bukan pengaturan perangkat |
| `dir` | `'ltr' \| 'rtl'` | Arah teks dari bahasa halaman |> [!NOTE]
>
> Untuk menerima `didit:layout` di iframe Anda sendiri, tambahkan `sdk_presentation=embedded` ke URL verifikasinya. Mulai versi 0.5.0, [JavaScript SDK](https://docs.didit.me/id/integration/web-sdks/javascript-sdk.md) mengatur presentasi ini secara otomatis. Tanpa parameter presentasi, halaman menggunakan tata letak mandiri dan tidak mengirim pesan tata letak.Host ini mengikuti [ukuran yang direkomendasikan](#ukuran-iframe): kartu tetap dengan lebar mulai 1024px, layar penuh pada lebar 540px ke bawah, dan di antaranya iframe selebar 500px yang mengikuti tinggi yang dilaporkan halaman:```html theme={null}
<iframe
  id="didit-verification"
  class="didit-iframe"
  title="Didit verification"
  allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
></iframe>

<style>
  /* 541px to 1023px wide: 500px wide and as tall as the content */
  .didit-iframe {
    display: block;
    width: 500px;
    max-width: 100%;
    height: var(--didit-content-height, 700px); /* 700px until the first didit:layout */
    max-height: 90vh;
    max-height: 90dvh;
    margin: 0 auto;
    border: none;
    border-radius: 16px;
  }

  /* 1024px and wider: the computer card */
  @media (min-width: 1024px) {
    .didit-iframe {
      width: 960px;
      max-width: 90vw;
      height: 660px;
    }
  }

  /* 540px and below: full screen */
  @media (max-width: 540px) {
    .didit-iframe {
      position: fixed;
      inset: 0;
      width: 100%;
      height: 100vh;
      height: 100dvh;
      max-height: none;
      border-radius: 0;
    }
  }
</style>

<script>
  const DIDIT_ORIGIN = 'https://verify.didit.me'; // or your white-label domain
  const iframe = document.getElementById('didit-verification');

  // verificationUrl: the session `url` from your backend, or your UniLink
  const src = new URL(verificationUrl);
  src.searchParams.set('sdk_presentation', 'embedded');
  window.addEventListener('message', (event) => {
    if (event.origin !== DIDIT_ORIGIN || event.source !== iframe.contentWindow) return;
    const { type, data } = event.data || {};
    if (type !== 'didit:layout') return;
    const height = data?.contentHeight;
    if (typeof height !== 'number' || !Number.isFinite(height) || height <= 0) return;

    // Only the 541px to 1023px size reads it; the other two sizes are fixed
    iframe.style.setProperty('--didit-content-height', `${height}px`);
  });
  iframe.src = src.toString();
</script>
```Di antara 541px dan 1023px, contoh ini menggunakan tinggi awal 700px sampai pesan tata letak diterima, dengan batas maksimal 90% dari tinggi jendela yang terlihat. Ukuran untuk komputer dan ponsel langsung berlaku. Di ponsel, iframe menutupi seluruh jendela, jadi sediakan cara bagi pengguna untuk keluar dari verifikasi di aplikasi host Anda. Gunakan `colorScheme` dan `dir` untuk menyesuaikan kontrol apa pun di sekitar iframe dengan tema dan arah teks halaman.Jika koneksi pengguna terputus, halaman menampilkan layar "Tidak ada koneksi internet" yang akan tertutup sendiri begitu koneksi kembali. Jika pengguna memilih **Exit Verification** di layar tersebut, halaman mengirim `didit:error` dengan `error: "network_error"`, lalu `didit:cancelled`. Tutup iframe saat menerima `didit:cancelled`.***## Implementasi ModalUntuk pengalaman modal yang rapi di atas halaman Anda:### HTML/CSS/JS```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <style>
    .didit-modal-overlay {
      display: none;
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.6);
      z-index: 9999;
      backdrop-filter: blur(4px);
    }
    
    .didit-modal-container {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 90%;
      max-width: 480px;
      height: 85vh;
      max-height: 750px;
      background: white;
      border-radius: 16px;
      overflow: hidden;
      box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    }
    
    .didit-modal-close {
      position: absolute;
      top: 12px;
      right: 12px;
      z-index: 10;
      width: 32px;
      height: 32px;
      border: none;
      background: rgba(0, 0, 0, 0.1);
      border-radius: 50%;
      cursor: pointer;
      font-size: 18px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .didit-modal-close:hover {
      background: rgba(0, 0, 0, 0.2);
    }
    
    .didit-iframe {
      width: 100%;
      height: 100%;
      border: none;
    }
  </style>
</head>
<body>
  <button onclick="openVerification()">Verify Identity</button>

  <div id="didit-modal" class="didit-modal-overlay">
    <div class="didit-modal-container">
      <button class="didit-modal-close" onclick="closeVerification()">✕</button>
      <iframe 
        id="didit-iframe"
        class="didit-iframe"
        allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
      ></iframe>
    </div>
  </div>

  <script>
    const UNILINK_URL = 'https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64';
    
    function openVerification() {
      document.getElementById('didit-iframe').src = UNILINK_URL;
      document.getElementById('didit-modal').style.display = 'block';
      document.body.style.overflow = 'hidden';
    }
    
    function closeVerification() {
      document.getElementById('didit-iframe').src = '';
      document.getElementById('didit-modal').style.display = 'none';
      document.body.style.overflow = '';
    }
    
    // Close on escape key
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') closeVerification();
    });
    
    // Close on overlay click
    document.getElementById('didit-modal').addEventListener('click', (e) => {
      if (e.target.id === 'didit-modal') closeVerification();
    });
  </script>
</body>
</html>
```***## Komponen ReactKomponen React yang dapat digunakan ulang untuk verifikasi berbasis modal:```tsx theme={null}
import { useState, useEffect } from 'react';

interface DiditInContextProps {
  /**
   * Either the `url` returned by POST /v3/session/ (API session)
   * or your UniLink URL copied from the Console (Workflows → Copy Link).
   * Don't derive the UniLink yourself — the path segment is a 22-character
   * base64url encoding of the workflow UUID's raw bytes, not btoa(workflowId).
   */
  verificationUrl: string;
  isOpen: boolean;
  onClose: () => void;
  onComplete?: (sessionId: string, status: string) => void;
}

export function DiditInContext({ 
  verificationUrl, 
  isOpen, 
  onClose,
  onComplete 
}: DiditInContextProps) {
  const [iframeSrc, setIframeSrc] = useState<string>('');

  useEffect(() => {
    if (isOpen) {
      setIframeSrc(verificationUrl);
      document.body.style.overflow = 'hidden';
    } else {
      setIframeSrc('');
      document.body.style.overflow = '';
    }
  }, [isOpen, verificationUrl]);

  // Listen for postMessage from iframe
  // Messages look like: { type: 'didit:<event>', data: {...}, timestamp }
  useEffect(() => {
    const handleMessage = (event: MessageEvent) => {
      // Use your white-label domain here if you have one configured
      if (event.origin !== 'https://verify.didit.me') return;

      if (event.data?.type === 'didit:completed' && onComplete) {
        onComplete(event.data.data?.sessionId, event.data.data?.status);
        onClose();
      }
    };

    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [onComplete, onClose]);

  // Handle escape key
  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && isOpen) onClose();
    };
    
    document.addEventListener('keydown', handleEscape);
    return () => document.removeEventListener('keydown', handleEscape);
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return (
    <div 
      className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center"
      onClick={(e) => e.target === e.currentTarget && onClose()}
    >
      <div className="relative w-[90%] max-w-[480px] h-[85vh] max-h-[750px] bg-white rounded-2xl overflow-hidden shadow-2xl">
        <button 
          onClick={onClose}
          className="absolute top-3 right-3 z-10 w-8 h-8 rounded-full bg-black/10 hover:bg-black/20 flex items-center justify-center"
          aria-label="Close"
        >
          ✕
        </button>
        <iframe 
          src={iframeSrc}
          className="w-full h-full border-0"
          allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
          title="Didit Verification"
        />
      </div>
    </div>
  );
}
```### Penggunaan```tsx theme={null}
import { useState } from 'react';
import { DiditInContext } from './DiditInContext';

function App() {
  const [isVerificationOpen, setIsVerificationOpen] = useState(false);
  
  return (
    <>
      <button onClick={() => setIsVerificationOpen(true)}>
        Verify Identity
      </button>
      
      <DiditInContext
        verificationUrl="https://verify.didit.me/u/YOUR_WORKFLOW_ID_BASE64" // UniLink from Console, or the API session `url`
        isOpen={isVerificationOpen}
        onClose={() => setIsVerificationOpen(false)}
        onComplete={(sessionId, status) => {
          console.log(`Verification ${status}: ${sessionId}`);
          if (status === 'Approved') {
            // Navigate to success page
          }
        }}
      />
    </>
  );
}
```***## Komponen Vue```vue theme={null}
<template>
  <Teleport to="body">
    <div 
      v-if="isOpen"
      class="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center"
      @click.self="$emit('close')"
    >
      <div class="relative w-[90%] max-w-[480px] h-[85vh] max-h-[750px] bg-white rounded-2xl overflow-hidden shadow-2xl">
        <button 
          @click="$emit('close')"
          class="absolute top-3 right-3 z-10 w-8 h-8 rounded-full bg-black/10 hover:bg-black/20 flex items-center justify-center"
        >
          ✕
        </button>
        <iframe 
          :src="iframeSrc"
          class="w-full h-full border-0"
          allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
        />
      </div>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { computed, watch, onMounted, onUnmounted } from 'vue';

const props = defineProps<{
  isOpen: boolean;
  // The `url` from POST /v3/session/, or your UniLink URL copied from the
  // Console (Workflows → Copy Link). Don't derive the UniLink with btoa() —
  // its path segment is base64url of the workflow UUID's raw bytes.
  verificationUrl: string;
}>();

const emit = defineEmits<{
  close: [];
  complete: [sessionId: string, status: string];
}>();

const iframeSrc = computed(() => (props.isOpen ? props.verificationUrl : ''));

// Handle escape key
const handleEscape = (e: KeyboardEvent) => {
  if (e.key === 'Escape' && props.isOpen) emit('close');
};

// Handle postMessage — messages look like { type: 'didit:<event>', data: {...}, timestamp }
const handleMessage = (event: MessageEvent) => {
  // Use your white-label domain here if you have one configured
  if (event.origin !== 'https://verify.didit.me') return;
  if (event.data?.type === 'didit:completed') {
    emit('complete', event.data.data?.sessionId, event.data.data?.status);
  }
};

onMounted(() => {
  document.addEventListener('keydown', handleEscape);
  window.addEventListener('message', handleMessage);
});

onUnmounted(() => {
  document.removeEventListener('keydown', handleEscape);
  window.removeEventListener('message', handleMessage);
});

// Lock body scroll when open
watch(() => props.isOpen, (isOpen) => {
  document.body.style.overflow = isOpen ? 'hidden' : '';
});
</script>
```***## Konfigurasi### Izin yang DiperlukanGunakan daftar izin lengkap ini untuk pengambilan gambar, lokasi, penyalinan, dan kompatibilitas media:```html theme={null}
allow="camera; microphone; geolocation; clipboard-write; fullscreen; autoplay; encrypted-media; digital-credentials-get"
```| Izin | Digunakan untuk dan yang terjadi jika tidak ada |
| - | - |
| `camera` | Pemindaian dokumen dan pengambilan gambar wajah. Tanpa izin ini, kamera tidak dapat dinyalakan dan pengguna melihat panduan untuk mengakses kamera |
| `microphone` | Audio opsional selama perekaman video dokumen dan wajah. Tanpa izin ini, perekaman tetap berjalan tanpa audio |
| `geolocation` | Langkah lokasi membaca posisi perangkat. Tanpa izin ini, pengguna melihat **Akses lokasi nonaktif**, meskipun mereka sudah mengizinkan lokasi di browser |
| `clipboard-write` | Menyalin referensi sesi atau tautan verifikasi, termasuk di layar browser dalam aplikasi. Tanpa izin ini, tindakan salin dapat gagal dan pengguna harus menyalin teks yang terlihat atau alamat browser secara manual |
| `fullscreen` | Memungkinkan kontrol media meminta layar penuh. Tanpa izin ini, kontrol tersebut tetap berada di dalam iframe |
| `autoplay` | Memungkinkan video panduan dan pratinjau kamera diputar otomatis, sesuai aturan browser. Tanpa izin ini, pemutaran mungkin menunggu tindakan pengguna |
| `encrypted-media` | Dipertahankan untuk kompatibilitas media terproteksi. Langkah pengambilan saat ini tidak memerlukannya; tanpa izin ini, pemutaran media terproteksi akan diblokir |
| `digital-credentials-get` | Berbagi ID digital dari dompet seperti Google Wallet melalui Digital Credentials API browser. Tanpa izin ini, browser menolak permintaan dompet di dalam iframe Anda, sehingga pengguna tidak dapat membagikan ID dari dompet di sana |Atribut `allow` memberikan izin ke iframe; atribut ini tidak menggantikan pilihan pengguna atau header `Permissions-Policy` yang lebih ketat pada halaman host Anda.### Ukuran iframeAlur verifikasi menyesuaikan tata letaknya dengan ukuran iframe-nya. Sesuaikan ukuran iframe dengan jendela tempat iframe ditampilkan:| Lebar jendela | Ukuran iframe yang disarankan |
| - | - |
| 1024px ke atas (komputer) | 960px kali 660px, paling besar 90% dari lebar dan tinggi jendela. Pertahankan ukuran ini di setiap langkah |
| 541px sampai 1023px | selebar 500px dan setinggi konten: ambil tinggi dari `contentHeight` pada [pesan `didit:layout`](#atur-ukuran-iframe-dari-diditlayout), paling besar 90% dari tinggi jendela |
| 540px ke bawah (ponsel) | Layar penuh: seluruh lebar dan seluruh tinggi jendela yang terlihat, tanpa sudut membulat |Untuk rentang tengah, mulailah dari 500px kali 700px sampai pesan `didit:layout` pertama tiba, dengan batas tinggi yang sama. [Contoh `didit:layout`](#atur-ukuran-iframe-dari-diditlayout) menerapkan ketiga ukuran, termasuk ukuran untuk komputer dan ponsel, sebelum pesan apa pun tiba.### Content Security Policy (CSP)Jika Anda menggunakan CSP, tambahkan Didit ke direktif `frame-src` Anda:```
Content-Security-Policy: frame-src https://verify.didit.me;
```***## Verifikasi Lintas PerangkatInContext iframe secara otomatis mendukung verifikasi lintas perangkat:1) Pengguna memulai verifikasi di desktop
2) Jika kamera tidak tersedia, kode QR ditampilkan
3) Pengguna memindai kode QR di ponsel
4) Pengguna menyelesaikan verifikasi di ponsel
5) Iframe di desktop otomatis diperbarui dengan hasilnyaIni terjadi secara otomatis, tanpa konfigurasi tambahan.***## Pemecahan Masalah### Kamera Tidak Berfungsi1) Pastikan iframe menyertakan [daftar izin](#izin-yang-diperlukan) lengkap
2) Pastikan situs Anda diakses melalui HTTPS
3) Pastikan pengguna sudah memberikan izin kamera untuk domain Anda
4) Coba metode [Pengalihan](https://docs.didit.me/id/integration/web-sdks/web-redirect.md) jika akses kamera di iframe gagal### Iframe Tidak Dapat Dimuat1) Periksa masalah Content Security Policy (CSP)
2) Tambahkan `https://verify.didit.me` ke direktif `frame-src` Anda
3) Periksa konsol browser untuk melihat kesalahan### postMessage Tidak Diterima1) Pastikan Anda mendengarkan origin yang benar (`https://verify.didit.me`, atau domain White Label Anda)
2) Pastikan event listener sudah ditambahkan sebelum iframe dibuka
3) Periksa nama dan bentuk event: tipenya diberi awalan (`didit:completed`, bukan `verification_complete`) dan payload-nya berada di dalam `event.data.data`***## Repositori Contoh> [card] [Repositori GitHub](https://github.com/didit-protocol/iframe-example)
>
> Lihat kode sumber dan contoh di GitHub***


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