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

# अलर्ट webhook: टीम अलर्ट आपके endpoint तक

> Didit से टीम अलर्ट अपने HTTPS endpoint पर भेजें: समीक्षा, AML, बिलिंग, webhook विफलता। HMAC-SHA256 से साइन, 24 घंटे तक पुनः प्रयास।



अलर्ट webhook प्रॉम्प्ट
        प्रॉम्प्ट को क्लिपबोर्ड पर कॉपी करें



      
      

\<pre>

\`Add an endpoint that receives Didit alert webhooks (team alerts, not verification results).

\## What to build
A public HTTPS POST endpoint (e.g. /api/didit/alerts) that:
1\. Reads the raw request body as bytes (do NOT parse and re-serialize the JSON before verifying)
2\. Checks that X-Timestamp is within 300 seconds of now
3\. Recomputes X-Signature-V2 = hex(HMAC-SHA256(secret, X-Timestamp + "." + rawBody)), where secret is the FULL signing secret including its "whsec_" prefix
4\. Compares the two signatures in constant time
5\. Parses the JSON, ignores an alert_id it already handled, answers 2xx within 5 seconds, then processes the alert asynchronously
6\. Answers a failed check with 400, not 401 (401, 403, 404 and 410 mark the destination for reconnection)

\## Headers
\- Content-Type: application/json
\- User-Agent: Didit-Alerts/1.0
\- X-Timestamp: Unix seconds, new on every attempt
\- X-Signature-V2: hex HMAC-SHA256 described above
This is NOT the signature scheme of verification webhooks. Alert webhooks send no X-Signature and no X-Signature-Simple.

\## Body (compact JSON, keys sorted)
\{
"alert_id": "alt_<16 hex characters>",  // the same on every retry: deduplicate on it
"created_at": 1791884460,                // Unix seconds when Didit created the alert
"data": { "event": "session_in_review", "label": "Session", "value": "#1042" },
"organization": { "id": "<uuid>", "name": "<your organization>" },
"severity": "info" | "warning" | "critical",
"subtitle": "<English explanation, can be empty>",
"title": "<English headline>",
"url": "<link to the Didit console>",
"webhook_type": "alert.<type>"
}

\## webhook_type values
\- alert.verification.in_review, alert.business_verification.in_review
\- alert.transaction.held, alert.aml.monitoring_hit
\- alert.billing.low_balance, alert.billing.autorefill_failed (data.paused), alert.billing.backup_card_charged
\- alert.webhook.delivery_failing
\- alert.service.degraded (data.status "degraded" or "down"), alert.service.recovered (data.status "recovered")
\- alert.test (sent from the console's Send test button)
Ignore webhook_type values and data keys you do not recognize.

\## Retries
\- 2xx = delivered. Redirects are not followed.
\- Timeout (5 s), connection failure, 5xx, 408, 425 or 429 = retried 5 times, after 1 min, 5 min, 30 min, 3 h and 20 h 24 min (about 24 h).
\- Any other response is final.
\- Test alerts are never retried.

\## Secret rotation
Rotating the secret in the console replaces it at once. There is no overlap and no header signed with the previous secret: deploy the new secret immediately.

Docs: /integration/alert-webhooks`

\</pre>



      
      

यहाँ पेस्ट करें

अलर्ट webhook आपकी टीम के अलर्ट आपके स्वामित्व वाले HTTPS endpoint पर भेजते हैं।
इनका उपयोग ऑन-कॉल टूल, टिकट कतार या अपने संचालन डैशबोर्ड को डेटा देने के लिए करें।अलर्ट webhook [सत्यापन webhook](https://docs.didit.me/hi/integration/webhooks.md) से अलग हैं।
सत्यापन webhook आपके एप्लिकेशन को सत्र, इकाई और लेन-देन के परिणाम भेजते हैं।
अलर्ट webhook आपकी टीम को बताते हैं कि किसी चीज़ पर ध्यान देने की ज़रूरत है: समीक्षा की प्रतीक्षा कर रहा सत्यापन, विफल भुगतान, या सेवा में कोई घटना।
इनके अपने payload, साइनिंग सीक्रेट, हस्ताक्षर और पुनः प्रयास का शेड्यूल होते हैं।## गंतव्य सेट करेंआप अलर्ट webhook **Business Console** में कॉन्फ़िगर करते हैं, API के माध्यम से नहीं।
जो सदस्य **संगठन सेटिंग्स** प्रबंधित कर सकते हैं, वे गंतव्य जोड़ सकते हैं, बदल सकते हैं और उनका परीक्षण कर सकते हैं।**1. गंतव्य जोड़ें****संगठन सेटिंग्स** > **टीम की सूचनाएँ** में, अपने endpoint के URL के साथ **अलर्ट webhook** गंतव्य जोड़ें।
URL में `https://` होना चाहिए और वह एक सार्वजनिक पते पर रिज़ॉल्व होना चाहिए।**2. साइनिंग सीक्रेट सहेजें**Didit पूरा साइनिंग सीक्रेट दिखाता है, जो `whsec_` से शुरू होता है, केवल एक बार।
इसे अभी सहेज लें: उसके बाद कंसोल केवल इसके अंतिम चार अक्षर दिखाता है।**3. अलर्ट को रूट करें**गंतव्य जोड़ने से अभी उस पर कुछ नहीं भेजा जाता।
जिन अलर्ट को आप इस गंतव्य पर प्राप्त करना चाहते हैं, उनके रूटिंग नियमों में गंतव्य जोड़ें।**4. परीक्षण भेजें**`alert.test` अलर्ट भेजने के लिए **परीक्षण भेजें** पर क्लिक करें, और जाँचें कि आपका endpoint उसे स्वीकार करता है।किसी संगठन की **टीम की सूचनाएँ** में अधिकतम 25 गंतव्य हो सकते हैं।केवल लाइव गतिविधि ही किसी गंतव्य तक पहुँचती है।
सैंडबॉक्स सत्यापन, व्यवसाय सत्यापन, लेन-देन और AML हिट के बारे में अलर्ट उसे कभी नहीं भेजे जाते।## अलर्ट के प्रकार| `webhook_type` | `severity` | Didit इसे कब भेजता है |
| - | - | - |
| `alert.verification.in_review` | `warning` | एक सत्यापन पूरा हुआ और मैन्युअल समीक्षा के लिए चिह्नित किया गया। |
| `alert.business_verification.in_review` | `warning` | एक व्यवसाय सत्यापन को मैन्युअल समीक्षा की ज़रूरत है। |
| `alert.transaction.held` | `warning` | आपके लेन-देन निगरानी नियमों ने एक लेन-देन को समीक्षा के लिए चिह्नित किया। |
| `alert.aml.monitoring_hit` | `warning` | सतत AML निगरानी को एक नया हिट मिला। |
| `alert.billing.low_balance` | `warning` | आपके संगठन का बैलेंस आपके सेट किए थ्रेशोल्ड से नीचे चला गया। |
| `alert.billing.autorefill_failed` | `critical` | बैलेंस का स्वचालित टॉप अप विफल हुआ क्योंकि कार्ड अस्वीकृत हो गया। |
| `alert.billing.backup_card_charged` | `warning` | एक स्वचालित शुल्क एक कार्ड पर अस्वीकृत हुआ और बैकअप कार्ड से भुगतान किया गया। |
| `alert.webhook.delivery_failing` | `warning` | आपके एक [सत्यापन webhook](https://docs.didit.me/hi/integration/webhooks.md) endpoint पर डिलीवरी विफल हो रही है। |
| `alert.service.degraded` | `critical` | आपके संगठन द्वारा उपयोग की जाने वाली एक सेवा ख़राब है या बंद है। |
| `alert.service.recovered` | `info` | वह सेवा सामान्य हो गई है। |
| `alert.test` | `info` | किसी ने गंतव्य पर **परीक्षण भेजें** पर क्लिक किया। |## Payloadहर अलर्ट एक JSON बॉडी के साथ `POST` होता है।
Didit बॉडी को संक्षिप्त JSON के रूप में भेजता है, जिसकी कुंजियाँ क्रमबद्ध हैं।
यह उदाहरण पढ़ने के लिए फ़ॉर्मैट किया गया है:```json theme={null}
{
  "alert_id": "alt_9f2c4e1a7b3d5c80",
  "created_at": 1791884460,
  "data": {
    "event": "session_in_review",
    "label": "Session",
    "value": "#1042"
  },
  "organization": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "Example Org"
  },
  "severity": "warning",
  "subtitle": "A KYC or KYB verification was completed and flagged for manual review.",
  "title": "Verification in review",
  "url": "https://business.didit.me/console/3fa85f64-5717-4562-b3fc-2c963f66afa6/9b2d1c4e-8f3a-4e6b-a1d2-5c7e9f0b3a14/verifications?session-id=1b4e28ba-2fa1-41d2-883f-0016d3cca427",
  "webhook_type": "alert.verification.in_review"
}
```| फ़ील्ड | प्रकार | विवरण |
| - | - | - |
| `webhook_type` | स्ट्रिंग | `alert.` के बाद अलर्ट का प्रकार। देखें [अलर्ट के प्रकार](#अलर्ट-के-प्रकार)। |
| `alert_id` | स्ट्रिंग | `alt_` के बाद 16 हेक्साडेसिमल अक्षर। अलर्ट के हर पुनः प्रयास में वही `alert_id` होता है, इसलिए डुप्लिकेट को अनदेखा करने के लिए इसका उपयोग करें। |
| `created_at` | पूर्णांक | Didit द्वारा अलर्ट बनाए जाने का Unix समय, सेकंड में। पुनः प्रयास पर यह वही रहता है। |
| `severity` | स्ट्रिंग | `info`, `warning` या `critical`। |
| `organization` | ऑब्जेक्ट | आपके संगठन का `id` (UUID) और `name`। |
| `title` | स्ट्रिंग | छोटी अंग्रेज़ी हेडलाइन। |
| `subtitle` | स्ट्रिंग | अंग्रेज़ी स्पष्टीकरण। खाली हो सकता है। |
| `data` | ऑब्जेक्ट | वह जिसके बारे में अलर्ट है। नीचे देखें। |
| `url` | स्ट्रिंग | Didit कंसोल में संबंधित पेज का लिंक। |`data` में हमेशा ये होते हैं:- `event`: इवेंट कुंजी, उदाहरण के लिए `session_in_review`।
- `label` और `value`: जिसके बारे में अलर्ट है, उदाहरण के लिए `Session` और `#1042`।कुछ अलर्ट प्रकार `data` में कुंजियाँ जोड़ते हैं:- `alert.billing.autorefill_failed` में `paused` जुड़ता है, एक बूलियन मान, जो `true` होता है जब ऑटो-रीफ़िल अब रोक दिया गया है और आपके कार्ड अपडेट करने तक रुका रहेगा।
- `alert.service.degraded` और `alert.service.recovered` में `service`, `status`, `incident_id`, `service_name`, `state`, `affected`, `country_name`, `started_at`, `resolved_at`, `duration_minutes`, `title` और `body` जुड़ते हैं।
  `status` `alert.service.degraded` पर `degraded` या `down` होता है, और `alert.service.recovered` पर `recovered`।
  `service` में [`GET /v3/status/`](https://docs.didit.me/hi/api-reference/service-status) की सेवा कुंजियाँ इस्तेमाल होती हैं, और `incident_id` वहाँ मौजूद किसी घटना के `id` से मेल खाता है।अलर्ट में कभी अंतिम उपयोगकर्ता का व्यक्तिगत डेटा या दस्तावेज़ का डेटा शामिल नहीं होता।
वे सत्र, लेन-देन या किसी अन्य आइटम की पहचान उसकी संख्या से करते हैं और कंसोल में उसका लिंक देते हैं।
`webhook_type` के वे मान और `data` की वे कुंजियाँ अनदेखी करें जिन्हें आप पहचानते नहीं, ताकि नए मान आपके endpoint को न तोड़ें।## अनुरोध हेडर| हेडर | उदाहरण | अर्थ |
| - | - | - |
| `Content-Type` | `application/json` | बॉडी JSON है। |
| `User-Agent` | `Didit-Alerts/1.0` | Didit के अलर्ट भेजने वाले की पहचान करता है। |
| `X-Timestamp` | `1791884462` | इस प्रयास पर Didit द्वारा हस्ताक्षर किए जाने का Unix समय, सेकंड में। हर प्रयास पर यह नया होता है। |
| `X-Signature-V2` | 64 हेक्साडेसिमल अक्षर | इस प्रयास का HMAC-SHA256 हस्ताक्षर। |## हस्ताक्षर सत्यापित करें`X-Signature-V2` उस स्ट्रिंग का hex-encoded HMAC-SHA256 है जो `<X-Timestamp>.<raw body>` है, और इसे आपके गंतव्य के हस्ताक्षर सीक्रेट से साइन किया जाता है।* Didit ने जैसा दिखाया था, पूरा सीक्रेट ठीक वैसे ही इस्तेमाल करें, जिसमें `whsec_` प्रिफ़िक्स भी शामिल हो।
* कच्चे अनुरोध के बाइट्स को वैसे ही साइन करें जैसे आपको मिले थे। JSON को parse करके फिर से serialize करने से बाइट्स बदल सकते हैं और जाँच विफल हो सकती है।
* हस्ताक्षरों की तुलना constant time में करें।
* ऐसे अनुरोध को अस्वीकार करें जिसका `X-Timestamp` आपकी घड़ी से 5 मिनट से ज़्यादा दूर हो। Didit हर प्रयास पर, हर पुनः प्रयास सहित, नया टाइमस्टैम्प लगाकर साइन करता है, इसलिए यह विंडो कभी भी वास्तविक पुनः प्रयास को अस्वीकार नहीं करती।
* विफल जाँच का उत्तर `400` से दें। `401`, `403`, `404` या `410` रिस्पॉन्स गंतव्य को फिर से कनेक्ट करने के लिए चिह्नित कर देता है (देखें [पुनः प्रयास](#पुनः-प्रयास))।> [!WARNING]
>
> अलर्ट webhook को सत्यापन webhook की तरह साइन नहीं किया जाता।
> Header का नाम भी `X-Signature-V2` ही है, लेकिन साइन की गई स्ट्रिंग अलग है, और अलर्ट webhook कोई `X-Signature` या `X-Signature-Simple` नहीं भेजते।
> अपने सत्यापन webhook सत्यापक को दोबारा इस्तेमाल न करें।### Node.js (Express)```javascript theme={null}
const express = require("express");
const crypto = require("crypto");

const app = express();
// The full secret Didit showed when you added the destination, including "whsec_".
const ALERT_SECRET = process.env.DIDIT_ALERT_SECRET;
const TOLERANCE_SECONDS = 300;

// express.raw keeps the body as the exact bytes Didit sent.
app.post("/api/didit/alerts", express.raw({ type: "application/json" }), (req, res) => {
  const timestamp = req.get("X-Timestamp") || "";
  const signature = Buffer.from(req.get("X-Signature-V2") || "", "utf8");

  const now = Math.floor(Date.now() / 1000);
  if (!/^\d+$/.test(timestamp) || Math.abs(now - Number(timestamp)) > TOLERANCE_SECONDS) {
    return res.status(400).send("Stale or missing timestamp");
  }

  const expected = Buffer.from(
    crypto.createHmac("sha256", ALERT_SECRET).update(`${timestamp}.`).update(req.body).digest("hex"),
    "utf8",
  );
  if (signature.length !== expected.length || !crypto.timingSafeEqual(signature, expected)) {
    return res.status(400).send("Invalid signature");
  }

  const alert = JSON.parse(req.body.toString("utf8"));
  res.sendStatus(204); // answer within 5 seconds, then process
  handleAlert(alert); // skip an alert_id you already handled
});
```### Python (Flask)```python theme={null}
import hashlib
import hmac
import json
import os
import time

from flask import Flask, request

app = Flask(__name__)
# The full secret Didit showed when you added the destination, including "whsec_".
ALERT_SECRET = os.environ["DIDIT_ALERT_SECRET"].encode("utf-8")
TOLERANCE_SECONDS = 300


@app.post("/api/didit/alerts")
def didit_alert():
    raw_body = request.get_data()  # the exact bytes Didit sent
    timestamp = request.headers.get("X-Timestamp", "")
    signature = request.headers.get("X-Signature-V2", "")

    try:
        too_old = abs(time.time() - int(timestamp)) > TOLERANCE_SECONDS
    except ValueError:
        too_old = True
    if too_old:
        return "Stale or missing timestamp", 400

    expected = hmac.new(ALERT_SECRET, timestamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected.encode(), signature.encode()):
        return "Invalid signature", 400

    alert = json.loads(raw_body)
    handle_alert(alert)  # skip an alert_id you already handled; keep this fast
    return "", 204
```### हस्ताक्षर सीक्रेट बदलेंआप **टीम की सूचनाएँ** में गंतव्य का सीक्रेट बदलते हैं।
Didit नया सीक्रेट एक बार दिखाता है और उसके बाद हर प्रयास को उसी से साइन करता है, जिसमें बदलाव से पहले बनाए गए अलर्ट के पुनः प्रयास भी शामिल हैं।
पुराना सीक्रेट तुरंत काम करना बंद कर देता है।
इसमें कोई ओवरलैप अवधि नहीं है, और कोई header पिछले सीक्रेट से बने हस्ताक्षर नहीं भेजता।
सीक्रेट बदलते ही नया सीक्रेट अपने endpoint पर तैनात कर दें।## पुनः प्रयासDidit किसी भी `2xx` रिस्पॉन्स को डिलीवर हुआ मानता है।
हर प्रयास आपके रिस्पॉन्स के लिए अधिकतम 5 सेकंड प्रतीक्षा करता है और रीडायरेक्ट का पालन नहीं करता।Didit टाइमआउट, कनेक्शन विफलता, `5xx` रिस्पॉन्स, या `408`, `425` या `429` रिस्पॉन्स के बाद अलर्ट का पुनः प्रयास करता है।
यह अधिकतम 5 बार, लगभग 24 घंटे की अवधि में पुनः प्रयास करता है:| पुनः प्रयास | पिछले प्रयास के बाद का विलंब |
| - | - |
| पहला | 1 मिनट |
| दूसरा | 5 मिनट |
| तीसरा | 30 मिनट |
| चौथा | 3 घंटे |
| पाँचवाँ | 20 घंटे 24 मिनट |बाकी हर रिस्पॉन्स अंतिम होता है, जिसमें `3xx` और कोई भी अन्य `4xx` शामिल है।
**परीक्षण भेजें** से भेजा गया परीक्षण केवल एक प्रयास किया जाता है और उसका कभी पुनः प्रयास नहीं होता।`401`, `403`, `404` या `410` रिस्पॉन्स भी गंतव्य को फिर से कनेक्ट करने के लिए चिह्नित कर देता है: कंसोल उसे **फिर से कनेक्ट करें** स्थिति के साथ दिखाता है।
Didit जब भेजता है, तब यदि कोई URL किसी निजी या अन्यथा अवरुद्ध पते पर रिज़ॉल्व होता है, तो भी यही होता है।
Didit गंतव्य पर नए अलर्ट भेजता रहता है, और अगली सफल डिलीवरी के बाद या जब आप उसका URL अपडेट करते हैं, तब वह फिर से सक्रिय हो जाता है।**टीम की सूचनाएँ** में **हाल की सूचनाएँ** हर डिलीवरी को उसके परिणाम के साथ सूचीबद्ध करती हैं, और आप वहाँ से विफल डिलीवरी का पुनः प्रयास कर सकते हैं।## संबंधित- [सत्यापन webhooks](https://docs.didit.me/hi/integration/webhooks.md): आपके एप्लिकेशन के लिए सत्र, इकाई और लेन-देन के परिणाम।
- [सेवा स्थिति](https://docs.didit.me/hi/api-reference/service-status.md): सार्वजनिक फ़ीड जिस पर `alert.service.degraded` और `alert.service.recovered` आधारित हैं।
- [मैन्युअल समीक्षा](https://docs.didit.me/hi/console/manual-review.md): समीक्षाधीन सत्यापन के साथ क्या करना है।


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