Langsung ke konten utama
Aktivitas autentikasi dan pengiriman webhook-nya yang bergantung pada rilis didokumentasikan di Event autentikasi dan webhook. Jangan mendaftarkan tipe event autentikasi yang tidak tercantum pada API tujuan saat ini.

Ringkasan

Webhook adalah cara Didit mengirim pembaruan real-time ke backend Anda setiap kali sesi verifikasi, sesi bisnis, pengguna vendor, bisnis vendor, atau transaksi berubah status. Dengan berlangganan satu atau beberapa tujuan webhook ke event yang Anda butuhkan, Anda dapat merespons begitu hasilnya siap, biasanya dalam hitungan detik setelah pengguna yang sedang diverifikasi menyelesaikan alurnya. Webhook adalah pola integrasi yang direkomendasikan. Polling GET /v3/session/{id}/decision/ didukung sebagai cadangan, tetapi lebih lambat, memerlukan lebih banyak permintaan, dan melewatkan event seperti data.updated, transaction.status.updated, serta perubahan pada tingkat entitas yang hanya dikirim melalui webhook. Perlakukan pengiriman webhook sebagai sumber kebenaran dan hanya lakukan polling saat cold start atau untuk rekonsiliasi. Bab ini dari pelajaran integrasi Didit Academy melanjutkan dari ikhtisar webhook. Pelajaran integrasi Academy membahas webhook mulai dari 3:12: menambahkan tujuan, memilih event, dan rahasia penandatanganan yang akan Anda verifikasi di bawah.
Pengguna Cloudflare / WAF. Didit mengirim webhook dari IP statis 18.203.201.92 dengan User-Agent: DiditWebhook/2.0 +https://didit.me. Jika edge Anda memblokir klien yang tidak dikenal, izinkan IP ini di Security > WAF > Tools > IP Access Rules dan pilih Izinkan untuk nama host penerima.

Jenis Event

Gunakan nilai persis di array subscribed_events pada tujuan. Tidak ada wildcard, jadi cantumkan setiap keluarga event yang ingin Anda terima. Anda juga dapat membagi event ke beberapa tujuan. Nilai dalam tabel ini adalah kumpulan lengkap event webhook yang dapat Anda langgani. Tidak ada session.status.updated, kyc.completed, atau event serupa. Satu-satunya pengiriman lain yang dilakukan Didit adalah callback kyb.registry_search.resolved yang tidak ditandatangani, yang dikirim ke webhook_url per permintaan yang Anda sertakan di POST /v3/kyb/search/, dan tidak pernah ke tujuan webhook.
Menu Try Webhook di Business Console > API & Webhooks mengirim payload lengkap untuk setiap event berikut: disetujui, ditolak, dalam peninjauan, nama Unicode, KYC/KYB, entitas, aktivitas, dan transaksi. Gunakan menu ini untuk memvalidasi endpoint Anda sebelum beralih ke lingkungan produksi.

Struktur payload

Amplop

Setiap webhook memakai amplop yang sama. Kolom selalu diserialisasi dengan sort_keys=True dan pemisah ringkas (, / :) agar payload yang sama menghasilkan tanda tangan yang sama di kedua sisi. Untuk event sesi (status.updated, data.updated pada sesi reguler dan sesi bisnis), amplop juga memuat:

Contoh amplop sesi

Objek decision memiliki skema yang sama dengan yang dikembalikan oleh GET /v3/session/{id}/decision/. Untuk referensi kolom kanonik per fitur (setiap properti pada id_verifications[], aml_screenings[], dll.), lihat Model data. Kami sengaja tidak menduplikasi tabel kolom per fitur di sini agar skema hanya ada di satu tempat.

Array jamak V3 (penting)

Di dalam decision, setiap hasil per fitur adalah array jamak sehingga satu alur kerja dapat menyertakan beberapa instans fitur yang sama (misalnya, beberapa pemeriksaan ID pada beberapa dokumen):
Setiap item memuat node_id yang cocok dengan graf alur kerja serta status per fitur. Jangan membaca kolom tunggal V2 lama (id_verification, nfc, liveness, face_match, phone, email, poa, aml, ip_analysis, database_validation). Kolom tersebut hanya muncul jika tujuan secara eksplisit ditetapkan ke webhook_version: "v2". Hasil Tanda Tangan Elektronik ada di signatures[], dan hanya tersedia jika alur kerja memiliki langkah Tanda Tangan Elektronik: satu item per penandatangan, dengan penandatangan, konfirmasi kode, sertifikat, stempel waktu, hash dan jalur unduh setiap dokumen, serta PDF bukti. Tidak ada event tanda tangan terpisah. status.updated memberi tahu Anda kapan harus membacanya. Lihat laporan Tanda Tangan Elektronik. Hasil Verifikasi bank ada di bank_verifications[], satu item per langkah Verifikasi bank. method pada setiap item menunjukkan cara rekening diverifikasi: open_banking (masuk ke bank), account_lookup (pemeriksaan rekening), atau fallback statement atau microdeposits. Nilainya null hingga rekening dievaluasi. Ketika pengguna memilih Continue without your bank, continued_without_bank bernilai true dan continuation menjelaskan alasannya. method kemudian bernilai none, kecuali sebuah percobaan sudah dievaluasi sebelumnya: lihat Ketika pengguna tidak dapat memverifikasi bank mereka. Rekening yang diverifikasi melalui pemeriksaan rekening tidak membaca data keuangan apa pun, sehingga financial_data.not_collected mencantumkan saldo, transaksi, atau penghasilan yang diminta langkah tersebut. Lihat Metode verifikasi bank.

Investigator block

decision V3 untuk sesi pengguna atau bisnis juga memuat investigator: tinjauan Investigator terbaru untuk sesi tersebut, atau null jika sesi tidak pernah memilikinya. Fitur pengumpulan dokumen, yaitu Dokumen KYB dan Document AI, tidak memiliki array khusus. Fitur ini muncul dalam daftar features[] pada keputusan sebagai { "feature": "DOCUMENT_AI", "node_id": "…" } (satu entri per node). Lihat Document AI. Keputusan Verifikasi Pengguna juga memuat satu objek biometric_consent tunggal: apakah sesi mewajibkan persetujuan biometrik eksplisit, trigger, status dari jawaban, dan buktinya. status: "pending" dengan reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK" berarti SDK native di bawah 4.10.0 merekam wajah tanpa langkah persetujuan. Lihat Persetujuan biometrik.

Kunci metode Verifikasi Identitas

Setiap item id_verifications[] menyebutkan metode Verifikasi Identitas yang menghasilkannya, sehingga handler dapat bercabang berdasarkan bukti yang benar-benar diterimanya: Handler yang sudah ada tetap berfungsi tanpa perubahan: sesi dokumen mengatur verification_method menjadi document dan membiarkan sisanya null. Tipe data per kolom ada di Model data.

Sesi dompet yang disetujui (status.updated)

Payload entitas

Status entitas adalah ACTIVE, FLAGGED, atau BLOCKED. user.data.updated dan business.data.updated tetap memuat kolom status dan menambahkan array changed_fields serta map changes berupa { field: { previous, current } }. Event business.* menggunakan vendor_business_id sebagai pengganti vendor_user_id.

Payload event transaksi

Webhook transaksi menggunakan infrastruktur fan-out yang sama dan format envelope yang sama, tetapi mengidentifikasi transaksi, bukan sesi:
action_required berisi null, atau tindakan pengguna yang tertunda (type wallet_ownership atau verification_session, dengan url-nya) yang dijelaskan di Tindakan pengguna yang diperlukan. Transaksi baru secara default berstatus APPROVED. Jika aturan, daftar blokir, atau alur kerja mengubah status saat pembuatan, payload transaction.created awal mencerminkan status akhir tersebut. transaction.status.updated memuat bentuk yang sama dengan status yang diperbarui. Status transaksi adalah APPROVED, IN_REVIEW, DECLINED, atau AWAITING_USER; severity adalah UNKNOWN / LOW / MEDIUM / HIGH / CRITICAL dan direction adalah INBOUND / OUTBOUND. transaction.created dan transaction.status.updated hanya dikirim untuk aplikasi live. Pertukaran Travel Rule di sandbox tetap mengirim travel_rule.status.updated dengan environment: sandbox.

Callback pencarian registri KYB

Alur POST /v3/kyb/search/ yang asinkron mengirim satu payload tambahan yang bukan event tujuan: ketika Anda meneruskan webhook_url ke permintaan pencarian, Didit mengirim POST callback kyb.registry_search.resolved ke URL tersebut setelah registri selesai diproses. Callback ini berbeda dari webhook tujuan dalam tiga hal:
  • Callback ini tanpa tanda tangan: tidak ada header X-Signature*. Sebagai gantinya, Didit memberi tanda X-Didit-Unsigned-Callback: true. Validasi dilakukan dengan mencocokkan request_id dengan id yang dikembalikan oleh permintaan pencarian.
  • Nama event berada di event_type (bukan webhook_type), dan tidak ada application_id ataupun environment.
  • timestamp dan created_at berupa integer epoch, seperti webhook lain tetapi tidak seperti created_at ISO pada endpoint pencarian.
Callback mengikuti kebijakan coba lagi yang sama dengan webhook tujuan (percobaan ulang memperbarui timestamp dan tetap tanpa tanda tangan). Lihat API Registri KYB untuk skema daftar kandidat lengkap.

Verifikasi tanda tangan

Setiap webhook ditandatangani dengan HMAC-SHA256 menggunakan secret_shared_key milik tujuan. Tiga header tanda tangan dikirim agar Anda dapat memilih header yang tetap berfungsi pada stack Anda: Header yang selalu dikirim Didit: Selama 24 jam setelah secret penandatanganan tujuan dirotasi, pengiriman juga membawa X-Signature-Previous, X-Signature-V2-Previous dan X-Signature-Simple-Previous (lihat Rotasi secret penandatanganan).

Rotasi secret penandatanganan

Anda merotasi secret penandatanganan tujuan di Business Console. Selama 24 jam setelah rotasi, setiap pengiriman ke tujuan tersebut membawa tiga header tambahan yang dibuat dengan secret yang digantikan: Handler yang menerima kecocokan pada header tanda tangan atau pada header -Previous-nya akan tetap memverifikasi saat Anda men-deploy secret baru: secret lama cocok dengan header -Previous, dan secret baru cocok dengan header biasa. Contoh kode di bawah melakukan hal ini. Deploy secret baru dalam 24 jam, karena setelah itu hanya secret baru yang lolos verifikasi. previous_secret_expires_at pada GET /v3/webhook/destinations/{destination_uuid}/ memberi tahu kapan 24 jam tersebut berakhir. Percobaan ulang dan pengiriman ulang ditandatangani ulang dengan secret tujuan yang berlaku saat dikirim, dan hanya membawa header -Previous selama 24 jam masih berjalan. Merotasi lagi dalam 24 jam akan langsung mencabut secret tertua: hanya secret yang berlaku sampai rotasi baru yang tetap lolos verifikasi melalui header -Previous, selama 24 jam sejak rotasi baru. Header -Previous hanya ada untuk tujuan webhook. secret_shared_key tingkat aplikasi yang menandatangani webhook_url lama tidak memiliki masa tumpang tindih: merotasinya dengan rotate_secret_key pada PATCH /v3/webhook/ langsung membatalkan secret lama.

X-Signature-Simple sudah tidak digunakan lagi

X-Signature-Simple mengautentikasi envelope, bukan payload. String kanonisnya hanya mencakup timestamp, session_id, status dan webhook_type. String ini tidak mencakup decision, serta resubmit_info, metadata, vendor_data atau event_id. Permintaan yang decision-nya ditulis ulang, sementara keempat kolom tersebut dibiarkan tidak berubah, tetap lolos verifikasi X-Signature-Simple.Kondisinya lebih lemah lagi pada event yang sama sekali tidak membawa session_id. Event transaksi (transaction_id, txn_id, amount, score) dan event entitas (vendor_user_id, vendor_business_id) ditandatangani dengan "{timestamp}::{status}:{webhook_type}", yang tidak mengidentifikasi transaksi atau entitas mana yang dimaksud event tersebut. Dua transaksi berbeda yang dilaporkan dengan status yang sama dalam detik yang sama akan memiliki X-Signature-Simple yang sama. Event travel_rule.status.updated, workflow.compliance_changed dan transaction_rule_suggestions.created juga tidak membawa status, sehingga ditandatangani dengan "{timestamp}:::{webhook_type}", misalnya "{timestamp}:::travel_rule.status.updated".Jika X-Signature-Simple adalah satu-satunya header yang Anda periksa, perlakukan semua data di luar keempat field tersebut sebagai tidak tepercaya, lalu ambil ulang record dari API: GET /v3/session/{session_id}/decision/ untuk sesi, GET /v3/transactions/{transaction_id}/ untuk transaksi. API adalah sumber data resmi.
Ini adalah batasan kompatibilitas, bukan sesuatu yang dapat kami perbaiki di tempat. String kanonis empat field adalah kontrak wire: setiap penerima yang memverifikasi X-Signature-Simple menghitung ulang persis keempat field tersebut, sehingga mengubah apa yang ditandatangani header ini akan diam-diam merusak semua verifikasi tersebut. Mencakup body juga memerlukan bentuk kanonis JSON yang ditetapkan dan dapat direproduksi byte demi byte oleh kedua sisi, dan Didit sudah menyediakannya sebagai X-Signature-V2. Daripada menambahkan varian kedua yang mencakup body dengan aturan kanonikalisasinya sendiri, header ini dibiarkan seperti sekarang dan dinyatakan sudah tidak digunakan lagi demi varian yang mencakup seluruh payload dan sudah ada. Artinya bagi Anda:
  • Tidak ada yang berubah di wire. X-Signature-Simple tetap dikirim pada setiap pengiriman, dihitung dengan cara yang sama. Verifier yang ada tetap berfungsi, dan kami akan mengumumkan setiap penghapusan jauh sebelumnya.
  • Integrasi baru wajib menggunakan X-Signature-V2. Header ini aman untuk middleware dan mencakup seluruh payload.
  • Jika Anda belum bisa beralih dari X-Signature-Simple, verifikasi header tersebut, lalu ambil record dari API, bukan membacanya dari body webhook.

Mengapa tiga varian?

Beberapa framework web (body parser Express, middleware Django, API gateway) diam-diam melakukan encode ulang JSON sebelum handler Anda membacanya. Jika body asli berisi "José" dan middleware Anda menulisnya ulang menjadi "José", byte-nya berubah meskipun datanya identik. Akibatnya X-Signature gagal. X-Signature-V2 dihitung dari bentuk JSON kanonis (kunci diurutkan, separator compact, Unicode tanpa escape) yang hampir semua middleware dapat mereproduksi secara deterministik. X-Signature-Simple yang tidak lagi direkomendasikan kembali ke penandatanganan string pendek yang tidak bergantung pada parser ketika bahkan itu pun gagal. Karena hanya menandatangani string pendek tersebut dan tidak pernah body, ia tidak dapat menjamin keaslian body.

Urutan verifikasi yang direkomendasikan

  1. Coba X-Signature-V2 terlebih dahulu. Enkode ulang JSON.parse(body) dengan kunci yang diurutkan dan Unicode tetap dipertahankan, lalu HMAC-SHA256(secret, canonical) dan timingSafeEqual terhadap header.
  2. Jika V2 gagal dan Anda dapat membaca byte mentah, coba X-Signature terhadap HMAC-SHA256(secret, rawBody).
  3. Hanya jika kedua langkah sebelumnya gagal, gunakan X-Signature-Simple yang sudah usang sebagai cadangan terhadap HMAC-SHA256(secret, "{timestamp}:{session_id}:{status}:{webhook_type}"). Cara ini hanya mengautentikasi amplop, jadi perlakukan decision di body sebagai tidak tepercaya dan ambil ulang dari GET /v3/session/{session_id}/decision/ sebelum Anda bertindak berdasarkannya.
Pada setiap langkah, jika header -Previous yang sesuai ada, terima kecocokan dari salah satu header (lihat Rotasi rahasia penandatanganan). Dalam semua kasus, tolak permintaan apa pun yang berusia lebih dari 5 menit (abs(now - X-Timestamp) > 300) untuk melindungi dari replay.

Kebijakan coba lagi

Jika endpoint Anda merespons dengan 5xx atau 404, Didit melakukan coba lagi hingga 2 kali dengan backoff eksponensial:
  • Coba lagi ke-1, sekitar 1 menit setelah kegagalan awal.
  • Coba lagi ke-2, sekitar 4 menit setelah coba lagi ke-1.
Setelah coba lagi kedua, pengiriman dibuang. Setiap percobaan pengiriman (awal + coba lagi) dicatat sebagai entri terpisah di Business Console pada tab Pengiriman milik tujuan, sehingga Anda dapat mengulang atau memeriksa percobaan mana pun. Setiap percobaan dalam log pengiriman tujuan memuat nomor attempt: 1 untuk pengiriman pertama sebuah event, dan satu angka lebih besar daripada nomor percobaan yang diulang untuk setiap coba lagi atau pengiriman ulang. Coba lagi otomatis dikirim ke URL tempat percobaan pertama dikirim, meskipun Anda sudah mengubah url tujuan setelahnya. Pengiriman ulang manual dikirim ke URL tujuan yang berlaku saat ini, sehingga memperbaiki URL juga memperbaiki pengiriman ulang. Aturan pengiriman lain yang perlu diketahui:
  • Permintaan HTTP keluar habis waktu (timeout) setelah 5 detik.
  • Didit memblokir pengiriman ke URL privat atau localhost sebagai pengaman SSRF, dan tidak pernah mengikuti pengalihan. Gunakan endpoint HTTPS publik yang merespons langsung.
  • url tujuan yang memuat backslash mentah, karakter kontrol, atau lebih dari satu @ pada bagian otoritas akan ditolak sebagai tidak valid. URL seperti itu tidak dapat dibuat, dan URL yang sudah ada tidak dapat dikirim ulang atau diputar ulang. Gunakan URL https://host/path biasa dengan paling banyak satu bagian userinfo (untuk URL webhook gaya basic-auth).
  • 2xx dianggap berhasil. Timeout dan kegagalan koneksi dianggap dapat dicoba lagi (muncul sebagai 504/503 di log pengiriman). Respons 3xx dan 4xx selain 404 tidak dicoba lagi.
  • Saat coba lagi, Didit menghitung ulang tanda tangan dengan X-Timestamp yang baru, sehingga pasangan timestamp dan tanda tangan selalu cocok.
  • Coba lagi dan pengiriman ulang ditandatangani dengan rahasia penandatanganan tujuan yang berlaku pada saat dikirim.

Urutan pengiriman

Didit tidak menjamin urutan webhook akan sampai kepada Anda. Setiap pengiriman diantrekan secara terpisah, dan coba lagi tiba beberapa menit setelah percobaan pertama, sehingga status.updated untuk Approved dapat sampai kepada Anda sebelum event yang lebih awal untuk In Progress. Rancang penerima webhook Anda untuk kondisi itu:
  • Perlakukan webhook sebagai sinyal bahwa sesuatu telah berubah. Jika urutan penting, panggil GET /v3/session/{session_id}/decision/ dan bertindak berdasarkan status terkini.
  • Jangan biarkan event yang lebih lama menimpa status yang lebih baru: bandingkan created_at event dengan yang terakhir Anda simpan untuk rekaman tersebut, dan abaikan event yang lebih lama.
  • Deduplikasi berdasarkan event_id, yang tetap sama di seluruh coba lagi.
Didit mengantrekan event dari transfer Travel Rule dalam urutan tertentu, yang dijelaskan di Travel Rule exchange status changed, tetapi coba lagi tetap dapat mengubah urutan kedatangannya.

Mengatur tujuan

Anda dapat mengelola tujuan dari Business Console > API & Webhooks atau melalui Management API.
1

Buat tujuan

Panggil POST /v3/webhook/destinations/ (atau klik Tambah tujuan di konsol) dengan label, url publik, webhook_version ("v3"), dan array subscribed_events yang berisi setiap keluarga event yang seharusnya diterima endpoint ini. Minimal satu event wajib diisi, dan tidak ada wildcard.
2

Simpan secret_shared_key

Respons pembuatan mengembalikan secret_shared_key milik tujuan. Simpan bersama rahasia server Anda yang lain: kunci ini hanya milik tujuan ini dan menjadi input untuk ketiga varian tanda tangan HMAC-SHA256. GET /v3/webhook/destinations/{destination_uuid}/ mengembalikannya lagi kepada pemanggil dengan kunci API dan kepada pengguna konsol yang dapat membaca webhook.
3

Implementasikan endpoint

Sediakan rute POST HTTPS publik, baca isi mentah, verifikasi tanda tangan (lebih baik gunakan X-Signature-V2), periksa jendela timestamp, lalu tentukan penanganan berdasarkan webhook_type. Kembalikan 2xx segera setelah Anda mengantrekan pekerjaan, dan lakukan pemrosesan berat secara asinkron.
4

Konfirmasi penerimaan

Pantau tab Pengiriman pada tujuan. Webhook yang sehat mengembalikan 200 dalam satu atau dua detik. 5xx/404 memicu kebijakan coba lagi Didit, dan kegagalan yang terus berlanjut dibuang setelah coba lagi kedua.
5

Iterasi dengan Try Webhook

Gunakan skenario konsol Try Webhook untuk menguji endpoint Anda dengan payload untuk skenario disetujui, ditolak, dalam peninjauan, KYB, entitas, aktivitas, dan transaksi sebelum mengaktifkan lalu lintas produksi.
Fitur pengujian webhook Didit di Business Console

Kirim webhook uji langsung dari Business Console untuk memvalidasi endpoint Anda sebelum ditayangkan ke produksi.

Anda dapat membuat tujuan sebanyak yang dibutuhkan. Pola yang umum adalah satu tujuan per konsumen, misalnya event KYC ke layanan autentikasi Anda, event KYB ke layanan operasi kepatuhan Anda, dan transaksi ke antrean penipuan Anda. Setiap tujuan memiliki rahasia, versi, dan daftar langganan sendiri, sehingga rahasia yang dirotasi atau penerapan yang bermasalah pada satu konsumen tidak memengaruhi konsumen lain.

Contoh kode

Untuk memastikan keamanan endpoint webhook Anda, verifikasi keaslian setiap permintaan masuk menggunakan secret_shared_key milik tujuan webhook.
Gunakan X-Signature-V2. Ini adalah varian yang paling tahan terhadap encoding ulang oleh middleware, dan varian ini sepenuhnya mengautentikasi isi (termasuk decision).

Node.js / Express (disarankan: X-Signature-V2)

Jika Anda dapat membaca byte mentah sebelum parser mana pun memprosesnya, varian X-Signature asli bekerja dengan cara yang sama, tetapi menandatangani isi mentah. Kami menyimpannya di bagian lama di bawah untuk kelengkapan.

Python / FastAPI (disarankan: X-Signature-V2)

PHP / Laravel (disarankan: X-Signature-V2)

Default JSON PHP tidak menghasilkan bentuk kanonik. Empat default harus ditimpa, dan jika salah satunya terlewat, byte yang ditandatangani akan berubah sehingga digest tidak pernah cocok: Jebakan objek kosong adalah yang paling merugikan. Payload Didit rutin memuat map kosong seperti risk_view.countries.risk_scores, risk_view.crimes.risk_scores, dan risk_view.custom_list, sehingga round-trip asosiatif akan merusak tanda tangan pada sesi yang disetujui pada umumnya, bukan hanya pada kasus langka.
Dua hal lain yang perlu diketahui:
  • Float bernilai bulat tidak memerlukan penanganan khusus di PHP. Didit menyerialisasinya sebagai integer (100.0 → 100), dan json_encode PHP menuliskan float bulat dengan cara yang sama, sehingga langkah shortenFloats tidak diperlukan, berbeda dengan contoh Node.js di atas.
  • Pertahankan serialize_precision pada -1 (default sejak PHP 7.1). Jika host Anda menimpanya menjadi 17, json_encode akan menuliskan 87.42 sebagai 87.420000000000002 dan setiap pemeriksaan X-Signature-V2 akan gagal.
Jika Anda tidak dapat membuat bentuk kanonik cocok, verifySignatureRaw di atas adalah opsi cadangan yang lebih sederhana: $request->getContent() milik Laravel mengembalikan byte asli, sehingga X-Signature bekerja selama tidak ada yang di depan PHP yang meng-encode ulang isi. Itulah kondisi yang memang dirancang untuk diatasi oleh X-Signature-V2, sehingga V2 dicoba terlebih dahulu.

Pengujian

Anda tidak perlu menjalankan verifikasi penuh untuk menguji endpoint Anda.
  • Dari Business Console > API & Webhooks > Try Webhook, pilih skenario (misalnya approved_full_features, declined_face_mismatch, in_review_aml_hit, business_session_approved, transaction_created, activity_created, user_status_updated) dan kirim webhook lengkap ke URL tujuan webhook Anda.
  • Setiap skenario ditandatangani dengan tiga header tanda tangan dan encoding kanonik yang sama dengan lalu lintas produksi, termasuk data uji unicode (approved_kyc_with_unicode) agar Anda dapat memastikan X-Signature-V2 berfungsi melalui middleware Anda. Pengiriman uji membawa data contoh dan ditandai dengan header tambahan X-Didit-Test-Webhook: true (serta sufiks (Test) pada User-Agent) agar Anda dapat memastikan pengiriman tersebut tidak memengaruhi status produksi.
  • Putar ulang pengiriman historis mana pun dari tab Pengiriman pada tujuan webhook jika Anda perlu men-debug regresi.
Untuk smoke test end-to-end, jalankan verifikasi nyata melalui alur kerja uji di aplikasi Anda sendiri. Webhook yang dihasilkan menggunakan format pesan, header, dan kebijakan coba lagi yang sama dengan skenario Try Webhook.

Contoh

Sesi KYC disetujui (status.updated)

Sesi ditolak dengan peringatan (status.updated)

Sesi bisnis disetujui (status.updated, KYB)

Transaksi dibuat (transaction.created)

Status pertukaran Travel Rule berubah (travel_rule.status.updated)

travel_rule_status berisi salah satu dari 13 status pertukaran yang didokumentasikan di Travel Rule. rail bernilai INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA, atau EMAIL (string kosong sebelum jalur dipilih, jika tidak ada jalur yang dapat ditentukan, dan selalu untuk registrasi sunrise), atau TEST_VASP untuk transfer sandbox yang dijawab oleh Didit Test VASP, dan direction bernilai INBOUND atau OUTBOUND. Event sandbox memuat "environment": "sandbox", dan event TEST_VASP juga memuat test_vasp: true dan test_vasp_scenario (skenario yang memberikan jawaban). Saat Didit membuat transaksi untuk transfer Travel Rule (panggilan POST /v3/transactions/, registrasi sunrise setelah deposit, permintaan masuk TRP, atau tahap masuk jalur INTERNAL), Didit mengirim event transaction.created untuk transaksi tersebut terlebih dahulu, lalu event travel_rule.status.updated untuk transfer tersebut setelahnya. Aturan yang mengubah status transaksi selama langkah ini juga dapat mengirim transaction.status.updated sebelum transaction.created, dan registrasi sunrise yang dilampirkan ke transaksi deposit yang sudah Anda buat tidak mengirim transaction.created. Setiap webhook dikirim dan dicoba ulang secara terpisah, sehingga event yang dicoba ulang tetap dapat tiba setelah event berikutnya: gunakan transaction_id sebagai kunci di handler Anda, dan baca ulang transaksi saat Anda membutuhkan status terkininya. Transfer yang dikirim melalui TRUST tidak pernah menerima event COMPLETED, karena TRUST tidak mengirimkan apa pun yang dapat dibaca Didit: transfer tetap berada di AWAITING_COUNTERPARTY hingga batas waktu konfirmasi, lalu berakhir EXPIRED. Melalui GTR, VerifyVASP dan Sygna Bridge, Didit membaca jawaban pihak lawan dari jaringan dan event mengikuti jawaban tersebut (lihat jaringan Travel Rule).

Kepatuhan alur kerja berubah (workflow.compliance_changed)

transition.from dan transition.to berisi salah satu dari compliant, gaps_detected, pending_change, unknown_coverage, atau not_evaluated. severity bernilai actionable saat celah terdeteksi, indicative untuk perubahan yang tertunda, dan informative saat celah sudah teratasi. Didit mengirim satu event untuk setiap alur kerja yang berubah.

Saran aturan transaksi dibuat (transaction_rule_suggestions.created)

kind bernilai ADD untuk aturan baru, TWEAK untuk perubahan pada aturan yang sudah ada, dan DISABLE untuk mematikan satu aturan. rule_id bernilai null untuk ADD. open_count adalah jumlah saran yang masih terbuka setelah proses berjalan, termasuk saran baru. Pengaturan saran aturan menentukan apakah webhook ini aktif atau nonaktif; lihat Webhook transaksi.

Event Investigator (investigator.*)

Dua belas event investigator.* menggunakan amplop yang sama (event_id, webhook_type, timestamp, created_at, application_id, environment) dan header tanda tangan yang sama dengan setiap event lainnya. Event ini hanya berisi ID dan angka: tidak pernah berisi nama, alasan yang diketik peninjau, narasi, atau apa pun yang ditulis pengguna akhir. Event ini tidak memiliki session_id; item yang dimaksud disebutkan di item.
provenance menyatakan versi Investigator yang menulis laporan:
  • engine adalah versi engine Investigator: ID delapan karakter yang tidak transparan. ID ini berubah setiap kali engine berubah, sehingga dua laporan dengan engine yang sama ditulis oleh engine yang sama.
  • agent_version adalah versi agen.
  • policy_version adalah versi kebijakan Anda sendiri yang diikuti laporan.
  • model_id adalah alias usang yang memuat nilai yang sama dengan engine. Baca engine sebagai gantinya.
  • prompt_hash tidak lagi dikirim.
item.kind menyebutkan jenis item (sesi, sesi bisnis, transaksi, atau kasus) dan item.id menyebutkan ID-nya. Timestamp yang berakhiran _at adalah string ISO 8601. Untuk berlangganan event ini, cantumkan string persisnya di subscribed_events, sama seperti event lainnya.

Status entitas pengguna berubah (user.status.updated)

Sesi yang diajukan ulang

Lama: X-Signature dengan isi mentah

X-Signature tetap dikirim pada setiap pengiriman. Nilainya adalah HMAC-SHA256 atas byte persis yang dikirim Didit (json.dumps(..., sort_keys=True, separators=(",", ":"))). Gunakan hanya ketika Anda dapat membaca body mentah sebelum middleware mana pun mengubahnya.

Lama: format webhook V2

Bidang di bawah ini hanya berlaku ketika tujuan dikunci ke webhook_version: "v2". Ada juga penguncian "v1" yang lebih lama (bentuk keputusan tunggal ketiga) untuk tujuan yang dibuat sebelum V2, jadi hubungi dukungan sebelum mengandalkannya. Integrasi baru sebaiknya menggunakan V3 (default), yang didokumentasikan di atas dan menggunakan array dalam bentuk jamak.
Objek per fitur itu sendiri sama di kedua versi: tujuan V2 menerima persis match_score, risk_score, score_breakdown, risk_view dan review_status untuk setiap hasil, serta skor agregat score seperti yang ada pada V3 (lihat laporan AML). Mengunci ke V2 mengubah letak laporan AML dalam decision, bukan isinya. Jika konsumen hilir Anda masih memerlukan bentuk V2, buat tujuan terpisah yang dikunci ke webhook_version: "v2" dan tetap gunakan V3 untuk konsumen baru Anda.

Terkait

  • API tujuan webhook: daftar, buat, perbarui, hapus tujuan, dan periksa log pengiriman.
  • Buat tujuan webhook: skema permintaan dan respons, termasuk secret_shared_key milik tujuan.
  • Model data: skema kanonik untuk setiap objek per fitur yang disematkan dalam decision.
  • Skema keputusan: daftar bidang lengkap untuk objek decision yang disematkan dalam webhook sesi.
  • Status verifikasi: nilai status yang tepat dan transisinya seperti yang dirujuk di atas.
  • Batas laju: batas yang berlaku saat melakukan polling GET /v3/session/{id}/decision/ sebagai cadangan.
Terakhir diubah pada 7 November 2026