---
title: "ہر کال کے لیے متحرک کنفیگریشن"
description: "اپنے کنٹرول والے webhook میں کسٹم منطق کی بنیاد پر، ہر آنے والی کال کے لیے جواب دینے والا ایجنٹ منتخب کریں — یا اس کا prompt اور ترتیبات الگ سے تبدیل کریں۔"
---

بطور ڈیفالٹ ہر فون نمبر اور قابل اشاعت کلید کے ساتھ ایک جامد ایجنٹ
منسلک ہوتا ہے۔ جب آپ کو **ہر کالر کے لیے** یا **ہر وزیٹر کے لیے** تخصیص
درکار ہو — VIP روٹنگ، لاگ اِن صارف کا سیاق، A/B prompt ٹیسٹس — تو
ویب ہک موڈ پر منتقل ہوں اور اپنے سرور کو فیصلہ کرنے دیں۔

## یہ کیسے کام کرتا ہے

1. آپ [`telephony.incoming`](/ur/webhooks/events)
   (فون) یا [`web.incoming`](/ur/webhooks/events) (ویجیٹ)
   ایونٹ کو سبسکرائب کرتے ہیں۔ دونوں **روکنے والے** ویب ہکس ہیں:
   ThunderPhone کال جاری رکھنے سے پہلے آپ کے جواب کا 10 سیکنڈ تک انتظار کرتا ہے۔
2. ThunderPhone آپ کو `{call_id, from_number, to_number}` بھیجتا ہے (ویجیٹ
   سیشنز میں نمبروں کے بجائے ویجیٹ کے مخصوص فیلڈز ہوتے ہیں — [درخواست
   اسکیما](/ur/webhooks/call-incoming) دیکھیں)۔
3. آپ کا سرور ایجنٹ کنفیگریشن (prompt، آواز،
   پروڈکٹ، ٹولز) کے ساتھ جواب دیتا ہے۔ ThunderPhone کال کے لیے وہی کنفیگریشن استعمال کرتا ہے۔
4. اگر آپ `{}` واپس کریں، وقت ختم ہو جائے، یا خرابی ہو تو جامد طور پر منسلک
   ایجنٹ کو متبادل کے طور پر استعمال کیا جاتا ہے۔ محفوظ ڈیفالٹ۔

<Note>
  فون کالز (`telephony.incoming`) اور ویجیٹ
  سیشنز (`web.incoming`) کے لیے یکساں طور پر کام کرتا ہے، چاہے اسے ویب ہک اینڈپوائنٹ
  یا پرانے سنگل-URL ویب ہک پر پہنچایا جائے۔
</Note>

<Warning>
  **اِن لائن ویب ہک کے ذریعے کنفیگر شدہ کالز پر ThunderPhone کی رضامندی کی اطلاع نہیں چلتی۔**
  یہ راستہ ایجنٹ کی سطح پر کال شروع ہونے کی اطلاع کو نظرانداز کرتا ہے
  اور ThunderPhone کے رضامندی کی اطلاع کے فریم ورک (سروس کی شرائط، "ریکارڈنگ اور رضامندی"
  سیکشن) سے صراحتاً خارج ہے۔ ان کالز پر تمام ریکارڈنگ، نگرانی، AI کی شرکت، اور
  کالر کی شناخت سے متعلق اطلاعات اور رضامندیاں آپ کی تنظیم کی ذمہ داری ہیں۔ اِن لائن
  ویب ہک موڈ فعال کرنے سے پہلے انہیں اپنے فلو میں فراہم کریں — مثال کے طور پر
  prompt کے ابتدائی اسکرپٹ میں۔ ایسی ویب ہک جواب جو محفوظ شدہ `agent_id`
  کا حوالہ دے، اس ایجنٹ کی معمول کی ریکارڈنگ اور انکشاف کی پالیسی استعمال کرتا ہے۔
</Warning>

## 1. ویب ہک منزل کنفیگر کریں

<Tabs>
<Tab title="فون کالز">
فون نمبروں کے لیے، اپنے اینڈپوائنٹ کو `telephony.incoming` کے لیے سبسکرائب کریں:

```bash
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Prod call-incoming",
    "url":    "https://example.com/thunderphone/incoming",
    "events": ["telephony.incoming"]
  }'
```

جواب میں ایک بار استعمال ہونے والا `secret` شامل ہوتا ہے — اسے محفوظ کریں؛ آپ اسے
دستخط کی توثیق کے لیے استعمال کریں گے۔
</Tab>
<Tab title="ویب ویجیٹ">
ویجیٹ سیشنز کے لیے، اپنے اینڈپوائنٹ URL کے ساتھ شامل `mode="webhook"` میں قابل اشاعت کلید بنائیں:

```bash
curl -X POST https://api.thunderphone.com/v1/publishable-key \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":            "Dynamic widget",
    "mode":            "webhook",
    "webhook_url":     "https://example.com/thunderphone/widget-incoming",
    "allowed_domains": ["example.com"]
  }'
```

ویجیٹ ہر سیشن شروع ہونے پر اس URL پر POST کرے گا۔
</Tab>
</Tabs>

## 2. ہینڈلر نافذ کریں

تین بنیادی اصول:

- ہر درخواست پر **دستخط کی توثیق کریں** (دیکھیں
  [ویب ہُک دستخط کی توثیق کریں](/ur/guides/verify-webhook-signatures))۔
  ڈویلپمنٹ میں بھی اسے نظر انداز نہ کریں — اسے ایک بار درست کریں اور دوبارہ استعمال کریں۔
- **فوراً جواب دیں**۔ دس سیکنڈ حتمی حد ہے، اور ہر سیکنڈ کال کرنے والے کے لیے خاموشی ہے۔
  ضرورت ہو تو ڈیٹابیس لک اَپس کریں، مگر ڈاؤن اسٹریم LLMs کو ہم وقت انداز میں کال نہ کریں —
  اگر آپ کو متحرک prompt جنریشن چاہیے تو پہلے سے حساب کر کے کیش کریں۔
- **درست انداز میں فال بیک کریں**۔ کسی بھی غیر متوقع حالت میں `{}` واپس کریں تاکہ
  مستقل طور پر مقرر کردہ ایجنٹ کال سنبھال لے۔

<CodeGroup>
```python FastAPI
import hashlib
import hmac
import json
import os

from fastapi import FastAPI, HTTPException, Request

app = FastAPI()
SECRET = os.environ["THUNDERPHONE_WEBHOOK_SECRET"]

def verify(body: bytes, sig: str) -> bool:
    expected = hmac.new(SECRET.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig or "")

@app.post("/thunderphone/incoming")
async def incoming(request: Request):
    body = await request.body()
    if not verify(body, request.headers.get("X-ThunderPhone-Signature", "")):
        raise HTTPException(401)

    event = json.loads(body)
    if event["type"] not in ("telephony.incoming", "web.incoming"):
        return {}  # fall back to default

    caller = event["data"]["from_number"]
    # Cheap DB lookup: is this a known VIP?
    customer = lookup_customer(caller)
    if customer and customer.tier == "vip":
        return {
            "prompt":  f"You are a VIP concierge for {customer.name}. Be proactive…",
            "voice":   "john",
            "product": "storm-base",
        }
    return {}  # default agent handles non-VIPs

def lookup_customer(phone: str):
    # ... your CRM integration ...
    pass
```

```javascript Express
import crypto from "node:crypto";
import express from "express";

const app = express();
const SECRET = process.env.THUNDERPHONE_WEBHOOK_SECRET;

function verify(body, sig) {
  const expected = crypto.createHmac("sha256", SECRET).update(body).digest("hex");
  return sig &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}

app.post(
  "/thunderphone/incoming",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    if (!verify(req.body, req.header("X-ThunderPhone-Signature"))) {
      return res.sendStatus(401);
    }
    const event = JSON.parse(req.body.toString("utf8"));

    const IMPORTANT_TYPES = new Set([
      "telephony.incoming",
      "web.incoming",
    ]);
    if (!IMPORTANT_TYPES.has(event.type)) return res.json({});

    const customer = await lookupCustomer(event.data.from_number);
    if (customer?.tier === "vip") {
      return res.json({
        prompt:  `You are a VIP concierge for ${customer.name}. Be proactive…`,
        voice:   "john",
        product: "storm-base",
      });
    }
    res.json({}); // fall back to default agent
  },
);
```
</CodeGroup>

## 3. رسپانس اسکیما

رسپانس باڈی بالکل
[ان کمنگ کال رسپانس اسکیما](/ur/webhooks/call-incoming)
سے مطابقت رکھتی ہے۔ عام طور پر استعمال ہونے والی فیلڈز:

| فیلڈ | قسم | وضاحت |
|-------|------|-------------|
| `prompt` | اسٹرنگ (لازمی) | ایجنٹ کے لیے سسٹم prompt |
| `voice` | اسٹرنگ (لازمی) | [`GET /v1/voices`](/api-reference/agents#voices) سے وائس آئی ڈی |
| `product` | اسٹرنگ | ڈیفالٹ `spark` ہے |
| `background_track` | اسٹرنگ \| null | محیطی آڈیو آئی ڈی |
| `acknowledgement_prompt_mode` | اسٹرنگ | `auto` یا `manual` (صرف ack کے ساتھ Storm) |
| `acknowledgement_prompt` | اسٹرنگ | موڈ `manual` ہونے پر لازمی |
| `tools` | ارے | ان لائن فنکشن-ٹول اسکیماز — [فنکشن ٹولز](/ur/tools/overview) دیکھیں |

<Note>
  فی کال بولنے کی ترتیب اور `max_hold_seconds` ویب ہک رسپانس میں دستیاب نہیں ہیں۔
  انہیں اس [ایجنٹ](/api-reference/agents) پر سیٹ کریں جسے آپ ریفرنس کرتے ہیں۔
</Note>

### محفوظ شدہ ایجنٹ رکھیں اور ویری ایبلز فراہم کریں

اس تنظیم کے محفوظ شدہ ایجنٹ کو فی کال ڈیٹا کے ساتھ استعمال کرنے کے لیے
`{"agent_id": 12, "variables": {"name": "Ada"}}` واپس کریں۔ اس کے prompt میں
`{{name}}` یا `{{name|Friend}}` شامل ہو سکتا ہے۔ ویب ہک ویری ایبلز ریکویسٹ-سطح کے
ویری ایبلز پر ضم ہو جاتے ہیں؛ null پلیس ہولڈر کا ڈیفالٹ استعمال کرتا ہے، یا اگر
کوئی فراہم نہ کیا گیا ہو تو خالی متن استعمال ہوتا ہے۔ حتمی قدریں اور حل نہ ہونے
والے نام کال کی تفصیلات اور تکمیلی ویب ہکس میں ظاہر ہوتے ہیں۔ محفوظ شدہ ایجنٹ
رسپانس صرف `agent_id` اور `variables` قبول کرتے ہیں۔ اگر `prompt` موجود ہو تو
رسپانس ان لائن کنفیگریشن استعمال کرتا ہے اور `agent_id` کو نظر انداز کر دیتا ہے
(بشمول null یا غیر عددی میٹا ڈیٹا)؛ ان لائن prompt پھر بھی درست ہونا ضروری ہے۔
ان لائن کنفیگریشن رسپانس میں `variables` بھی شامل ہو سکتے ہیں۔ محفوظ شدہ ایجنٹ
رسپانس فون اور وجٹ، دونوں کالز پر ایجنٹ کی ڈیپلائے شدہ A/B تقسیم استعمال کرتے ہیں،
پھر ویری ایبلز رینڈر کرتے ہیں۔ حدود اور سیشن API سپورٹ کے لیے
[کال ویری ایبلز](/ur/guides/call-variables) دیکھیں۔ بلاکنگ کنفیگریشن پرانے
فون نمبر/تنظیم URL یا ویب ہک موڈ وجٹ کی سے آتی ہے؛ اینڈ پوائنٹ-سسٹم ان کمنگ ایونٹس
صرف اطلاعات ہیں۔

## پیٹرنز

### لاگ اِن صارف کا سیاق

ویب ہک موڈ وجٹس میں، وزیٹر کا صفحہ پہلے ہی جانتا ہے کہ وہ کون ہیں۔
اپنے ویب ہک کو ایک کوئری اسٹرنگ پیرامیٹر کے ساتھ کال کریں جسے وجٹ SDK
آگے بھیجتا ہے (`?customer_id=123`) اور صارف کو سرور سائیڈ پر تلاش کریں۔

### A/B prompt رول آؤٹ

اسے خود تیار کرنے سے پہلے، نوٹ کریں کہ ThunderPhone میں مقامی
[ایکسپیریمنٹس](/ur/guides/concepts) فیچر
(`/dashboard/experiments` اور ایجنٹ بلڈر کا **A/B** ٹیب) موجود ہے جو
ویریئنٹس متعین کرتا ہے، ٹریفک تقسیم کرتا ہے، اور ہر ویریئنٹ کے نتائج کا موازنہ کرتا ہے —
کسی ویب ہک کی ضرورت نہیں۔

اگر آپ کو پھر بھی ویب ہک سائیڈ کنٹرول درکار ہو: `call_id` کو ہیش کر کے بکٹ بنائیں؛
`0..49` کے لیے prompt A اور `50..99` کے لیے prompt B فراہم کریں۔ اپنے DB میں
منتخب کردہ بکٹ ریکارڈ کریں اور بعد میں اسے مکمل شدہ کال کے گریڈ سے مربوط کریں۔

### وقت پر مبنی روٹنگ

کاروباری اوقات → "براہ راست سپورٹ" ایجنٹ؛ کاروباری اوقات کے بعد → "پیغام لیں"
ایجنٹ۔ اپنے ہینڈلر میں `new Date().getUTCHours()` پر سادہ سوئچ استعمال کریں۔

---

## اگلے مراحل

<CardGroup cols={2}>
  <Card title="ان کمنگ کال ویب ہک حوالہ" icon="phone" href="/ur/webhooks/call-incoming">
    ہر کنفیگریشن کی سمیت درست ریکویسٹ اور رسپانس اسکیماز۔
  </Card>
  <Card title="ویب ہک دستخطوں کی تصدیق کریں" icon="shield-check" href="/ur/guides/verify-webhook-signatures">
    HMAC کو ایک بار درست کریں؛ ہر جگہ دوبارہ استعمال کریں۔
  </Card>
  <Card title="ٹول انٹیگریشن بنائیں" icon="screwdriver-wrench" href="/ur/guides/build-tool-integration">
    متحرک روٹنگ کو فی ایجنٹ ٹولز کے ساتھ ملائیں۔
  </Card>
  <Card title="ترسیل کی معنویت" icon="bolt" href="/ur/webhooks/overview">
    دوبارہ کوششیں، ترتیب، ٹائم آؤٹس۔
  </Card>
</CardGroup>
