वेबहुक्स का अवलोकन
ThunderPhone रीयल-टाइम इवेंट्स कैसे डिलीवर करता है, सिग्नेचर कैसे सत्यापित करें, और लेगेसी तथा एंडपॉइंट-आधारित डिलीवरी मॉडल की तुलना।
ThunderPhone आपके सर्वर को HTTP POST अनुरोध भेजता है जब कॉल के दौरान घटनाएँ होती हैं — इनबाउंड कॉल शुरू होती है, कॉल समाप्त होती है, ग्रेडिंग रन पूरा होता है, अलर्ट ट्रिगर होता है, आदि। दो डिलीवरी मॉडल हैं:
कई URL, प्रति-एंडपॉइंट सीक्रेट, प्रति-एंडपॉइंट इवेंट फ़िल्टर,
और ऑटोमैटिक रीट्राइ।
GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints के ज़रिए प्रबंधित करें।
प्रति संगठन एक URL। इसमें ब्लॉकिंग कॉन्फ़िगरेशन एक्सचेंज सहित
कॉल-लाइफसाइकल इवेंट होते हैं। GET/PUT /v1/webhook पर प्रबंधित।
इवेंट्स कैटलॉग में सभी दस इवेंट प्रकार वेबहुक एंडपॉइंट के माध्यम से
डिलीवर किए जाते हैं। छह कॉल-लाइफसाइकल इवेंट
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) भी लेगसी सिंगल-URL
वेबहुक पर भेजे जाते हैं — यदि आपके पास लेगसी URL और मैचिंग एंडपॉइंट दोनों हैं,
तो आपको इवेंट दोनों पथों पर मिलता है। ब्लॉकिंग व्यवहार
(telephony.incoming / web.incoming कॉन्फ़िगरेशन
एक्सचेंज और वेबहुक-मोड
टूल डिस्पैच) विशेष रूप से
लेगसी पथ पर उपलब्ध है; प्रत्येक एंडपॉइंट डिलीवरी फायर-एंड-फॉरगेट
नोटिफ़िकेशन है।
पेलोड फ़ॉर्मैट
एंडपॉइंट डिलीवरी data, event_id, और type वाला एक 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 के बिना:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}नेटवर्क पर, प्रत्येक बॉडी कैनॉनिकली सीरियलाइज़ होती है — कुंजियाँ वर्णानुक्रम में सॉर्ट की जाती हैं, कोई व्हाइटस्पेस नहीं होता, और UTF-8 का उपयोग होता है। इन डॉक्स में प्रिटी-प्रिंट किए गए उदाहरण केवल पठनीयता के लिए हैं।
इवेंट प्रकारों और पेलोड फ़ील्ड की पूरी सूची के लिए इवेंट्स कैटलॉग देखें।
सिग्नेचर सत्यापन
हर अनुरोध में X-ThunderPhone-Signature हेडर में रॉ रिक्वेस्ट
बॉडी पर HMAC-SHA256 सिग्नेचर होता है। साइनिंग की एंडपॉइंट का
secret है (या लेगसी डिलीवरी के लिए आपका संगठन-स्तरीय वेबहुक
secret)।
चरण
- किसी भी पार्सिंग से पहले रॉ रिक्वेस्ट बॉडी पढ़ें।
hmac_sha256(secret, body).hexdigest()कैलकुलेट करें।X-ThunderPhone-Signatureहेडर से कॉन्स्टेंट टाइम में तुलना करें।
हम ठीक उन्हीं बाइट्स पर साइन करते हैं जिन्हें हम भेजते हैं, और वे बाइट्स कैनोनिकल JSON सीरियलाइज़ेशन हैं (सॉर्ट कीज़, कॉम्पैक्ट सेपरेटर)। इसलिए रॉ बॉडी के विरुद्ध सत्यापन हमेशा काम करता है — और यदि आपका फ्रेमवर्क आपको केवल पार्स किया हुआ JSON देता है, तो उसे सॉर्ट कीज़ और कॉम्पैक्ट सेपरेटर के साथ फिर से सीरियलाइज़ करने पर समान बाइट्स मिलती हैं। दोनों तरीके सत्यापन गाइड में शामिल हैं।
import hmac
import hashlib
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature or "")
# Example Flask handler
from flask import Flask, request, abort
app = Flask(__name__)
@app.post("/thunderphone-webhook")
def handle():
body = request.get_data()
sig = request.headers.get("X-ThunderPhone-Signature", "")
if not verify_signature(body, sig, WEBHOOK_SECRET):
abort(401)
event = request.get_json()
# dispatch on event["type"] …
return "", 204import crypto from "node:crypto";
import express from "express";
function verifySignature(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
if (!signature || expected.length !== signature.length) return false;
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}
const app = express();
app.post(
"/thunderphone-webhook",
express.raw({ type: "application/json" }),
(req, res) => {
const sig = req.header("X-ThunderPhone-Signature") || "";
if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
// dispatch on event.type …
res.sendStatus(204);
},
);डिलीवरी सेमांटिक्स
ये सेमांटिक्स एंडपॉइंट डिलीवरी पर लागू होते हैं। लेगेसी सिंगल-URL वेबहुक बिना किसी पुनः प्रयास के एकल सिंक्रोनस प्रयास है।
पुनः प्रयास
प्रत्येक इवेंट का तुरंत एक बार प्रयास किया जाता है। कोई भी 2xx रिस्पॉन्स
डिलीवरी की पुष्टि करता है। किसी भी अन्य परिणाम पर (नॉन-2xx,
कनेक्शन एरर, टाइमआउट) हम पहले प्रयास के 1 मिनट, 5 मिनट, 30 मिनट, 2 घंटे, 6 घंटे,
12 घंटे और 24 घंटे बाद पुनः प्रयास करते हैं — 24 घंटों में
8 प्रयास। यदि प्रत्येक प्रयास विफल होता है, तो डिलीवरी रुक जाती है और एंडपॉइंट को
वेबहुक एंडपॉइंट्स में status="failing" के रूप में
चिह्नित किया जाता है। जैसे ही पेलोड स्थायी रूप से स्वीकार हो जाए, 2xx लौटाएँ;
एसिंक्रोनस रूप से प्रोसेस करें।
क्रम
डिलीवरी क्रम सर्वोत्तम-प्रयास आधारित है। व्यवहार में हम इवेंट्स को उनके
उत्सर्जित होने के क्रम में डिलीवर करते हैं, लेकिन विफलता पर पुनः प्रयास क्रम बदल सकते हैं।
हमेशा call_id / ऑब्जेक्ट आईडी द्वारा डुप्लिकेट हटाएँ और मिलान करें।
डुप्लिकेट
डिलीवरी कम-से-कम-एक-बार होती है: ऐसे रिस्पॉन्स के बाद पुनः प्रयास, जो हमें कभी
प्राप्त नहीं हुआ, किसी इवेंट की डुप्लिकेट डिलीवरी कर सकता है। प्रत्येक पुनः प्रयास में वही
event_id होता है, इसलिए प्रोसेस की गई आईडी स्टोर करें और दोहराव छोड़ दें। event_id
एंडपॉइंट्स के बीच भी साझा होता है — एक ही इवेंट को सब्सक्राइब किए गए दो एंडपॉइंट्स को
समान event_id प्राप्त होता है।
टाइमआउट
एंडपॉइंट डिलीवरी में प्रत्येक प्रयास के लिए 30 सेकंड का टाइमआउट होता है। लेगेसी पथ पर,
लाइव कॉल व्यवहार नियंत्रित करने वाले ब्लॉकिंग रिक्वेस्ट —
telephony.incoming / web.incoming
कॉन्फ़िगरेशन एक्सचेंज — 10 सेकंड बाद टाइमआउट हो जाते हैं, लेकिन धीमा
रिस्पॉन्स कॉल पिकअप में देरी करता है, इसलिए कुछ सेकंड के भीतर जवाब देने का लक्ष्य रखें।
वेबहुक-मोड टूल डिस्पैच डिफ़ॉल्ट रूप से 20 सेकंड की अनुमति देता है,
और टूल डिक्लेरेशन टॉप-लेवल timeout सेट कर सकते हैं।
स्रोत IPs
आउटबाउंड वेबहुक ThunderPhone की क्लाउड IP रेंज से उत्पन्न होते हैं। यदि आपके फ़ायरवॉल को अलाउलिस्ट की आवश्यकता है, तो सपोर्ट से संपर्क करें और हम वर्तमान रेंज साझा करेंगे।
लेगेसी और एंडपॉइंट-आधारित वेबहुक के बीच चयन
| सुविधा | लेगेसी (/v1/webhook) | एंडपॉइंट्स (/v1/developer/webhook-endpoints) |
|---|---|---|
| URL की संख्या | प्रति संगठन 1 | प्रति संगठन कई |
| इवेंट कवरेज | केवल telephony.* / web.* | सभी 10 इवेंट प्रकार |
| इवेंट फ़िल्टर | — | प्रति एंडपॉइंट |
| पुनः प्रयास | कोई नहीं | 24 घंटों में 8 प्रयास |
| एनवेलप | type + data | type + data + event_id |
| सीक्रेट रोटेशन | एकल सीक्रेट को बदलता है | प्रति एंडपॉइंट सीक्रेट |
| हटाए बिना निष्क्रिय करना | — | status=disabled |
| स्टेटस दृश्यता | — | active / disabled / failing |
| ब्लॉकिंग कॉन्फ़िगरेशन एक्सचेंज | हाँ (telephony.incoming / web.incoming) | कभी नहीं — केवल नोटिफ़िकेशन |
| इसके लिए सर्वश्रेष्ठ | डायनेमिक कॉल कॉन्फ़िगरेशन | प्रोडक्शन में इवेंट उपभोग |
नए इंटीग्रेशन को एंडपॉइंट-आधारित वेबहुक के माध्यम से इवेंट्स का उपभोग करना चाहिए। लेगेसी URL केवल तभी रखें (या जोड़ें) जब आप कॉल पिकअप के समय कॉल को डायनेमिक रूप से कॉन्फ़िगर करते हैं या वेबहुक-मोड टूल डिस्पैच का उपयोग करते हैं — वे रिक्वेस्ट/रिस्पॉन्स एक्सचेंज केवल लेगेसी पथ पर चलते हैं।
संबंधित
सभी इवेंट प्रकार और उनके पेलोड।
कई एंडपॉइंट्स, इवेंट फ़िल्टर और सीक्रेट प्रबंधित करें।
कॉल कॉन्फ़िगर करने के लिए आपके सर्वर को जिस ब्लॉकिंग रिक्वेस्ट का जवाब देना होता है।
ट्रांसक्रिप्ट, रिकॉर्डिंग और मेट्रिक्स के साथ कॉल के बाद का पेलोड।