Langsung ke konten utama
Didit SDK dapat mengirimkan transaksi yang dipantau langsung dari perangkat pengguna akhir, termasuk transfer Travel Rule dan skrining kripto. Backend Anda membuat token dengan cakupan terbatas yang berumur pendek; SDK menangani sisanya. SDK otomatis melampirkan intelijen perangkat. Ketika transfer Travel Rule memerlukan bukti kontrol dompet, SDK langsung meluncurkan alur tersebut. Sesi verifikasi yang diperlukan tidak pernah diluncurkan otomatis. Sesi itu dikembalikan dalam respons agar aplikasi Anda meluncurkannya dengan integrasi verifikasi Didit Anda sendiri; lihat Tindakan pengguna yang diperlukan di bawah.

Ringkasan

Pengiriman transaksi dari sisi klien dibangun di atas tiga jaminan:
  • Pengikatan subjek yang tahan spoofing. Token dibatasi ke satu vendor_data (ID pengguna Anda) saat dibuat. Identitas subjek dari setiap transaksi yang dikirim dengan token tersebut ditegakkan di sisi server berdasarkan pengikatan ini, sehingga klien yang dimanipulasi tidak dapat mengirim atas nama pengguna lain, dan payload tidak perlu membawa kredensial.
  • Intelijen perangkat otomatis. SDK mengumpulkan sidik jari perangkat dan mengirimkannya bersama permintaan. Didit menurunkan alamat IP dan user agent di sisi server. Konteks perangkat gabungan dilampirkan ke subjek transaksi tanpa pustaka tambahan, tanpa token perangkat terpisah, dan tanpa integrasi tambahan di pihak Anda. Konteks ini mendukung aturan berbasis perangkat serta korelasi berdasarkan perangkat lintas sesi dan transaksi.
  • Pembuktian kepemilikan dompet yang diluncurkan otomatis. Ketika transaksi yang dibuat mengharuskan pengguna akhir membuktikan kontrol atas dompet, respons membawa blok action_required bertipe wallet_ownership. SDK langsung membuka alur tersebut, lalu menyegarkan transaksi setelah selesai, tanpa loop polling atau pengiriman tautan yang harus Anda bangun sendiri. Tindakan verification_session yang diperlukan berbeda: tindakan itu tidak pernah diluncurkan otomatis dan dikembalikan dalam blok yang sama agar aplikasi Anda meluncurkannya dengan integrasi verifikasi Didit miliknya sendiri.
POST /v3/transactions/ di sisi server tetap menjadi pilihan yang tepat ketika tidak ada pengguna akhir: transfer back-office, impor batch, atau event yang dilaporkan oleh sistem Anda sendiri. Kedua jalur membuat rekaman transaksi yang sama, menjalankan aturan yang sama, dan mengirim webhook yang sama.

Alur

1

Buat token transaksi

Backend Anda memanggil POST /v3/transactions/sdk-token/ dengan kunci API Anda dan vendor_data pengguna, lalu menyerahkan sdk_token yang dikembalikan ke aplikasi Anda.
2

Kirim dari perangkat

Aplikasi memanggil submitTransaction pada SDK. Pemanggilan ini mengirim payload ke POST /v1/transactions/ dengan header X-Transaction-Token dan pengayaan perangkat otomatis.
3

Tangani tindakan yang diperlukan

Jika action_required.type adalah wallet_ownership, SDK otomatis meluncurkan widget, lalu menyegarkan transaksi melalui GET /v1/transactions/{transaction_id}/. Jika tipenya verification_session, SDK tidak meluncurkan apa pun. Baca action_required dan mulai alur verifikasi Anda sendiri dengan session_token-nya (atau url di web).

Membuat token transaksi

Buat token dari backend Anda dengan POST /v3/transactions/sdk-token/. Autentikasinya menggunakan kunci API yang sama dengan endpoint transaksi /v3/ lainnya.
Alias camelCase (vendorData, ttlSeconds, maxUses) juga diterima, seperti pada API /v3/ lainnya.
Jangan pernah menyertakan kunci API Anda di aplikasi. Kunci API tetap berada di backend Anda dan digunakan untuk membuat token. Hanya sdk_token berumur pendek yang dikirim ke perangkat. Buat token baru untuk setiap sesi pengguna, alih-alih menggunakan ulang token berumur panjang. Batasi max_uses ketika jumlah pengiriman yang diharapkan sudah diketahui.

Mengirim dari perangkat

SDK mengirim ke POST /v1/transactions/ dengan token di header X-Transaction-Token. Payload wire menggunakan camelCase. Metode submitTransaction membangunnya untuk Anda, jadi Anda hanya perlu menanganinya langsung saat memanggil endpoint dari klien HTTP Anda sendiri:
Setiap kolom tingkat atas dipetakan ke padanan POST /v3/transactions/-nya: Respons berisi detail transaksi snake_case yang sama dengan endpoint /v3/, ditambah blok action_required:

Mendeklarasikan dompet swakelola

Contoh di atas menyatakan tujuan sebagai dompet swakelola milik pengguna: paymentMethod.type pada counterparty adalah unhosted_wallet. Deklarasi tersebut mengubah cara pertukaran Travel Rule berjalan:
  • Didit melewati routing VASP pihak lawan sepenuhnya - tidak ada VASP di balik dompet swakelola - dan membuat transfer langsung dalam status UNCONFIRMED_OWNERSHIP.
  • Saat auto_wallet_verification aktif di pengaturan Travel Rule Anda (default-nya), sesi widget kepemilikan dompet dibuat otomatis dan dikembalikan dalam action_required, persis seperti pada respons di atas.
  • SDK meluncurkan widget secara otomatis; setelah pengguna membuktikan kendali atas dompet, transfer menjalankan pencocokan nama dan beralih ke COMPLETED, atau ke COUNTERPARTY_MISMATCHED_DATA jika nama tidak cocok dengan pemilik yang tercatat di buku alamat dompet.
Tanpa deklarasi, Didit justru mencoba jalur secara berurutan dan hanya beralih ke alur kepemilikan jika tidak ada VASP pihak lawan yang ditemukan. Deklarasikan dompet kapan pun produk Anda sudah mengetahui bahwa target penarikan adalah dompet milik pengguna sendiri. Dengan begitu, Anda menghemat satu kali percobaan routing yang gagal dan pengguna langsung masuk ke alur pembuktian.

Penegakan subjek

Tiga hal berikut selalu ditentukan oleh token, tidak pernah oleh payload:
  • Aplikasi tempat transaksi dibuat.
  • Identitas subjek: subject.externalUserId dalam payload diabaikan dan digantikan dengan vendor_data dari token.
  • Konteks perangkat subjek (lihat di bawah); kolom yang diturunkan dari server selalu menang jika terjadi konflik dengan apa pun yang dikirim dalam subject.device.
Respons 401 dari endpoint ini berarti token ditolak: token tidak ada, tidak dikenal, dicabut, melebihi max_uses-nya, atau kedaluwarsa. Respons token kedaluwarsa selalu memuat kata expired dalam detail error, dan itulah cara SDK membedakan error expired_token dari error invalid_token.

Membaca transaksi kembali

GET /v1/transactions/{transaction_id}/ mengembalikan detail yang sama dengan autentikasi X-Transaction-Token yang sama. SDK memanggilnya secara otomatis setelah alur tindakan yang diluncurkan selesai atau jendela waktunya tertutup, sehingga status akhir tidak pernah bergantung pada satu event atau notifikasi saja. Anda dapat memanggilnya sendiri untuk memeriksa ulang status dan action_required kapan pun selama token masih berlaku. Dari backend Anda, GET /v3/transactions/{transaction_id}/ mengembalikan catatan yang sama.

Intelijen perangkat otomatis

Setiap pengiriman membawa intelijen perangkat tanpa pekerjaan integrasi apa pun di sisi Anda:
  • SDK mengumpulkan sidik jari perangkat yang menjaga privasi (skema didit-fp-v2: sinyal platform dan navigator, ID perangkat yang persisten, skor bot, dan hash gabungan) lalu mengirimkannya bersama permintaan.
  • Didit menurunkan alamat IP, user agent, dan accept-language di sisi server dari koneksi itu sendiri, sehingga nilai-nilai tersebut tidak dapat dipalsukan lewat payload.
Hasil gabungan dinormalisasi ke dalam konteks perangkat peserta subjek, lalu di-upsert ke dalam graf perangkat, yaitu graf yang sama dengan yang juga diisi oleh sesi KYC. Hal ini membuat transaksi dapat dikorelasikan berdasarkan perangkat di seluruh basis pengguna Anda (“terkait berdasarkan perangkat”), mengalirkan sinyal perangkat dan jaringan ke dalam aturan dan pengayaan IP, serta muncul di detail transaksi pada Console. Transaksi /v3/ yang dikirim dari server dapat tetap meneruskan objek device_context eksplisit untuk setiap peserta. Pada jalur SDK, Anda mendapatkan versi yang lebih kuat dari data yang sama tanpa biaya tambahan.

Tindakan yang diperlukan pengguna

Beberapa transaksi memerlukan tindakan pengguna akhir sebelum dapat diselesaikan: sebuah aturan dapat mensyaratkan sesi verifikasi, atau transfer Travel Rule dapat mensyaratkan bukti bahwa dompet tujuan benar-benar milik pengguna. Kedua kasus ini muncul di tempat yang sama, yaitu blok action_required pada respons submit (dan pada setiap pembacaan transaksi berikutnya):
Jika keduanya dapat berlaku pada transaksi yang sama, wallet_ownership didahulukan, karena bukti kepemilikan yang belum ada akan memblokir pertukaran Travel Rule itu sendiri. action_required menjadi null setelah tindakan yang tertunda diselesaikan. Kolom remediation yang ada tetap dipertahankan demi kompatibilitas ke belakang; action_required adalah blok kanonis.

Kontrak peluncuran otomatis

autoLaunchAction (default true) secara otomatis hanya meluncurkan tindakan wallet_ownership:
  • Web - dibuka di modal overlay milik SDK, dengan penyelesaian dideteksi melalui pesan yang divalidasi asal-usulnya ditambah polling transaksi yang terbatas (tidak pernah bergantung pada satu event saja).
  • iOS / Android (dan pembungkus React Native serta Flutter, yang meneruskan ke SDK native) - ditampilkan sebagai pengalaman kepemilikan dompet native milik SDK (SwiftUI / Jetpack Compose) ketika useNativeWalletOwnership bernilai true (default), dengan cadangan ke SFSafariViewController / Chrome Custom Tab, dan terakhir ke browser default. Setelah alur ditutup atau aplikasi kembali ke latar depan, SDK membaca ulang transaksi secara otomatis.
Tindakan verification_session tidak pernah diluncurkan otomatis: tindakan itu selalu muncul di action_required agar aplikasi Anda memulainya dengan integrasi verifikasi Didit milik Anda sendiri.
Widget kepemilikan dompet tidak boleh pernah dirender di dalam webview seluler tertanam - deep link dompet tidak dapat keluar darinya dan alur pembuktian akan buntu. SDK sudah menggunakan tampilan browser yang tepat saat meluncurkan otomatis; pertahankan aturan ini jika Anda menangani url sendiri. Lihat panduan widget kepemilikan dompet untuk detailnya.
Setelah alur kepemilikan dompet yang diluncurkan otomatis oleh SDK selesai atau ditutup, SDK membaca ulang transaksi dan menyerahkan hasil yang diperbarui ke callback onActionCompleted Anda. Tindakan verification_session tidak termasuk dalam siklus itu, karena aplikasi Anda yang meluncurkannya - lihat bagian berikutnya.

Meluncurkan sesi verifikasi

Ketika action_required.type bernilai verification_session, baca blok dari result.actionRequired dan serahkan ke integrasi verifikasi Didit yang sudah ada:
Setelah alur verifikasi Anda selesai, panggil GET /v1/transactions/{transaction_id}/ (atau tunggu webhook transaksi) untuk mengambil status transaksi yang diperbarui.

Contoh: biometrik tambahan untuk penarikan bernilai tinggi

Ini adalah alur terbaik: batasi transaksi berisiko - jumlah besar, penerima baru, perangkat baru - dengan pemeriksaan ulang biometrik dari orang yang sama yang Anda verifikasi saat onboarding. Pengambilalihan akun terlihat persis seperti ini: kata sandi benar, kode 2FA benar (hasil phishing atau SIM swap), dan penarikan ke dompet yang belum pernah Anda lihat. Setiap pertahanan berbasis kredensial sudah gagal pada titik itu. Namun, wajah tidak demikian: penyerang tidak dapat lolos dari swafoto dengan pemeriksaan liveness yang harus cocok dengan wajah yang direkam selama KYC onboarding pemilik sah.
1

Buat aturan sekali, di konsol

Transactions → Rules → Create Rule: kondisi amount gte 5000, tindakan Change status → AWAITING_USER, dan pilih alur kerja Autentikasi Biometrik Anda pada tindakan tersebut. Tambahkan kondisi risiko lain yang Anda inginkan - pihak lawan yang baru pertama kali, sidik jari perangkat baru, perubahan negara IP - sebagai kondisi tambahan atau aturan tambahan.
2

Kirim penarikan seperti biasa

Tidak ada yang berubah pada kode submit Anda. Ketika aturan terpicu, respons kembali dengan status: "AWAITING_USER" dan blok action_required bertipe verification_session:
3

Luncurkan pemeriksaan ulang

Serahkan session_token (atau url) ke integrasi verifikasi Didit Anda yang sudah ada, persis seperti di Meluncurkan sesi verifikasi. Karena sesi dibuat untuk vendor_data yang sama dengan subjek transaksi, Didit sudah memiliki wajah referensi terverifikasi pengguna dari onboarding - swafoto liveness yang disetujui, foto chip paspor, atau potret dokumen. Pengguna mengambil satu swafoto langsung; Didit menjalankan liveness plus pencocokan wajah 1:1 terhadap referensi yang tersimpan itu. Tidak ada pemindaian ulang dokumen, tidak ada onboarding ulang - proses yang hanya memerlukan beberapa detik, dan hanya pada transaksi yang memang memerlukannya.
4

Selesaikan berdasarkan hasil

Ketika sesi selesai, transaksi dievaluasi ulang secara otomatis: APPROVED jika pemeriksaan ulang berhasil, DECLINED jika gagal, dengan webhook transaction.status.updated dalam kedua kasus (reason: remediation_completed pada linimasa transaksi). Aplikasi Anda menerima hasilnya melalui callback bergaya onActionCompleted, GET /v1/transactions/{transaction_id}/, atau webhook.
Ini berhasil karena onboarding KYC, pemeriksaan ulang biometrik, dan keputusan transaksi berjalan di satu platform: wajah yang diambil saat onboarding menjadi referensi untuk step-up, graf perangkat menghubungkan sesi dengan transaksi, dan mesin aturan menyatukan keduanya. Tidak ada kode integrasi antarvendor, tidak ada ekspor gambar wajah, dan tidak ada kontrak biometrik terpisah. Pemeriksaan ulang ditagihkan sebagai fitur Autentikasi Biometrik standar ($0.10) hanya ketika benar-benar dijalankan.

SDK Web

submitTransaction tersedia di singleton Web SDK saat ini:
Hasilnya berupa { transactionId, status, travelRuleStatus?, actionRequired? }. Di payload tingkat SDK, Anda menulis category, details, dan customProperties; SDK memetakannya ke alias wire (type, info, props) untuk Anda. Error memiliki tipe DiditTransactionError:

SDK Native

API submitTransaction native tersedia di iOS dan Android SDK 4.1.0 (serta rilis React Native dan Flutter yang menggunakan versi tersebut). Berbeda dengan Web SDK, payload native langsung menggunakan nama field wire: type, info, dan props.
Setiap SDK juga menyediakan getTransaction(transactionToken, transactionId) untuk membaca ulang transaksi dengan token yang sama. SDK memanggilnya untuk Anda setelah alur tindakan dimulai, dan Anda dapat memanggilnya sendiri kapan saja. Di perangkat mobile, mekanisme pengiriman sidik jari perangkat sudah diterapkan pada semua panggilan jaringan SDK, sehingga pengiriman transaksi otomatis membawa intelijen perangkat yang sama.

Tanpa SDK

Semua yang dilakukan SDK adalah HTTPS biasa, jadi tidak ada yang mewajibkan penggunaan SDK. Ada dua bentuk integrasi yang setara: Hanya sisi server (tanpa token sama sekali). Kirim dengan POST /v3/transactions/ dari backend Anda menggunakan kunci API Anda. Respons (dan setiap GET /v3/transactions/{transaction_id}/ berikutnya) membawa blok action_required yang sama. Anda juga dapat menyertakan konteks device eksplisit per peserta, karena tidak ada SDK yang mengumpulkannya untuk Anda. Sisi klien dengan HTTP stack Anda sendiri. Buat token dengan POST /v3/transactions/sdk-token/, lalu panggil POST /v1/transactions/ dan GET /v1/transactions/{transaction_id}/ dari perangkat dengan header X-Transaction-Token. Pengikatan subjek yang sama dan penurunan IP/user-agent di sisi server juga berlaku. Lalu tangani action_required sendiri: Dan deteksi penyelesaian tanpa callback dari klien:
  • Webhook (direkomendasikan). transaction.status.updated dipicu saat tindakan yang tertunda menyelesaikan transaksi, dan travel_rule.status.updated dipicu pada setiap transisi pertukaran. Keduanya memuat informasi yang cukup untuk memperbarui catatan Anda tanpa polling.
  • Polling. Baca ulang transaksi (/v3/ dari backend Anda, atau /v1/ dengan token selama token masih berlaku): action_required kembali menjadi null setelah diselesaikan, dan status / travel_rule.status memuat hasilnya.
Desain ini tidak memiliki ketergantungan sekali pakai: widget, sesi verifikasi, dan backend Anda semuanya bertemu di status transaksi persisten yang sama, sehingga tab yang ditutup atau webhook yang terlewat selalu dapat dipulihkan dengan membaca ulang transaksi.

Webhook

Backend Anda tidak memerlukan aplikasi untuk mengirimkan laporan balik. Ketika transaksi yang dikirim memerlukan tindakan pengguna, webhook transaksi (transaction.created atau transaction.status.updated) menyertakan blok action_required yang sama, sehingga sistem Anda mengetahui tindakan yang tertunda meskipun aplikasi ditutup sebelum alur selesai. Tindakan verification_session disertai status AWAITING_USER, tetapi tindakan wallet_ownership tidak mengubah status transaksi dengan sendirinya, jadi baca action_required alih-alih status. Transisi Travel Rule juga mengirimkan travel_rule.status.updated.

Langkah berikutnya

Mengirim transaksi

API Create Transaction di sisi server dan referensi payload lengkap.

Travel Rule

Pertukaran pengirim-penerima terkelola, pengaturan, dan siklus hidupnya.

Widget kepemilikan dompet

Alur bukti kontrol yang di-hosting untuk tindakan wallet_ownership.

Webhook

transaction.created, transaction.status.updated, dan verifikasi tanda tangan.

Aturan

Tindakan aturan, termasuk yang membuat sesi verifikasi.

Status

Arti AWAITING_USER dalam siklus hidup transaksi.
Terakhir diubah pada 7 November 2026