मुख्य सामग्री पर जाएं
प्रमाणीकरण गतिविधि और उससे जुड़ी रिलीज़-निर्भर webhook डिलीवरी Authentication events and webhooks में दस्तावेज़ित है। मौजूदा गंतव्य API के साथ सूची में न दिए गए auth इवेंट प्रकार रजिस्टर न करें।

अवलोकन

Webhooks वह तरीका हैं जिससे Didit जब भी कोई verification session, business session, vendor user, vendor business या transaction अपनी स्थिति बदलता है, तो आपके backend को real-time अपडेट भेजता है। एक या अधिक webhook गंतव्यों को उन इवेंट के लिए सब्सक्राइब करने से आप परिणाम तैयार होते ही प्रतिक्रिया दे सकते हैं, आमतौर पर उस क्षण से कुछ सेकंड के भीतर जब सत्यापन करने वाला उपयोगकर्ता अपना flow पूरा करता है। Webhooks अनुशंसित इंटीग्रेशन पैटर्न हैं। GET /v3/session/{id}/decision/ पर polling एक fallback के रूप में समर्थित है, लेकिन यह धीमा है, इसमें अधिक अनुरोध करने पड़ते हैं, और data.updated, transaction.status.updated तथा इकाई-स्तरीय बदलावों जैसे इवेंट छूट जाते हैं, जो केवल webhooks के माध्यम से भेजे जाते हैं। Webhook delivery को source of truth मानें और polling केवल cold start के समय या reconciliation के लिए करें। Didit Academy के इंटीग्रेशन पाठ का यह अध्याय webhooks के अवलोकन से आगे बढ़ता है। इंटीग्रेशन Academy का यह पाठ 3:12 से webhooks को कवर करता है: webhook गंतव्य जोड़ना, इवेंट चुनना, और वह साइनिंग सीक्रेट जिसे आप नीचे सत्यापित करेंगे।
Cloudflare / WAF उपयोगकर्ता। Didit स्थिर IP 18.203.201.92 से User-Agent: DiditWebhook/2.0 +https://didit.me के साथ webhooks भेजता है। यदि आपका edge अज्ञात क्लाइंट को ब्लॉक करता है, तो इस IP को Security > WAF > Tools > IP Access Rules में अनुमति दें और webhook प्राप्त करने वाले होस्टनेम के लिए Allow चुनें।

इवेंट प्रकार

किसी webhook गंतव्य के subscribed_events array में सटीक मान का उपयोग करें। यहाँ कोई वाइल्डकार्ड नहीं है। आप जिन भी परिवारों को प्राप्त करना चाहते हैं, उन सभी को सूचीबद्ध करें। आप इवेंट्स को कई webhook गंतव्यों में बाँट भी सकते हैं। इस तालिका में दिए गए मान सदस्यता के लिए उपलब्ध इवेंट का पूरा सेट हैं। इनमें session.status.updated, kyc.completed या इन जैसा कोई इवेंट नहीं है। Didit का एकमात्र अन्य डिलीवरी तंत्र बिना हस्ताक्षर वाला kyb.registry_search.resolved कॉलबैक है। यह कॉलबैक किसी गंतव्य पर नहीं जाता। यह उस प्रति-अनुरोध webhook_url पर जाता है जिसे आप POST /v3/kyb/search/ को भेजते हैं।
Business Console > API & Webhooks > Try Webhook मेनू इन सभी इवेंट के लिए पूरी तरह से बने पेलोड भेजता है, जिनमें स्वीकृत, अस्वीकृत, समीक्षाधीन, Unicode नाम, KYC/KYB, entity, activity और लेन-देन इवेंट शामिल हैं। लाइव होने से पहले अपने endpoint की जाँच करने के लिए इसका उपयोग करें।

payload संरचना

एन्वेलप

हर webhook का एक ही एन्वेलप होता है। फ़ील्ड हमेशा sort_keys=True के साथ और संक्षिप्त विभाजकों (, / :) का उपयोग करके सीरियलाइज़ किए जाते हैं, ताकि एक ही payload दोनों ओर एक ही हस्ताक्षर दे। सत्र इवेंट (सामान्य और व्यवसाय सत्रों पर status.updated, data.updated) के लिए एन्वेलप में ये फ़ील्ड भी होते हैं:

सत्र एन्वेलप उदाहरण

decision ऑब्जेक्ट वही स्कीमा है जो GET /v3/session/{id}/decision/ लौटाता है। हर सुविधा के फ़ील्ड का मानक संदर्भ (id_verifications[], aml_screenings[] आदि पर हर प्रॉपर्टी) डेटा मॉडल में है। हम जानबूझकर प्रति-सुविधा फ़ील्ड तालिकाएँ यहाँ नहीं दोहराते, ताकि स्कीमा केवल एक ही जगह रहे।

V3 बहुवचन सरणियाँ (महत्वपूर्ण)

decision के भीतर हर सुविधा-परिणाम एक बहुवचन सरणी है, ताकि एक ही वर्कफ़्लो में एक ही सुविधा के कई उदाहरण हो सकें (जैसे कई दस्तावेज़ों पर कई पहचान जाँचें):
हर आइटम में वर्कफ़्लो ग्राफ़ से मेल खाने वाला node_id और प्रति-सुविधा status होता है। न पढ़ें पुराने V2 एकवचन फ़ील्ड (id_verification, nfc, liveness, face_match, phone, email, poa, aml, ip_analysis, database_validation); ये केवल तब दिखते हैं जब कोई गंतव्य स्पष्ट रूप से webhook_version: "v2" पर पिन किया गया हो। ई-हस्ताक्षर परिणाम signatures[] में होते हैं, जो केवल तब मौजूद होते हैं जब वर्कफ़्लो में ई-हस्ताक्षर चरण हो: हर हस्ताक्षरकर्ता के लिए एक आइटम, जिसमें हस्ताक्षरकर्ता, कोड पुष्टि, प्रमाणपत्र, समय-मुहर, हर दस्तावेज़ के हैश और डाउनलोड पथ, तथा साक्ष्य PDF शामिल हैं। कोई अलग हस्ताक्षर इवेंट नहीं है: status.updated बताता है कि इन्हें कब पढ़ना है। ई-हस्ताक्षर रिपोर्ट देखें। बैंक सत्यापन परिणाम bank_verifications[] में होते हैं, हर बैंक सत्यापन चरण के लिए एक आइटम। हर आइटम का method बताता है कि खाता कैसे सत्यापित हुआ: open_banking (बैंक साइन-इन), account_lookup (खाता जाँच), या statement या microdeposits फ़ॉलबैक, और जब तक कोई खाता मूल्यांकित न हो, तब तक null। जब व्यक्ति ने अपने बैंक के बिना जारी रखें चुना, तब continued_without_bank true होता है और continuation बताता है कि ऐसा क्यों हुआ। तब method none होता है, जब तक पहले कोई प्रयास मूल्यांकित न हुआ हो: देखें जब व्यक्ति अपना बैंक सत्यापित नहीं कर पाता। खाता जाँच से सत्यापित खाते से कोई वित्तीय डेटा नहीं पढ़ा जाता, इसलिए financial_data.not_collected उन बैलेंस, लेन-देन या आय को सूचीबद्ध करता है जो चरण ने माँगे थे। देखें बैंक सत्यापन विधियाँ।

Investigator ब्लॉक

उपयोगकर्ता या व्यवसाय सत्र के लिए V3 decision में investigator भी शामिल होता है: सत्र की नवीनतम Investigator समीक्षा, या null यदि इस सत्र की कभी कोई समीक्षा नहीं हुई। दस्तावेज़-संग्रह सुविधाएँ (KYB दस्तावेज़ और Document AI) के लिए कोई समर्पित ऐरे नहीं है; ये निर्णय की features[] सूची में { "feature": "DOCUMENT_AI", "node_id": "…" } के रूप में दिखाई देती हैं (प्रत्येक नोड के लिए एक प्रविष्टि)। देखें Document AI। उपयोगकर्ता सत्यापन के निर्णयों में एक एकल biometric_consent ऑब्जेक्ट भी होता है: यह बताता है कि सत्र को स्पष्ट बायोमेट्रिक सहमति चाहिए थी या नहीं, साथ में trigger, उत्तर की status और उसका साक्ष्य। status: "pending" के साथ reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK" का अर्थ है कि 4.10.0 से पहले के नेटिव SDK ने सहमति चरण के बिना चेहरा कैप्चर किया। देखें बायोमेट्रिक सहमति।

पहचान सत्यापन विधि कुंजियाँ

हर id_verifications[] आइटम बताता है कि उसे कौन सी पहचान सत्यापन विधि ने बनाया, ताकि हैंडलर को मिले साक्ष्य के आधार पर शाखा बनाई जा सके: मौजूदा हैंडलर बिना बदलाव के काम करते रहते हैं: दस्तावेज़ सत्र verification_method को document पर सेट करता है और बाकी null छोड़ता है। फ़ील्ड-दर-फ़ील्ड प्रकार Data models में हैं।

स्वीकृत वॉलेट सत्र (status.updated)

एंटिटी इवेंट payloads

एंटिटी की स्थितियाँ ACTIVE, FLAGGED या BLOCKED हैं। user.data.updated और business.data.updated में status फ़ील्ड बना रहता है और इनमें एक changed_fields ऐरे तथा { field: { previous, current } } के रूप का changes मैप जुड़ता है। business.* इवेंट vendor_user_id के बजाय vendor_business_id का उपयोग करते हैं।

लेन-देन इवेंट payloads

लेन-देन webhooks उसी फ़ैन-आउट इन्फ्रास्ट्रक्चर पर चलते हैं और वही एनवेलप इस्तेमाल करते हैं, लेकिन सत्र के बजाय लेन-देन की पहचान करते हैं:
action_required या तो null है, या लंबित उपयोगकर्ता कार्रवाई (type wallet_ownership या verification_session, उसके url के साथ), जिसका वर्णन आवश्यक उपयोगकर्ता कार्रवाइयाँ में है। नए लेन-देन डिफ़ॉल्ट रूप से APPROVED होते हैं। यदि कोई नियम, ब्लॉकलिस्ट या वर्कफ़्लो बनाने के दौरान status बदलता है, तो प्रारंभिक transaction.created payload यही अंतिम status दिखाता है। transaction.status.updated में वही संरचना होती है, जिसमें अद्यतन status होता है। लेन-देन की स्थितियाँ हैं APPROVED, IN_REVIEW, DECLINED या AWAITING_USER; severity है UNKNOWN / LOW / MEDIUM / HIGH / CRITICAL और direction है INBOUND / OUTBOUND। transaction.created और transaction.status.updated केवल live एप्लिकेशन के लिए भेजे जाते हैं। सैंडबॉक्स Travel Rule एक्सचेंज environment: sandbox के साथ travel_rule.status.updated भेजते हैं।

KYB रजिस्ट्री खोज कॉलबैक

असिंक्रोनस POST /v3/kyb/search/ प्रवाह एक अतिरिक्त payload भेजता है जो webhook गंतव्य इवेंट नहीं है: जब आप खोज अनुरोध को webhook_url देते हैं, तो रजिस्ट्री का उत्तर मिलते ही Didit उस URL पर kyb.registry_search.resolved कॉलबैक POST करता है। यह webhook गंतव्य से तीन तरह से अलग है:
  • यह अहस्ताक्षरित है: इसमें कोई X-Signature* हेडर नहीं होता। इसके बजाय Didit इसे X-Didit-Unsigned-Callback: true से चिह्नित करता है; request_id को खोज अनुरोध द्वारा लौटाए गए id से मिलाकर इसकी पुष्टि करें।
  • इवेंट का नाम event_type में रहता है (webhook_type में नहीं), और इसमें application_id या environment नहीं होता।
  • timestamp और created_at epoch पूर्णांक हैं, जैसे अन्य webhooks में, लेकिन खोज endpoint के ISO created_at से अलग।
यह कॉलबैक वही पुनः प्रयास नीति मानता है जो webhook गंतव्य पर लागू होती है (पुनः प्रयास timestamp को फिर से स्टैम्प करते हैं और अहस्ताक्षरित ही रहते हैं)। पूरी उम्मीदवार-सूची स्कीमा के लिए KYB Registry API देखें।

हस्ताक्षर सत्यापन

हर webhook, webhook गंतव्य के secret_shared_key का उपयोग करके HMAC-SHA256 से हस्ताक्षरित होता है। तीन हस्ताक्षर हेडर भेजे जाते हैं, ताकि आप अपने स्टैक के लिए वह हेडर चुन सकें जो सही तरह काम करे: Didit हमेशा ये हेडर भेजता है: किसी webhook गंतव्य का साइनिंग सीक्रेट रोटेट करने के बाद 24 घंटों तक डिलीवरी में X-Signature-Previous, X-Signature-V2-Previous और X-Signature-Simple-Previous भी आते हैं (देखें साइनिंग सीक्रेट रोटेशन)।

साइनिंग सीक्रेट रोटेशन

आप Business Console में webhook गंतव्य का साइनिंग सीक्रेट रोटेट करते हैं। रोटेशन के बाद 24 घंटों तक, उस गंतव्य की हर डिलीवरी में तीन और हेडर आते हैं, जो बदले गए सीक्रेट से बनाए जाते हैं: जो हैंडलर किसी सामान्य हस्ताक्षर हेडर या उसके -Previous हेडर में से किसी एक के मिलान को स्वीकार करता है, वह नया सीक्रेट डिप्लॉय करते समय भी सत्यापन जारी रखता है: पुराना सीक्रेट -Previous हेडर से मेल खाता है और नया सीक्रेट सामान्य हेडर से। नीचे दिए गए कोड सैंपल यही करते हैं। नया सीक्रेट 24 घंटों के भीतर डिप्लॉय करें, क्योंकि उसके बाद केवल नया सीक्रेट ही सत्यापित होता है। GET /v3/webhook/destinations/{destination_uuid}/ पर previous_secret_expires_at बताता है कि 24 घंटे कब खत्म होते हैं। रिट्राई और रीसेंड, भेजे जाने के समय गंतव्य के वर्तमान सीक्रेट से फिर से साइन किए जाते हैं, और -Previous हेडर केवल तब तक रहते हैं जब तक 24 घंटे चलते हैं। 24 घंटों के भीतर फिर से रोटेट करने पर सबसे पुराना सीक्रेट तुरंत रद्द हो जाता है: -Previous हेडर के माध्यम से नए रोटेशन से ठीक पहले जो सीक्रेट वर्तमान था, केवल उसी से सत्यापन होता रहता है, और यह नए रोटेशन से 24 घंटों तक चलता है। -Previous हेडर केवल webhook गंतव्यों के लिए होते हैं। लीगेसी webhook_url पर हस्ताक्षर करने वाला एप्लिकेशन-स्तरीय secret_shared_key कोई ओवरलैप नहीं देता: PATCH /v3/webhook/ पर rotate_secret_key से इसे रोटेट करने पर पुराना सीक्रेट तुरंत अमान्य हो जाता है।

X-Signature-Simple अप्रचलित है

X-Signature-Simple envelope को प्रमाणित करता है, payload को नहीं। इसकी कैनोनिकल स्ट्रिंग में केवल timestamp, session_id, status और webhook_type शामिल हैं। इसमें decision शामिल नहीं है, और न ही resubmit_info, metadata, vendor_data या event_id। यदि decision बदल दिया गया हो और बाकी चार फ़ील्ड अछूते हों, तब भी वह अनुरोध X-Signature-Simple सत्यापन पास कर देता है।जिन इवेंट्स में बिल्कुल session_id नहीं होता, उन पर यह और भी कमज़ोर है। लेन-देन इवेंट्स (transaction_id, txn_id, amount, score) और इकाई इवेंट्स (vendor_user_id, vendor_business_id) "{timestamp}::{status}:{webhook_type}" पर हस्ताक्षर करते हैं, जो यह नहीं बताता कि इवेंट किस लेन-देन या entity से जुड़ा है। एक ही सेकंड में, एक ही status के साथ रिपोर्ट किए गए दो अलग लेन-देन का X-Signature-Simple एक जैसा होता है। travel_rule.status.updated, workflow.compliance_changed और transaction_rule_suggestions.created इवेंट्स में भी status नहीं होता, इसलिए वे "{timestamp}:::{webhook_type}" पर हस्ताक्षर करते हैं, जैसे "{timestamp}:::travel_rule.status.updated"।यदि X-Signature-Simple ही एकमात्र हेडर है जिसकी आप जाँच करते हैं, तो उन चार फ़ील्ड्स के बाहर की हर चीज़ को अविश्वसनीय मानें और रिकॉर्ड API से फिर से प्राप्त करें। सेशन के लिए GET /v3/session/{session_id}/decision/ और लेन-देन के लिए GET /v3/transactions/{transaction_id}/ का उपयोग करें, क्योंकि वही आधिकारिक स्रोत है।
यह एक संगतता सीमा है, जिसे हम जगह पर पैच नहीं कर सकते। चार-फ़ील्ड वाली कैनोनिकल स्ट्रिंग एक वायर अनुबंध है: X-Signature-Simple सत्यापित करने वाला हर रिसीवर ठीक इन्हीं चार फ़ील्ड्स की पुनर्गणना करता है, इसलिए हेडर क्या साइन करता है, यह बदलने से उन सभी का सत्यापन चुपचाप टूट जाएगा। बॉडी को कवर करने के लिए JSON के एक ऐसे निर्दिष्ट कैनोनिकल रूप की भी ज़रूरत है, जिसे दोनों पक्ष बाइट-दर-बाइट दोहरा सकें, और Didit यह रूप X-Signature-V2 के रूप में पहले से देता है। अपने कैनोनिकलाइज़ेशन नियमों वाला दूसरा बॉडी-कवरिंग वेरिएंट जोड़ने के बजाय यह हेडर जैसा है वैसा ही रहता है, और मौजूदा पूर्ण-payload वेरिएंट्स के पक्ष में अप्रचलित घोषित किया गया है। इसका आपके लिए अर्थ है:
  • वायर पर कुछ नहीं बदलता। X-Signature-Simple हर डिलीवरी में पहले की तरह उसी तरीके से गणना करके भेजा जाता रहेगा। मौजूदा सत्यापनकर्ता काम करते रहेंगे, और किसी भी हटाने की घोषणा हम पहले से बहुत पहले करेंगे।
  • नए इंटीग्रेशन को X-Signature-V2 का उपयोग करना चाहिए। यह मिडलवेयर-सुरक्षित है और पूरे payload को कवर करता है।
  • यदि आप X-Signature-Simple से हट नहीं सकते, तो उसे सत्यापित करें, और फिर webhook बॉडी से पढ़ने के बजाय रिकॉर्ड API से प्राप्त करें।

तीन वेरिएंट क्यों?

कुछ वेब फ़्रेमवर्क (Express body parsers, Django middleware, API gateways) आपके handler द्वारा JSON पढ़ने से पहले उसे चुपचाप दोबारा एन्कोड कर देते हैं। यदि मूल बॉडी में "José" था और आपका middleware उसे दोबारा लिखकर "José" कर देता है, तो डेटा एक जैसा होने पर भी बाइट्स बदल जाते हैं। इससे X-Signature विफल हो जाता है। X-Signature-V2 एक कैनोनिकल JSON रूप से बनता है (कुंजियाँ क्रमबद्ध, कॉम्पैक्ट separators, बिना escape किया गया Unicode), जिसे लगभग हर middleware निर्धारित रूप से दोहरा देता है। और अप्रचलित X-Signature-Simple, जब वह भी विफल हो जाए, तब केवल एक छोटी, parser से स्वतंत्र स्ट्रिंग पर हस्ताक्षर करने पर निर्भर रहता है। चूँकि वह केवल उस छोटी स्ट्रिंग पर हस्ताक्षर करता है और कभी बॉडी पर नहीं, इसलिए वह बॉडी की पुष्टि नहीं कर सकता।

अनुशंसित सत्यापन क्रम

  1. सबसे पहले X-Signature-V2 आज़माएँ। JSON.parse(body) को sorted keys और Unicode को यथावत रखते हुए फिर से encode करें, फिर HMAC-SHA256(secret, canonical) निकालें और हेडर से timingSafeEqual द्वारा तुलना करें।
  2. अगर V2 विफल हो और आप raw bytes पढ़ सकते हैं, तो HMAC-SHA256(secret, rawBody) के विरुद्ध X-Signature आज़माएँ।
  3. केवल तभी जब दोनों विफल हों, अप्रचलित X-Signature-Simple का सहारा लें, जो HMAC-SHA256(secret, "{timestamp}:{session_id}:{status}:{webhook_type}") के विरुद्ध जाँचा जाता है। यह केवल आवरण को प्रमाणित करता है, इसलिए body के decision को अविश्वसनीय मानें और कार्रवाई से पहले GET /v3/session/{session_id}/decision/ से उसे फिर से प्राप्त करें।
हर चरण पर, जब मेल खाने वाला -Previous हेडर मौजूद हो, तो किसी भी हेडर पर मिलान स्वीकार करें (देखें साइनिंग सीक्रेट रोटेशन)। सभी मामलों में, replay हमलों से बचाव के लिए ऐसे किसी भी अनुरोध को अस्वीकार करें जिसका टाइमस्टैम्प वर्तमान समय से 5 मिनट से अधिक अलग हो (abs(now - X-Timestamp) > 300), चाहे वह अनुरोध बहुत पुराना हो या भविष्य का हो।

पुनः प्रयास नीति

अगर आपका endpoint 5xx या 404 से जवाब देता है, तो Didit क्रमशः बढ़ते अंतराल के साथ 2 बार तक पुनः प्रयास करता है:
  • पहला पुनः प्रयास: पहली विफलता के लगभग 1 मिनट बाद।
  • दूसरा पुनः प्रयास: पहले पुनः प्रयास के लगभग 4 मिनट बाद।
दूसरे पुनः प्रयास के बाद डिलीवरी छोड़ दी जाती है। हर डिलीवरी प्रयास (पहला और पुनः प्रयास) Business Console में गंतव्य के डिलीवरी टैब के अंतर्गत अलग प्रविष्टि के रूप में लॉग होता है, ताकि आप किसी भी प्रयास को दोबारा चला या जाँच सकें। गंतव्य के डिलीवरी लॉग में हर प्रयास का attempt नंबर होता है: किसी इवेंट की पहली डिलीवरी के लिए 1, और प्रत्येक पुनः प्रयास या पुनः भेजने के लिए, दोहराए जा रहे प्रयास के नंबर से एक अधिक। स्वचालित पुनः प्रयास हमेशा उसी URL पर जाते हैं जिस पर पहला प्रयास भेजा गया था, भले ही उसके बाद आपने गंतव्य का url बदल दिया हो। मैनुअल पुनः भेजना गंतव्य के वर्तमान URL पर जाता है, इसलिए URL ठीक करने से पुनः भेजना भी ठीक हो जाता है। डिलीवरी से जुड़े अन्य नियम जो जानना ज़रूरी है:
  • बाहरी HTTP अनुरोध 5 सेकंड में timeout हो जाता है।
  • Didit SSRF सुरक्षा के रूप में private या localhost URLs पर डिलीवरी ब्लॉक करता है और redirects का कभी पालन नहीं करता। ऐसा सार्वजनिक HTTPS endpoint उपयोग करें जो सीधे जवाब दे।
  • गंतव्य का url जिसमें कच्चा बैकस्लैश, नियंत्रण वर्ण, या प्राधिकरण भाग में एक से अधिक @ हो, malformed मानकर अस्वीकार किया जाता है। ऐसा URL न बनाया जा सकता है, और न ही मौजूदा URL को फिर से डिलीवर या replay किया जा सकता है। सरल https://host/path URL उपयोग करें, जिसमें अधिकतम एक उपयोगकर्ता-सूचना भाग हो (basic-auth शैली वाले webhook URLs के लिए)।
  • 2xx को सफलता माना जाता है। Timeouts और connection failures पुनः प्रयास योग्य माने जाते हैं (डिलीवरी लॉग में ये 504/503 के रूप में दिखते हैं)। 3xx और 404 के अलावा 4xx responses का पुनः प्रयास नहीं होता।
  • पुनः प्रयास पर Didit नए X-Timestamp के साथ हस्ताक्षरों की फिर से गणना करता है, इसलिए timestamp और signature की जोड़ी हमेशा मेल खाती है।
  • पुनः प्रयास और पुनः भेजे गए अनुरोध भेजे जाने के समय गंतव्य के वर्तमान signing secret से signed होते हैं।

डिलीवरी का क्रम

Didit यह गारंटी नहीं देता कि webhooks आप तक किस क्रम में पहुँचेंगे। हर डिलीवरी अलग कतार में रखी जाती है, और पुनः प्रयास पहले प्रयास के कई मिनट बाद पहुँचता है। इसलिए Approved के लिए status.updated आपके पास In Progress के पहले वाले इवेंट से पहले पहुँच सकता है। अपना प्राप्तकर्ता इसी के अनुसार बनाएँ:
  • webhook को इस संकेत के रूप में लें कि कुछ बदला है। जब क्रम मायने रखता है, तो GET /v3/session/{session_id}/decision/ कॉल करें और वर्तमान status के आधार पर कार्य करें।
  • पुराने इवेंट को नई स्थिति पर अधिलेखित न करने दें: इवेंट के created_at की तुलना उस रिकॉर्ड के लिए अंतिम संग्रहीत इवेंट से करें, और पुराने इवेंट को अनदेखा करें।
  • दोहराव की पहचान event_id से करें, जो पुनः प्रयासों में भी वही रहता है।
Didit Travel Rule transfer के इवेंट एक निश्चित क्रम में कतार में रखता है, जिसका वर्णन Travel Rule exchange status changed में है, लेकिन पुनः प्रयास फिर भी उस क्रम को बदल सकता है जिसमें वे पहुँचते हैं।

गंतव्य सेट अप करना

आप गंतव्य Business Console > API & Webhooks से या Management API के माध्यम से प्रबंधित कर सकते हैं।
1

गंतव्य बनाएँ

label, सार्वजनिक url, webhook_version ("v3"), और subscribed_events array के साथ POST /v3/webhook/destinations/ कॉल करें (या कंसोल में गंतव्य जोड़ें पर क्लिक करें)। इस array में वे सभी इवेंट परिवार शामिल हों जिन्हें यह endpoint प्राप्त करना चाहिए। कम से कम एक इवेंट आवश्यक है, और कोई wildcard नहीं है।
2

secret_shared_key सहेजें

बनाने की प्रतिक्रिया में गंतव्य की secret_shared_key मिलती है। इसे अपने अन्य सर्वर secrets के साथ सहेजें: यह केवल इसी गंतव्य का है और तीनों HMAC-SHA256 हस्ताक्षर वैरिएंट का इनपुट है। GET /v3/webhook/destinations/{destination_uuid}/ इसे API कुंजी वाले कॉलर और उन कंसोल उपयोगकर्ताओं को फिर से लौटाता है जो webhooks पढ़ सकते हैं।
3

endpoint लागू करें

एक सार्वजनिक HTTPS POST route बनाएँ, raw body पढ़ें, signature सत्यापित करें (X-Signature-V2 को प्राथमिकता दें), timestamp window जाँचें, फिर webhook_type के आधार पर dispatch करें। काम कतार में डालते ही 2xx लौटाएँ, और भारी प्रोसेसिंग asynchronously करें।
4

प्राप्ति की पुष्टि करें

गंतव्य का डिलीवरी टैब देखें। स्वस्थ webhooks एक-दो सेकंड के भीतर 200 लौटाते हैं। 5xx/404 प्रतिक्रियाएँ Didit की पुनः प्रयास नीति को ट्रिगर करती हैं, और लगातार विफलताएँ दूसरे पुनः प्रयास के बाद छोड़ दी जाती हैं।
5

Try Webhook से दोहराएँ

लाइव ट्रैफ़िक चालू करने से पहले, Try Webhook कंसोल परिदृश्यों का उपयोग करके अपने endpoint को स्वीकृत, अस्वीकृत, समीक्षाधीन, KYB, entity, activity, और transaction payloads से गुज़ारें।
Business Console में Didit webhook testing सुविधा

Business Console से सीधे परीक्षण webhook भेजें, ताकि लाइव जाने से पहले अपने endpoint को सत्यापित कर सकें।

आप जितने चाहें गंतव्य बना सकते हैं। एक आम पैटर्न है हर उपभोक्ता के लिए एक गंतव्य: जैसे KYC इवेंट → आपकी प्रमाणीकरण सेवा, KYB इवेंट → आपकी अनुपालन संचालन सेवा, और लेन-देन → आपकी फ़्रॉड कतार। हर गंतव्य का अपना secret, version और सब्सक्रिप्शन सूची होता है, इसलिए किसी एक उपभोक्ता पर बदली हुई सीक्रेट कुंजी या खराब परिनियोजन का असर बाकी पर नहीं पड़ता।

कोड उदाहरण

अपने webhook endpoint की सुरक्षा सुनिश्चित करने के लिए, गंतव्य की secret_shared_key का उपयोग करके आने वाले अनुरोधों की प्रामाणिकता जाँचें।
X-Signature-V2 का उपयोग करें। यह मिडलवेयर द्वारा री-एन्कोड किए जाने के प्रति सबसे अधिक सहनशील वैरिएंट है, और यह decision सहित पूरी बॉडी को पूरी तरह प्रमाणित करता है।

Node.js / Express (अनुशंसित: X-Signature-V2)

यदि आप किसी भी parser के छूने से पहले raw bytes पढ़ सकते हैं, तो मूल X-Signature वैरिएंट भी इसी तरह काम करता है, लेकिन वह raw body पर हस्ताक्षर करता है। पूर्णता के लिए हमने इसे नीचे legacy सेक्शन में रखा है।

Python / FastAPI (अनुशंसित: X-Signature-V2)

PHP / Laravel (अनुशंसित: X-Signature-V2)

PHP के JSON डिफ़ॉल्ट canonical form को नहीं दोहराते। उनमें से चार को ओवरराइड करना पड़ता है, और इनमें से किसी एक को भी छोड़ने से हस्ताक्षर वाले bytes बदल जाते हैं और digest कभी मेल नहीं खाता: खाली-ऑब्जेक्ट वाला जाल सबसे ज़्यादा परेशान करता है। Didit payloads में नियमित रूप से खाली maps होते हैं, जैसे risk_view.countries.risk_scores, risk_view.crimes.risk_scores और risk_view.custom_list, इसलिए associative round-trip किसी दुर्लभ अपवाद में नहीं, बल्कि सामान्य स्वीकृत सत्रों पर भी हस्ताक्षर तोड़ देता है।
दो और बातें जानने लायक हैं:
  • PHP में पूर्ण-मान वाले floats को किसी विशेष प्रबंधन की आवश्यकता नहीं होती। Didit उन्हें integers के रूप में serialize करता है (100.0 → 100), और PHP का json_encode पूर्ण float को उसी तरह लिखता है, इसलिए ऊपर Node.js उदाहरण वाले shortenFloats चरण की ज़रूरत नहीं है।
  • serialize_precision को -1 पर रखें (PHP 7.1 से यही डिफ़ॉल्ट है)। यदि आपका होस्ट इसे 17 पर सेट करता है, तो json_encode 87.42 को 87.420000000000002 लिखता है और हर X-Signature-V2 जाँच विफल हो जाती है।
यदि आप canonical form को मेल नहीं खिला पा रहे, तो ऊपर दिया verifySignatureRaw सरल fallback है: Laravel का $request->getContent() बिना छेड़े bytes लौटाता है, इसलिए X-Signature तब तक काम करता है जब तक PHP के सामने वाली कोई चीज़ बॉडी को री-एन्कोड नहीं करती। X-Signature-V2 इसी स्थिति में टिके रहने के लिए डिज़ाइन किया गया है, और इसी कारण V2 को पहले आज़माया जाता है।

टेस्टिंग

अपने endpoint को परखने के लिए आपको पूरा सत्यापन चलाने की आवश्यकता नहीं है।
  • Business Console > API & Webhooks > Try Webhook से कोई परिदृश्य चुनें (जैसे approved_full_features, declined_face_mismatch, in_review_aml_hit, business_session_approved, transaction_created, activity_created, user_status_updated) और अपने गंतव्य URL पर एक पूर्ण webhook भेजें।
  • हर परिदृश्य उन्हीं तीन हस्ताक्षर हेडरों और canonical encoding के साथ हस्ताक्षरित होता है, जैसी प्रोडक्शन ट्रैफ़िक में होती है, जिसमें यूनिकोड टेस्ट डेटा (approved_kyc_with_unicode) भी शामिल है, ताकि आप पुष्टि कर सकें कि आपके मिडलवेयर के माध्यम से X-Signature-V2 काम करता है। टेस्ट डिलीवरी में नमूना डेटा होता है और उन्हें एक अतिरिक्त X-Didit-Test-Webhook: true हेडर से चिह्नित किया जाता है (और User-Agent पर (Test) प्रत्यय लगा होता है), ताकि आप उन्हें प्रोडक्शन स्थिति से बाहर रख सकें।
  • किसी regression को डीबग करने के लिए, गंतव्य के Deliveries टैब से किसी भी पिछली डिलीवरी को रीप्ले करें।
एंड-टू-एंड स्मोक टेस्ट के लिए, अपने एप्लिकेशन में किसी टेस्ट वर्कफ़्लो के माध्यम से एक वास्तविक सत्यापन चलाएँ। इसके परिणामस्वरूप बने webhooks वही एनवेलप, हेडर और पुनः प्रयास नीति इस्तेमाल करते हैं जो Try Webhook परिदृश्यों में होती है।

Examples

स्वीकृत KYC सत्र (status.updated)

चेतावनियों के साथ अस्वीकृत सत्र (status.updated)

व्यवसाय सत्र स्वीकृत (status.updated, KYB)

लेन-देन बनाया गया (transaction.created)

Travel Rule एक्सचेंज स्थिति बदली गई (travel_rule.status.updated)

travel_rule_status इस Travel Rule में दर्ज 13 एक्सचेंज स्थितियों में से कोई एक लेता है। rail INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA या EMAIL होता है (कोई रेल चुने जाने से पहले, या यदि कोई रेल तय नहीं हो सकी हो तो खाली स्ट्रिंग, और सनराइज़ पंजीकरण में हमेशा खाली स्ट्रिंग)। Didit Test VASP द्वारा उत्तर दिए गए सैंडबॉक्स ट्रांसफ़र के लिए यह TEST_VASP होता है। direction INBOUND या OUTBOUND होता है। सैंडबॉक्स इवेंट में "environment": "sandbox" आता है, और TEST_VASP इवेंट में test_vasp: true और test_vasp_scenario (वह परिदृश्य जिसने उत्तर दिया) भी आते हैं। जब Didit किसी Travel Rule ट्रांसफ़र के लिए लेन-देन बनाता है (POST /v3/transactions/ कॉल, जमा के बाद का सनराइज़ पंजीकरण, आने वाली TRP पूछताछ, या INTERNAL रेल का इनबाउंड चरण), तो वह उस लेन-देन के लिए पहले transaction.created इवेंट भेजता है और उसके बाद ट्रांसफ़र के travel_rule.status.updated इवेंट। उस चरण के दौरान कोई नियम लेन-देन की स्थिति बदले, तो वह transaction.created से पहले transaction.status.updated भी भेज सकता है। और यदि सनराइज़ पंजीकरण आपके पहले से बनाए गए जमा लेन-देन से जुड़ता है, तो उसके लिए transaction.created नहीं भेजा जाता। हर webhook अलग से भेजा और दोबारा भेजा जाता है, इसलिए दोबारा भेजा गया इवेंट बाद वाले इवेंट के बाद भी पहुँच सकता है: अपना हैंडलर transaction_id पर रखें, और जब आपको लेन-देन की मौजूदा स्थिति चाहिए हो, तो उसे दोबारा पढ़ें। TRUST के ज़रिए भेजे गए ट्रांसफ़र को कभी COMPLETED इवेंट नहीं मिलता, क्योंकि TRUST कोई ऐसा जवाब नहीं लौटाता जिसे Didit पढ़ सके: वह पुष्टि की समय-सीमा तक AWAITING_COUNTERPARTY पर रहता है और फिर EXPIRED पर समाप्त हो जाता है। GTR, VerifyVASP और Sygna Bridge पर Didit नेटवर्क से काउंटरपार्टी का जवाब पढ़ता है, और इवेंट उसके बाद आता है (देखें Travel Rule नेटवर्क)।

वर्कफ़्लो अनुपालन बदला गया (workflow.compliance_changed)

transition.from और transition.to इनमें से कोई एक होते हैं: compliant, gaps_detected, pending_change, unknown_coverage या not_evaluated। severity actionable होता है जब कमियाँ पाई गई हों, indicative लंबित बदलाव के लिए, और informative जब कमियाँ सुलझ गई हों। Didit हर उस वर्कफ़्लो के लिए एक इवेंट भेजता है जो बदला हो।

लेन-देन नियम सुझाव बनाए गए (transaction_rule_suggestions.created)

kind नए नियम के लिए ADD, किसी मौजूदा नियम में बदलाव के लिए TWEAK, और किसी नियम को बंद करने के लिए DISABLE होता है। ADD के लिए rule_id null होता है। open_count रन के बाद भी खुले सुझावों की संख्या है, जिनमें नए सुझाव भी शामिल हैं। नियम-सुझाव सेटिंग्स से यह webhook चालू या बंद होता है; देखें लेन-देन webhook।

Investigator इवेंट (investigator.*)

बारह investigator.* इवेंट वही एनवेलप (event_id, webhook_type, timestamp, created_at, application_id, environment) और वही हस्ताक्षर हेडर इस्तेमाल करते हैं जो बाकी हर इवेंट करता है। इनमें केवल आईडी और आँकड़े होते हैं: कभी कोई नाम नहीं, समीक्षक का टाइप किया कारण नहीं, कोई विवरण नहीं और अंतिम उपयोगकर्ता का लिखा कुछ भी नहीं। इनमें session_id नहीं होता; जिस आइटम के बारे में इवेंट है, वह item में दिया जाता है।
provenance बताता है कि रिपोर्ट किस संस्करण के Investigator ने लिखी:
  • engine Investigator इंजन का संस्करण है: आठ अक्षरों का एक अपारदर्शी आईडी। यह तब बदलता है जब इंजन बदलता है, इसलिए एक ही engine वाली दो रिपोर्ट एक ही इंजन ने लिखी हैं।
  • agent_version एजेंट का संस्करण है।
  • policy_version आपकी अपनी नीति का वह संस्करण है जिसका रिपोर्ट ने पालन किया है।
  • model_id एक अप्रचलित उपनाम है जिसमें वही मान है जो engine में है। engine पढ़ें।
  • prompt_hash अब नहीं भेजा जाता।
item.kind आइटम का प्रकार बताता है (सत्र, व्यवसाय सत्र, लेन-देन या केस) और item.id उसकी आईडी। _at पर खत्म होने वाले टाइमस्टैम्प ISO 8601 स्ट्रिंग हैं। इन इवेंट की सदस्यता के लिए किसी भी दूसरे इवेंट की तरह subscribed_events में सटीक स्ट्रिंग सूचीबद्ध करें।

उपयोगकर्ता इकाई की स्थिति बदली गई (user.status.updated)

पुनः सबमिट किया गया सत्र

पुराना: कच्ची बॉडी के साथ X-Signature

X-Signature हर डिलीवरी में अब भी भेजा जाता है; यह Didit द्वारा भेजे गए ठीक बाइट्स पर HMAC-SHA256 है (json.dumps(..., sort_keys=True, separators=(",", ":")))। इसका उपयोग केवल तभी करें जब आप किसी भी मिडलवेयर द्वारा इसे बदलने से पहले कच्ची बॉडी पढ़ सकते हों।

पुराना: V2 webhook प्रारूप

नीचे दिए गए फ़ील्ड केवल तभी लागू होते हैं जब कोई webhook गंतव्य webhook_version: "v2" पर पिन किया गया हो। V2 से पहले बनाए गए गंतव्यों के लिए एक और भी पुराना "v1" पिन मौजूद है (एक तीसरी, एकवचन निर्णय संरचना), इस पर भरोसा करने से पहले सहायता से संपर्क करें। नए इंटीग्रेशन को V3 (डिफ़ॉल्ट) का उपयोग करना चाहिए, जो ऊपर दस्तावेज़ित है और जिसमें बहुवचन सरणियाँ होती हैं।
प्रति-सुविधा ऑब्जेक्ट दोनों संस्करणों में एक जैसे हैं: V2 गंतव्य को वही प्रति-हिट match_score, risk_score, score_breakdown, risk_view और review_status, तथा समग्र score प्राप्त होते हैं जो V3 में होते हैं (देखें AML रिपोर्ट)। V2 पर पिन करने से बदलता केवल यह है कि decision में AML रिपोर्ट कहाँ स्थित है, उसमें क्या है वह नहीं। यदि कोई डाउनस्ट्रीम उपभोक्ता अब भी V2 संरचना चाहता है, तो webhook_version: "v2" पर पिन किया हुआ एक अलग गंतव्य बनाएँ और अपने नए उपभोक्ताओं को V3 पर रखें।

संबंधित

  • Webhook गंतव्य API: गंतव्यों की सूची देखें, बनाएँ, अपडेट करें, हटाएँ और डिलीवरी लॉग देखें।
  • Webhook गंतव्य बनाएँ: अनुरोध/रिस्पॉन्स स्कीमा, जिसमें गंतव्य का secret_shared_key शामिल है।
  • डेटा मॉडल: decision में एम्बेड किए गए हर प्रति-सुविधा ऑब्जेक्ट की कैनोनिकल स्कीमा।
  • निर्णय स्कीमा: सत्र webhook में एम्बेड किए गए decision ऑब्जेक्ट की पूरी फ़ील्ड सूची।
  • सत्यापन स्थितियाँ: ऊपर संदर्भित सटीक status मान और उनके बदलाव।
  • रेट लिमिटिंग: वे सीमाएँ जो फ़ॉलबैक के रूप में GET /v3/session/{id}/decision/ पोलिंग करते समय लागू होती हैं।
अंतिम संशोधन 7 नवंबर 2026