---
title: "वेबहुक्स अवलोकन"
description: "ThunderPhone रीयल-टाइम इवेंट्स कैसे डिलीवर करता है, सिग्नेचर कैसे सत्यापित करें, और लेगेसी तथा एंडपॉइंट-आधारित डिलीवरी मॉडल की तुलना कैसे करें।"
---

ThunderPhone आपके सर्वर को HTTP `POST` रिक्वेस्ट भेजता है जब कॉल के दौरान
कुछ होता है — इनबाउंड कॉल शुरू होती है, कॉल समाप्त होती है, ग्रेडिंग
रन पूरा होता है, अलर्ट ट्रिगर होता है, और इसी तरह। **दो डिलीवरी
मॉडल** हैं:

<CardGroup cols={2}>
  <Card title="वेबहुक एंडपॉइंट्स (अनुशंसित)" icon="bolt" href="/hi/webhooks/endpoints">
    कई URLs, प्रति-एंडपॉइंट सीक्रेट्स, प्रति-एंडपॉइंट इवेंट फिल्टर्स,
    और ऑटोमैटिक रिट्राइज़।
    `GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints` के माध्यम से प्रबंधित करें।
  </Card>
  <Card title="सिंगल-URL लेगेसी वेबहुक" icon="link" href="/api-reference/organizations#legacy-single-url-webhook">
    प्रति संगठन एक URL। इसमें कॉल-लाइफसाइकल इवेंट्स शामिल होते हैं, जिनमें
    **ब्लॉकिंग** कॉन्फ़िगरेशन एक्सचेंज भी शामिल हैं। `GET/PUT /v1/webhook` पर प्रबंधित।
  </Card>
</CardGroup>

[इवेंट्स कैटलॉग](/hi/webhooks/events) में सूचीबद्ध सभी इवेंट टाइप्स
वेबहुक एंडपॉइंट्स के माध्यम से डिलीवर किए जाते हैं। छह कॉल-लाइफसाइकल इवेंट्स
(`telephony.incoming`, `telephony.complete`, `telephony.tool`,
`web.incoming`, `web.complete`, `web.tool`) **भी** लेगेसी सिंगल-URL
वेबहुक को भेजे जाते हैं — यदि आपके पास लेगेसी URL और मैचिंग एंडपॉइंट दोनों हैं,
तो आपको इवेंट **दोनों** पाथ्स पर मिलता है। ब्लॉकिंग
व्यवहार ([`telephony.incoming` / `web.incoming` कॉन्फ़िगरेशन
एक्सचेंज](/hi/webhooks/call-incoming) और वेबहुक-मोड
[टूल डिस्पैच](/hi/tools/overview)) केवल लेगेसी पाथ पर
होता है; प्रत्येक एंडपॉइंट डिलीवरी फायर-एंड-फॉरगेट नोटिफिकेशन होती है।

## पेलोड फ़ॉर्मेट

एंडपॉइंट डिलीवरी `data`, `event_id`, और
`type` के साथ एक JSON ऑब्जेक्ट होती है:

```json
{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}
```

`event_id` प्रत्येक उत्सर्जित इवेंट के लिए यूनिक होता है। यह रिट्राइज़
**और** इवेंट प्राप्त करने वाले प्रत्येक एंडपॉइंट पर समान होता है — इसके आधार पर डीडुप्लिकेट करें।

लेगेसी सिंगल-URL वेबहुक समान `type` और `data` भेजता है, लेकिन
`event_id` के **बिना**:

```json
{
  "type": "telephony.incoming",
  "data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}
```

वायर पर, प्रत्येक बॉडी कैनॉनिकली सीरियलाइज़ होती है — कीज़ वर्णानुक्रम में
सॉर्टेड, कोई व्हाइटस्पेस नहीं, UTF-8। इन डॉक्स में प्रिटी-प्रिंटेड उदाहरण
केवल पठनीयता के लिए हैं।

इवेंट टाइप्स और पेलोड फ़ील्ड्स की पूरी सूची के लिए [इवेंट्स कैटलॉग](/hi/webhooks/events) देखें।

## सिग्नेचर वेरिफिकेशन

हर अनुरोध में दो हस्ताक्षर होते हैं, दोनों एंडपॉइंट के `secret` (या लेगेसी डिलीवरी के लिए आपके संगठन-स्तरीय वेबहुक `secret`) के साथ HMAC-SHA256 द्वारा की किए जाते हैं:

- `X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>` टाइमस्टैम्प, मेथड, पाथ और क्वेरी, तथा रॉ बॉडी पर हस्ताक्षर करता है। इसे सत्यापित करें, और उन अनुरोधों को अस्वीकार करें जिनका `t` आपकी घड़ी से **5 मिनट** से अधिक अलग हो, ताकि कैप्चर किए गए अनुरोध को बाद में दोबारा चलाया न जा सके। भेजे जाने पर रिट्राई पर फिर से हस्ताक्षर किए जाते हैं।
- `X-ThunderPhone-Signature` केवल रॉ बॉडी पर हस्ताक्षर करता है। मौजूदा वेरिफ़ायर काम करते रहें, इसलिए इसे बिना बदलाव के अभी भी भेजा जाता है।

### चरण

1. किसी भी पार्सिंग से **पहले** हेडर, मेथड, रॉ पाथ और क्वेरी, और रॉ
   बॉडी पढ़ें।
2. अपने सीक्रेट के साथ
   `<t>\n<METHOD>\n<path and query>\n<body>` का हेक्स HMAC-SHA256 कंप्यूट करें।
3. अगर `t` 300 सेकंड से अधिक अलग है, या कॉन्स्टेंट-टाइम तुलना में परिणाम
   `v1` से मेल नहीं खाता है, तो रिक्वेस्ट अस्वीकार करें।

बॉडी कैनॉनिकल JSON सीरियलाइज़ेशन हैं (सॉर्ट की गई कीज़, कॉम्पैक्ट
सेपरेटर), और हम ठीक उन्हीं बाइट्स पर साइन करते हैं जो हम ट्रांसमिट करते हैं। [वेरिफिकेशन गाइड](/hi/guides/verify-webhook-signatures) में सटीक
साइन्ड स्ट्रिंग, एक वर्क्ड उदाहरण, SDK के बिना कोड, और लेगेसी
हेडर है।

<CodeGroup>
```python Python (Flask)
from flask import Flask, abort, request
from thunderphone import verify_signature

app = Flask(__name__)

@app.post("/thunderphone-webhook")
def handle():
    query = request.query_string.decode()
    if not verify_signature(
        request.headers.get("X-ThunderPhone-Signature-V2"),
        secret=WEBHOOK_SECRET,
        method=request.method,
        path=request.path + (f"?{query}" if query else ""),
        body=request.get_data(),  # raw bytes
    ):
        abort(401)
    event = request.get_json()
    # dispatch on event["type"] …
    return "", 204
```

```javascript Node.js (Express)
import express from "express";
import { verifySignature } from "@thunderphone/sdk";

const app = express();
app.post(
  "/thunderphone-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const ok = verifySignature({
      header: req.header("X-ThunderPhone-Signature-V2"),
      secret: process.env.WEBHOOK_SECRET,
      method: req.method,
      path: req.originalUrl,
      body: req.body,
    });
    if (!ok) return res.sendStatus(401);
    const event = JSON.parse(req.body.toString("utf8"));
    // dispatch on event.type …
    res.sendStatus(204);
  },
);
```
</CodeGroup>

## डिलीवरी सेमांटिक्स

ये सेमांटिक्स **एंडपॉइंट** डिलीवरी पर लागू होते हैं। लेगसी सिंगल-URL
webhook एक सिंगल सिंक्रोनस प्रयास है, जिसमें कोई रीट्राई नहीं होता, सिवाय
फोन-कॉल [`telephony.incoming`](/hi/webhooks/call-incoming)
कॉन्फ़िगरेशन एक्सचेंज के, जिसे एक बार रीट्राई किया जाता है।

<AccordionGroup>
  <Accordion title="रीट्राई">
    हर इवेंट का तुरंत एक बार प्रयास किया जाता है। कोई भी `2xx` रिस्पॉन्स
    डिलीवरी को स्वीकार करता है। किसी भी अन्य परिणाम पर (non-2xx,
    कनेक्शन एरर, टाइमआउट), हम पहले प्रयास के बाद **1 मिनट, 5 मिनट, 30 मिनट, 2 घंटे, 6 घंटे,
    12 घंटे और 24 घंटे** पर रीट्राई करते हैं — 24 घंटों में
    8 प्रयास। अगर हर प्रयास विफल हो जाता है, तो डिलीवरी रुक जाती है और एंडपॉइंट को
    [webhook endpoints](/hi/webhooks/endpoints) में `status="failing"` के रूप में
    मार्क किया जाता है; हम आपके संगठन के ओनर्स और एडमिन्स को ईमेल करते हैं
    और इसे डैशबोर्ड में दिखाते हैं। पेलोड के स्थायी रूप से स्वीकार होते ही `2xx` लौटाएँ;
    असिंक्रोनस रूप से प्रोसेस करें।
    एंडपॉइंट टेस्ट API से किए गए टेस्ट सेंड्स को पहले प्रयास के लगभग एक मिनट बाद
    एक रीट्राई मिलता है और वे कभी भी एंडपॉइंट का स्टेटस नहीं बदलते।
  </Accordion>

  <Accordion title="क्रम">
    डिलीवरी क्रम best-effort है। व्यवहार में हम इवेंट के एमिट होने के
    क्रम में डिलीवर करते हैं, लेकिन विफलता होने पर रिट्राई क्रम बदल सकते हैं।
    हमेशा `call_id` / ऑब्जेक्ट आईडी के आधार पर डीडुप्लिकेट और रिकन्साइल करें।
  </Accordion>

  <Accordion title="डुप्लिकेट">
    डिलीवरी **कम-से-कम-एक-बार** होती है: ऐसे रिस्पॉन्स के बाद रिट्राई जिसे
    हमने नहीं देखा, किसी इवेंट को डुप्लिकेट कर सकता है। हर रिट्राई में वही
    `event_id` होता है, इसलिए प्रोसेस किए गए आईडी स्टोर करें और दोहराव छोड़ दें।
    `event_id` एंडपॉइंट्स के बीच भी साझा होता है — एक ही इवेंट को सब्सक्राइब
    करने वाले दो एंडपॉइंट्स को वही `event_id` मिलता है।
  </Accordion>

  <Accordion title="टाइमआउट">
    एंडपॉइंट डिलीवरी में प्रति प्रयास **30 सेकंड** का टाइमआउट होता है। लेगसी
    पाथ पर, लाइव कॉल व्यवहार नियंत्रित करने वाले ब्लॉकिंग रिक्वेस्ट — 
    [`telephony.incoming` / `web.incoming`](/hi/webhooks/call-incoming)
    कॉन्फ़िगरेशन एक्सचेंज — फोन कॉल के पहले प्रयास के लिए **10 सेकंड** तक
    और उसके एक रीट्राई सहित पूरे एक्सचेंज के लिए **13 सेकंड** तक सीमित हैं,
    और विजेट सेशन के लिए **10 सेकंड** तक। धीमा रिस्पॉन्स कॉल पिकअप में देरी करता है,
    इसलिए कुछ सेकंड के भीतर जवाब देने का लक्ष्य रखें। Webhook-मोड [टूल डिस्पैच](/hi/tools/overview) डिफ़ॉल्ट रूप से 20 सेकंड
    की अनुमति देता है, और टूल डिक्लेरेशन टॉप-लेवल `timeout` सेट कर सकते हैं।
  </Accordion>

  <Accordion title="सोर्स IP">
    आउटबाउंड webhooks ThunderPhone की क्लाउड IP रेंज से आते हैं।
    अगर आपके फ़ायरवॉल को allowlist की आवश्यकता है, तो सपोर्ट से संपर्क करें और हम
    मौजूदा रेंज साझा करेंगे।
  </Accordion>
</AccordionGroup>

## लेगेसी और एंडपॉइंट-आधारित webhooks के बीच चयन

| सुविधा | लेगेसी (`/v1/webhook`) | एंडपॉइंट्स (`/v1/developer/webhook-endpoints`) |
|---------|------------------------|----------------------------------------------|
| URL की संख्या | प्रति संगठन 1 | प्रति संगठन कई |
| इवेंट कवरेज | केवल `telephony.*` / `web.*` | सभी 10 इवेंट प्रकार |
| इवेंट फ़िल्टर | — | प्रति एंडपॉइंट |
| रिट्राइ | कोई नहीं, फ़ोन-कॉल कॉन्फ़िगरेशन एक्सचेंज के लिए एक को छोड़कर | 24 घं. में 8 प्रयास |
| एनवेलप | `type` + `data` | `type` + `data` + `event_id` |
| सीक्रेट रोटेशन | एकल सीक्रेट को बदलता है | प्रति-एंडपॉइंट सीक्रेट |
| हटाए बिना अक्षम करें | `PUT /v1/webhook` के साथ `{"url": ""}` | `status=disabled` |
| स्टेटस दृश्यता | — | `active` / `disabled` / `failing` |
| ब्लॉकिंग कॉन्फ़िग एक्सचेंज | हाँ ([`telephony.incoming` / `web.incoming`](/hi/webhooks/call-incoming)) | कभी नहीं — केवल नोटिफिकेशन |
| इसके लिए सबसे उपयुक्त | डायनामिक कॉल कॉन्फ़िगरेशन | प्रोडक्शन में इवेंट कंजम्प्शन |

नए इंटीग्रेशन को एंडपॉइंट-आधारित webhooks के माध्यम से इवेंट कंज्यूम करने चाहिए।
लेगेसी URL केवल तभी रखें (या जोड़ें) जब आप पिकअप के समय कॉल को
डायनामिक रूप से कॉन्फ़िगर करते हैं या webhook-मोड tool dispatch का उपयोग करते हैं —
वे request/response एक्सचेंज केवल लेगेसी पथ पर चलते हैं।

---

## संबंधित

<CardGroup cols={2}>
  <Card title="इवेंट्स कैटलॉग" icon="list" href="/hi/webhooks/events">
    सभी इवेंट प्रकार और उनके पेलोड।
  </Card>
  <Card title="वेबहुक एंडपॉइंट्स" icon="bolt" href="/hi/webhooks/endpoints">
    कई एंडपॉइंट्स, इवेंट फ़िल्टर और सीक्रेट्स मैनेज करें।
  </Card>
  <Card title="telephony.incoming / web.incoming" icon="phone" href="/hi/webhooks/call-incoming">
    कॉल कॉन्फ़िगर करने के लिए आपके सर्वर को जिस ब्लॉकिंग रिक्वेस्ट का जवाब देना होगा।
  </Card>
  <Card title="telephony.complete / web.complete" icon="phone" href="/hi/webhooks/call-complete">
    ट्रांसक्रिप्ट, रिकॉर्डिंग और मेट्रिक्स के साथ कॉल के बाद का पेलोड।
  </Card>
</CardGroup>
