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

# Widget Kepemilikan Dompet - Bukti Kontrol Travel Rule

> Widget Didit untuk membuktikan pelanggan menguasai dompet kripto via tanda tangan pesan, Satoshi test, screenshot, atau deklarasi mandiri.

Widget kepemilikan dompet adalah halaman yang di-hosting untuk membuktikan bahwa pelanggan Anda menguasai alamat dompet kripto tertentu. Berdasarkan EU TFR, VASP wajib memverifikasi kepemilikan dompet swakelola (unhosted) sebelum mengirim dana ke atau dari dompet tersebut yang melebihi ambang batas sunrise. Widget ini adalah cara Didit mengumpulkan bukti tersebut tanpa Anda perlu membangun alur penandatanganan sendiri.

Bukti yang terverifikasi menandai [entri buku alamat dompet](https://docs.didit.me/id/transaction-monitoring/travel-rule.md#buku-alamat-dompet) yang sesuai dengan `is_ownership_verified: true`, yang memungkinkan [transfer Travel Rule](https://docs.didit.me/id/transaction-monitoring/travel-rule.md) terkait berpindah keluar dari status `UNCONFIRMED_OWNERSHIP`.

## Kapan Didit membuatnya untuk Anda

Anda jarang perlu membuat sesi sendiri.
Saat `auto_wallet_verification` aktif di [pengaturan Travel Rule](https://docs.didit.me/id/transaction-monitoring/travel-rule.md#pengaturan) Anda (nilai default), Didit otomatis membuat sesi widget ketika transaksi dibuat, setiap kali transfer memerlukan bukti kontrol dompet dari pengguna akhir:

* Transfer berada di `UNCONFIRMED_OWNERSHIP`, karena dompet pihak lawan [dinyatakan sebagai dompet swakelola](https://docs.didit.me/id/transaction-monitoring/travel-rule.md#dompet-swakelola-yang-dideklarasikan) saat pengajuan.
* Transfer bersifat keluar dan berada di `COUNTERPARTY_VASP_NOT_FOUND`, karena tidak ada VASP pihak lawan yang dapat diidentifikasi, sehingga pembuktian kepemilikan menjadi jalur yang tersisa untuk menyelesaikan transfer.

Sesi yang dibuat otomatis dikembalikan dalam blok `action_required` pada transaksi (`type: "wallet_ownership"`, dengan `url` yang akan dibuka), dan SDK meluncurkannya secara otomatis saat [pengiriman dari sisi klien](https://docs.didit.me/id/transaction-monitoring/sdk-transaction-submission.md#tindakan-yang-diperlukan-pengguna).
Transfer masuk yang dibuat Didit untuk Anda (pendaftaran sunrise, inkuiri `TRP` masuk, atau segmen masuk pada jalur `INTERNAL`) tidak pernah mendapatkan sesi yang dibuat otomatis, meskipun transfer tersebut masuk ke `UNCONFIRMED_OWNERSHIP`.
Buat sesi secara manual dengan `POST /v3/travel-rule/widget-session/` jika Anda ingin memverifikasi dompet sebelum ada transfer, jika `auto_wallet_verification` dinonaktifkan, atau untuk salah satu transfer masuk tersebut.

## Apa yang dibuktikan

Widget ini menawarkan hingga empat metode pembuktian. Metode yang muncul bergantung pada cara Anda membuat sesi dan [pengaturan Travel Rule](https://docs.didit.me/id/transaction-monitoring/travel-rule.md#pengaturan) Anda:

| Metode | Cara kerjanya | Kapan ditawarkan |
| - | - | - |
| `MESSAGE_SIGNING` | Pelanggan menandatangani string tantangan yang diterbitkan Didit dengan dompetnya. Mendukung dompet EVM, Solana, Bitcoin, dan Tron (untuk Bitcoin, alamat legacy, nested SegWit, native SegWit, dan Taproot); Didit memverifikasi tanda tangan terhadap alamat, dan penandatanganan dengan akun yang berbeda dari akun yang diverifikasi akan ditolak dengan petunjuk yang jelas untuk beralih akun. Akun smart contract EVM (dompet pintar ERC-4337) juga dapat menandatangani: Didit meminta kontrak akun tersebut, pada chain tempat dompet dideklarasikan, untuk memastikan apakah tanda tangan valid (ERC-1271), dan untuk akun yang belum di-deploy, Didit memeriksa tanda tangan ERC-6492 yang dikembalikan dompet, tanpa men-deploy akun atau mengirim transaksi apa pun. Akun smart contract diperiksa di setiap chain EVM yang didukung. Lihat [verifikasi kontrak message signing](#kontrak-verifikasi-penandatanganan-pesan) di bawah. Dompet yang terpasang di browser pelanggan ditemukan melalui protokol EIP-6963 dan Wallet Standard, sehingga setiap ekstensi muncul sebagai opsi penandatanganan tersendiri. Memasangkan aplikasi dompet seluler terpisah, misalnya melalui kode QR, saat ini belum tersedia. | Selalu, untuk keluarga chain yang didukung. |
| `SATOSHI_TEST` | Pelanggan mengirim jumlah kecil on-chain dari dompetnya ke alamat deposit yang Anda kendalikan; watcher Didit memeriksa pengirim (untuk akun smart contract EVM, akunnya sendiri, juga ketika bundler ERC-4337 yang mengirim transaksi), jumlahnya, dan bahwa deposit dikonfirmasi on-chain, lalu secara otomatis menyelesaikan pembuktian setelah deposit dikonfirmasi. Lihat [verifikasi kontrak tes Satoshi](#kontrak-verifikasi-tes-satoshi) di bawah. | Hanya jika Anda menyertakan `satoshi_deposit_address` saat membuat sesi dan chain-nya adalah chain EVM, Bitcoin, atau Solana, jadi tidak pernah pada sesi yang dibuat otomatis. |
| `SCREENSHOT` | Pelanggan mengunggah tangkapan layar dompet yang menampilkan alamat (JPEG/PNG/WebP, hingga 10 MB). Berbeda dengan metode lain, metode ini tidak pernah diverifikasi otomatis: tim kepatuhan Anda meninjaunya dari antrean peninjauan tangkapan layar ([`GET /v3/travel-rule/wallet-proofs/`](https://docs.didit.me/id/management-api/travel-rule/list-wallet-proofs)) dan menyetujui atau menolaknya ([`POST .../decision/`](https://docs.didit.me/id/management-api/travel-rule/decide-wallet-proof)), atau mengonfirmasi transfer dari tab **Travel Rule** pada transaksi di konsol atau melalui [`POST .../travel-rule/ownership/`](https://docs.didit.me/id/management-api/travel-rule/confirm-ownership) (untuk transfer dalam status `UNCONFIRMED_OWNERSHIP` atau transfer masuk yang ditahan). | Hanya jika `allow_screenshot_proof` bernilai `true` di pengaturan Anda. |
| `SELF_DECLARATION` | Pelanggan menyatakan kepemilikan tanpa bukti kriptografis, sebagai pilihan terakhir jika yurisdiksi memperbolehkannya. | Hanya jika `allow_self_declaration` bernilai `true` dan [`ownership_validation_mode`](https://docs.didit.me/id/transaction-monitoring/travel-rule#mode-validasi-kepemilikan) Anda menerima deklarasi untuk transfer yang terkait: tidak pernah pada `FULL`, dan pada `SIMPLIFIED` hanya di bawah `simplified_validation_threshold`. Memulai metode yang tidak diterima oleh mode tersebut akan mengembalikan `403`. |

### Kontrak verifikasi penandatanganan pesan

Setelah tanda tangan dikirim, respons `200` dengan `status: "VERIFIED"` dikembalikan ketika tanda tangan membuktikan kendali atas dompet.
Respons `400` dikembalikan dan pembuktian tetap terbuka, sehingga pelanggan dapat menandatangani ulang, dengan salah satu nilai `code` berikut:

| `code` | Arti |
| - | - |
| `SIGNATURE_INVALID` | Tanda tangan tidak membuktikan dompet tersebut: ditandatangani oleh akun atau kunci lain, atau pesannya berbeda. Untuk akun smart contract, kontraknya menjawab bahwa tanda tangan itu bukan miliknya. |
| `SIGNATURE_UNSUPPORTED_SCHEME` | Dompet menandatangani dalam format yang tidak diverifikasi Didit, misalnya multisig Bitcoin atau tanda tangan penuh BIP-322. |
| `SIGNATURE_LOOKUP_FAILED` | Dompet mungkin merupakan akun smart contract, dan chain-nya tidak dapat diperiksa saat ini. Pembuktian tidak pernah diverifikasi berdasarkan respons ini; menandatangani ulang akan memeriksanya kembali. |

### Kontrak verifikasi tes Satoshi

Verifikasi deposit tes Satoshi bersifat asinkron, karena transaksinya harus terlihat on-chain lalu dikonfirmasi.
Setelah `txid` deposit dikirim, respons `200` dengan `status: "PENDING"` dikembalikan selama deposit belum dikonfirmasi on-chain. `txid` disimpan, tidak dibuang.
Respons `200` dengan `status: "VERIFIED"` dikembalikan setelah deposit dikonfirmasi.
Respons `400` dengan `status: "REJECTED"` dikembalikan untuk deposit yang memang salah: dikirim dari dompet lain, jumlah yang dikirim ke alamat deposit bukan jumlah yang diharapkan, lebih lama dari tantangan, atau transaksi yang sudah membuktikan dompet lain. Pembuktian ditutup dan pelanggan dapat memulai pembuktian baru selama sesi masih memiliki sisa percobaan.
Deposit yang belum diindeks juga mengembalikan `200` dengan `status: "PENDING"`, dan pencarian yang gagal di sisi Didit mengembalikan `400` dengan kode `DEPOSIT_LOOKUP_FAILED`. Dalam kedua kasus, pembuktian tetap terbuka dan Didit terus memeriksa.
Respons `410` dikembalikan jika jendela tes berakhir sebelum deposit yang valid terlihat.

Setelah `txid` dikirim, job latar belakang memeriksa ulang deposit yang tertunda setiap lima menit dan menyelesaikan pembuktian setelah transaksi dikonfirmasi, sehingga pelanggan tidak perlu mengirim ulang `txid`.
Ketika Anda menyertakan `satoshi_deposit_address`, `expires_at` milik sesi widget diperpanjang menjadi minimal jendela tes Satoshi 24 jam, sehingga deposit memiliki waktu untuk dikonfirmasi sebelum sesi itu sendiri kedaluwarsa.

## Flow

**1. Terbitkan sesi widget**

Panggil `POST /v3/travel-rule/widget-session/` dengan dompet yang perlu diverifikasi. Secara opsional, tautkan sesi ke transfer agar transfer otomatis maju setelah kepemilikan terbukti.

**2. Buka URL yang dikembalikan**

Kirim pelanggan Anda ke `url` dari respons. Mereka menyelesaikan bukti di sana tanpa memerlukan akun Didit atau kunci API; token di URL berfungsi sebagai autentikasi.

**3. Deteksi penyelesaian**

Ketika bukti diverifikasi, widget menandai entri buku alamat sebagai terverifikasi dan, jika sesi ditautkan ke transfer, memajukan transfer tersebut. Pantau `travel_rule.status.updated` (untuk transfer yang ditautkan) atau lakukan polling pada konteks widget.

### Terbitkan sesi widget

Contoh ini menautkan sesi ke [transfer swakelola yang dideklarasikan](https://docs.didit.me/id/transaction-monitoring/travel-rule.md#dompet-swakelola-yang-dideklarasikan) dari panduan Travel Rule, sehingga `wallet_address` adalah dompet tujuan transfer tersebut.
Sesi yang ditautkan ke transfer hanya menerima bukti untuk dompet pihak lawan transfer.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/widget-session/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
    "chain": "ETH",
    "holder_name": "Jane Doe",
    "vendor_data": "user-042",
    "transaction_id": "99999999-aaaa-bbbb-cccc-dddddddddddd",
    "satoshi_deposit_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
    "callback_url": "https://yourapp.example/wallet-verified",
    "expires_in_minutes": 60
  }'
```

| Kolom | Tipe | Deskripsi |
| - | - | - |
| `wallet_address` | string | Alamat dompet yang akan diverifikasi. |
| `chain` | string | Pengidentifikasi chain untuk alamat (misalnya `ETH`, `BTC`, `SOL`). Gunakan token yang sama dengan yang dibawa transfer Anda (`ETH`, bukan `ethereum`): widget menyimpan entri buku alamat dengan `chain` ini, dan transfer pada chain yang berbeda tidak akan cocok dengannya. Penandatanganan pesan memerlukan chain yang dikenali Didit. |
| `holder_name` | string | Nama pemegang dompet, digunakan untuk pencocokan nama penerima. |
| `vendor_data` | string | Pengidentifikasi internal Anda untuk pemegang, dibawa ke entri buku alamat yang dibuat. |
| `transaction_id` | string (uuid) | Opsional. UUID transaksi Didit dari transfer Travel Rule yang akan dimajukan ketika bukti diverifikasi; UUID yang tidak dikenal mengembalikan `404`, dan bukti untuk dompet selain dompet pihak lawan transfer akan ditolak dengan `400`. Hilangkan untuk memverifikasi dompet secara mandiri. |
| `satoshi_deposit_address` | string | Opsional. Alamat deposit yang Anda kendalikan; jika diisi, metode `SATOSHI_TEST` diaktifkan. |
| `callback_url` | string | Opsional. Tempat widget mengembalikan pelanggan setelah penyelesaian. |
| `expires_in_minutes` | integer | Opsional. Masa berlaku tautan yang diterbitkan dalam menit, dari `5` hingga `10080` (default `60`); otomatis dinaikkan menjadi minimal jendela pengujian Satoshi 24 jam ketika Anda memberikan `satoshi_deposit_address`. |

```json theme={null}
{
  "widget_session_id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
  "token": "3s9x...urlsafe",
  "url": "https://verify.didit.me/wallet-ownership/3s9x...urlsafe",
  "expires_at": "2026-07-07T13:00:00Z"
}
```

Selalu buka `url` yang dikembalikan dalam respons apa adanya. Jangan membuatnya sendiri.

### Buka URL yang dikembalikan

> [!WARNING]
>
> **Widget hanya tersedia di web pada rilis ini. Buka `url` di browser sistem atau tab kustom, jangan pernah di dalam webview SDK seluler Didit.**
>
> Penandatanganan pesan berfungsi dengan dompet yang terpasang di browser pelanggan, yang ditemukan widget melalui protokol EIP-6963 dan Wallet Standard.
> Memasangkan aplikasi dompet seluler terpisah, misalnya dengan kode QR, belum tersedia saat ini, sehingga widget tidak mengalihkan ke aplikasi lain.
> Webview dalam aplikasi, seperti webview SDK Didit Web/Flutter/React Native/iOS/Android, **tidak dapat menjangkau dompet browser pelanggan**, sehingga widget yang dibuka di sana membuat pelanggan tidak memiliki cara untuk menandatangani.
>
> Di perangkat seluler, luncurkan `url` dengan browser sistem operasi (`SFSafariViewController` / Chrome Custom Tabs, atau browser default) alih-alih merendernya di webview. Di web, tab biasa atau popup sudah sesuai.

### Deteksi penyelesaian

Widget menyediakan endpoint publik untuk membaca status yang menggunakan token sebagai kunci. Lakukan polling untuk melihat progres, atau andalkan webhook ketika sesi ditautkan ke transfer:

```bash theme={null}
curl https://verification.didit.me/v3/travel-rule/widget/{token}/
```

```json theme={null}
{
  "vasp_name": "Origin CASP SL",
  "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
  "chain": "ETH",
  "holder_name": "Jane Doe",
  "allowed_methods": ["MESSAGE_SIGNING", "SCREENSHOT", "SATOSHI_TEST", "SELF_DECLARATION"],
  "transfer_status": "UNCONFIRMED_OWNERSHIP",
  "callback_url": "https://yourapp.example/wallet-verified",
  "expires_at": "2026-07-07T13:00:00Z",
  "completed_at": null,
  "proofs": [
    {
      "proof_id": "88888888-9999-aaaa-bbbb-cccccccccccc",
      "method": "SATOSHI_TEST",
      "status": "PENDING",
      "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
      "chain": "ETH",
      "deposit_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      "expected_amount": "0.000042817305521963",
      "expires_at": "2026-07-07T13:05:00.412731+00:00",
      "created_at": "2026-07-06T13:05:00.412731Z"
    }
  ],
  "customization": null
}
```

* `completed_at` berisi nilai non-null setelah bukti diverifikasi.
* Setiap entri dalam `proofs` memuat kolom yang dibutuhkan metodenya: bukti `SATOSHI_TEST` menambahkan `deposit_address`, `expected_amount`, dan `expires_at`-nya sendiri; bukti `MESSAGE_SIGNING` menambahkan `challenge`, teks yang ditandatangani pelanggan.
* Bukti `SATOSHI_TEST` dapat berada pada `status: "PENDING"` ketika depositnya terlihat on-chain tetapi belum dikonfirmasi, tanpa tindakan apa pun dari Anda atau pelanggan. Lihat [kontrak verifikasi Satoshi test](#kontrak-verifikasi-tes-satoshi) di atas.
* Ketika sesi diterbitkan dengan `transaction_id`, memverifikasi bukti akan memajukan transfer yang ditautkan, dan pada aplikasi produksi webhook [`travel_rule.status.updated`](https://docs.didit.me/id/integration/webhooks#jenis-event) akan terpicu.
  Utamakan webhook daripada polling.
  Permintaan `TRP` masuk disetujui kembali ke pengirim dan berpindah ke `COMPLETED` setelah persetujuan tersebut terkirim.
  Transfer lain dalam `UNCONFIRMED_OWNERSHIP` (atau transfer masuk yang `ON_HOLD`) berpindah ke `COMPLETED`, atau ke `COUNTERPARTY_MISMATCHED_DATA` ketika nama penerima tidak cocok dengan pemegang dompet, dan deposit sunrise yang telah diselesaikan akan terus berlanjut ke `FINISHED`.
  Transfer keluar dalam `COUNTERPARTY_VASP_NOT_FOUND` berpindah ke `COMPLETED`.
* Bukti `SCREENSHOT` tetap berstatus `status: "PENDING"` dalam konteks ini bahkan setelah Anda mengonfirmasi kepemilikan.
  Anda menyetujuinya dengan [`POST .../travel-rule/ownership/`](https://docs.didit.me/id/transaction-monitoring/travel-rule#mengonfirmasi-kepemilikan-dompet), yang hanya menerima transfer yang menunggu konfirmasi kepemilikan.
  Oleh karena itu, bukti screenshot tidak memiliki jalur persetujuan pada sesi tanpa transfer tertaut, atau pada sesi yang ditautkan ke transfer keluar dalam `COUNTERPARTY_VASP_NOT_FOUND`: nonaktifkan `allow_screenshot_proof` jika sesi-sesi tersebut tidak boleh menawarkannya.
* Setelah bukti ditolak, sesi memberikan percobaan baru selama percobaan masih tersisa.
  `max_attempts`, `attempts_used`, dan `attempts_remaining` melaporkan jumlahnya, bukti yang ditolak memuat `rejection_reason`, dan ketika `attempts_remaining` bernilai `0`, memulai bukti lain akan menghasilkan `409` dan Anda harus menerbitkan sesi baru.
* Endpoint konteks mengembalikan `404` untuk token yang tidak dikenal dan `410` setelah sesi kedaluwarsa tanpa diselesaikan.

> [!NOTE]
>
> Tidak ada dependensi sekali jalan di sini: widget dan backend Anda sama-sama menuju status persisten yang sama (entri buku alamat terverifikasi dan status transfer), sehingga webhook yang terlewat atau tab yang ditutup selalu dapat dipulihkan dengan membaca ulang transfer atau konteks widget.

## Lokalisasi dan branding

Widget ditampilkan dalam **54 bahasa**, mengikuti jalur bahasa pada tautan (atau bahasa default browser).

Jika White Label diaktifkan untuk aplikasi Anda, widget otomatis mewarisi branding alur verifikasi Anda: logo, warna merek, gaya tombol dan panel, font kustom, favicon, serta nama publik aplikasi Anda di judul.
Tidak ada konfigurasi terpisah yang perlu dilakukan. Kustomisasi yang Anda atur untuk sesi KYC juga berlaku di sini.

Pengguna yang kembali ke tautan yang sudah selesai akan melihat layar penyelesaian lagi. Jika Anda meneruskan `callback_url`, widget akan mengarahkan mereka ke sana.
Tautan yang sudah kedaluwarsa menampilkan layar kedaluwarsa dengan branding yang meminta pengguna mengajukan tautan baru.
Buat sesi baru untuk mereka dengan `POST /v3/travel-rule/widget-session/`. Mengirim ulang transfer dengan `action: "resend"` tidak membuat sesi.

## Langkah selanjutnya

> [card] [Travel Rule](https://docs.didit.me/id/transaction-monitoring/travel-rule.md)
>
> Siklus hidup pertukaran lengkap, jalur, pengaturan, dan alur penerimaan.

> [card] [Buku alamat dompet](https://docs.didit.me/id/transaction-monitoring/travel-rule.md#buku-alamat-dompet)
>
> Daftarkan dompet yang Anda kendalikan agar transfer masuk dicocokkan dengan dompet tersebut.

> [card] [Webhook](https://docs.didit.me/id/integration/webhooks.md)
>
> Berlangganan travel\_rule.status.updated agar dapat merespons saat bukti menyebabkan transfer berlanjut.

> [card] [SDK native](https://docs.didit.me/id/integration/native-sdks/overview.md)
>
> Buka URL widget dengan browser sistem, bukan webview SDK.


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