ویب ہکس کا جائزہ
ThunderPhone آپ کے سرور کو HTTP POST درخواستیں بھیجتا ہے جب کال کے دوران کوئی واقعہ پیش آتا ہے — ایک آنے والی کال شروع ہوتی ہے، کال ختم ہوتی ہے، گریڈنگ رن مکمل ہوتا ہے، الرٹ فعال ہوتا ہے، وغیرہ۔ ڈیلیوری کے دو ماڈلز ہیں:
متعدد URLs، ہر اینڈ پوائنٹ کے لیے الگ secrets، ہر اینڈ پوائنٹ کے لیے ایونٹ فلٹرز،
اور خودکار دوبارہ کوششیں۔
GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints کے ذریعے منظم کریں۔
ہر org کے لیے ایک 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" }
}
ترسیل کے دوران، ہر باڈی معیاری طور پر سریلائز کی جاتی ہے — keys حروف تہجی کے لحاظ سے ترتیب دی جاتی ہیں، کوئی whitespace نہیں ہوتا، اور UTF-8 استعمال ہوتا ہے۔ ان دستاویزات میں خوب صورت فارمیٹ کیے گئے نمونے صرف پڑھنے میں آسانی کے لیے ہیں۔
ایونٹ اقسام اور پے لوڈ فیلڈز کی مکمل فہرست کے لیے ایونٹس کیٹلاگ دیکھیں۔
دستخط کی تصدیق
ہر درخواست میں X-ThunderPhone-Signature ہیڈر میں خام درخواست
باڈی پر HMAC-SHA256 دستخط شامل ہوتا ہے۔ دستخطی کلید endpoint کا
secret ہے (یا legacy ڈیلیوریز کے لیے آپ کی تنظیمی سطح کے webhook کا
secret)۔
مراحل
- کسی بھی parsing سے پہلے خام درخواست باڈی پڑھیں۔
hmac_sha256(secret, body).hexdigest()کا حساب کریں۔X-ThunderPhone-Signatureہیڈر کے ساتھ مستقل وقت میں موازنہ کریں۔
ہم بالکل وہی بائٹس دستخط کرتے ہیں جو ہم منتقل کرتے ہیں، اور وہ بائٹس canonical JSON serialization ہیں (ترتیب شدہ keys، مختصر separators)۔ لہٰذا خام باڈی کے خلاف تصدیق ہمیشہ کام کرتی ہے — اور اگر آپ کا framework آپ کو صرف parsed JSON دیتا ہے تو اسے ترتیب شدہ keys اور مختصر separators کے ساتھ دوبارہ serialize کرنے سے یکساں بائٹس تیار ہوتے ہیں۔ دونوں طریقے تصدیقی گائیڈ میں شامل ہیں۔
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 "", 204
import 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" کے طور پر نشان زد
کر دیا جاتا ہے۔ جیسے ہی payload مستقل طور پر قبول ہو، 2xx واپس کریں؛
غیر ہم وقت طریقے سے پراسیس کریں۔
ترتیب
ترسیل کی ترتیب بہترین ممکنہ کوشش کی بنیاد پر ہے۔ عملی طور پر ہم ایونٹس کو
ان کے اخراج کی ترتیب میں پہنچاتے ہیں، لیکن ناکامی کی صورت میں دوبارہ کوششیں
ترتیب تبدیل کر سکتی ہیں۔ ہمیشہ call_id / آبجیکٹ id کے ذریعے نقلیں ختم کریں
اور مصالحت کریں۔
نقلیں
ترسیل کم از کم ایک بار ہوتی ہے: ایسے جواب کے بعد دوبارہ کوشش جسے ہم نے کبھی
نہ دیکھا ہو، کسی ایونٹ کی نقل بنا سکتی ہے۔ ہر دوبارہ کوشش میں وہی
event_id ہوتا ہے، اس لیے پراسیس شدہ ids محفوظ کریں اور تکرار کو چھوڑ دیں۔ event_id
اینڈپوائنٹس کے درمیان بھی مشترک ہوتا ہے — ایک ہی ایونٹ کو سبسکرائب کیے گئے دو
اینڈپوائنٹس کو ایک ہی event_id ملتا ہے۔
ٹائم آؤٹس
اینڈپوائنٹ ترسیلات میں ہر کوشش کے لیے 30 سیکنڈ کا ٹائم آؤٹ ہوتا ہے۔ لیگیسی
راستے پر، لائیو کال کے رویے کو کنٹرول کرنے والی بلاکنگ درخواستیں — یعنی
telephony.incoming / web.incoming
کنفیگریشن تبادلہ — 10 سیکنڈ بعد ٹائم آؤٹ ہو جاتی ہیں، لیکن سست جواب کال پک اپ
میں تاخیر کرتا ہے، اس لیے چند سیکنڈ کے اندر جواب دینے کی کوشش کریں۔ ویب ہک موڈ
ٹول ڈسپیچ میں 20 سیکنڈ کی اجازت ہے۔
ماخذ IPs
آؤٹ باؤنڈ ویب ہکس ThunderPhone کی کلاؤڈ IP رینج سے آتے ہیں۔ اگر آپ کے فائر وال کو اجازت فہرست درکار ہو تو سپورٹ سے رابطہ کریں، ہم موجودہ رینجز فراہم کر دیں گے۔
لیگیسی اور اینڈپوائنٹ پر مبنی ویب ہکس کے درمیان انتخاب
| خصوصیت | لیگیسی (/v1/webhook) | اینڈپوائنٹس (/v1/developer/webhook-endpoints) |
|---|---|---|
| URLs کی تعداد | ہر تنظیم کے لیے 1 | ہر تنظیم کے لیے متعدد |
| ایونٹ کوریج | صرف telephony.* / web.* | تمام 10 ایونٹ اقسام |
| ایونٹ فلٹر | — | فی اینڈپوائنٹ |
| دوبارہ کوششیں | کوئی نہیں | 24 گھنٹوں میں 8 کوششیں |
| لفافہ | type + data | type + data + event_id |
| سیکرٹ روٹیشن | واحد سیکرٹ کو تبدیل کرتا ہے | فی اینڈپوائنٹ سیکرٹ |
| حذف کیے بغیر غیر فعال کریں | — | status=disabled |
| اسٹیٹس کی مرئیت | — | active / disabled / failing |
| بلاکنگ کنفیگ تبادلہ | ہاں (telephony.incoming / web.incoming) | کبھی نہیں — صرف اطلاعات |
| بہترین استعمال | متحرک کال کنفیگریشن | پروڈکشن میں ایونٹ استعمال |
نئی انٹیگریشنز کو ایونٹس اینڈپوائنٹ پر مبنی ویب ہکس کے ذریعے استعمال کرنے چاہییں۔ لیگیسی URL صرف اسی صورت میں رکھیں (یا شامل کریں) جب آپ پک اپ کے وقت کالز کو متحرک طور پر کنفیگر کرتے ہوں یا ویب ہک موڈ ٹول ڈسپیچ استعمال کرتے ہوں — یہ درخواست/جواب تبادلے صرف لیگیسی راستے پر چلتے ہیں۔
متعلقہ
تمام ایونٹ اقسام اور ان کے payloads۔
متعدد اینڈپوائنٹس، ایونٹ فلٹرز، اور سیکرٹس کا نظم کریں۔
کالز کنفیگر کرنے کے لیے وہ بلاکنگ درخواست جس کا آپ کے سرور کو جواب دینا ضروری ہے۔
ٹرانسکرپٹ، ریکارڈنگ، اور میٹرکس کے ساتھ کال کے بعد کا payload۔