---
title: "telephony.incoming / web.incoming"
description: "Webhook חוסם שמעצב את תצורת השיחה הנכנסת בזמן אמת."
---

כאשר שיחת טלפון נכנסת מגיעה למספר **ללא סוכן שהוקצה לו**, או שסשן של וידג'ט אינטרנט מתחיל במפתח ניתן לפרסום במצב
`mode="webhook"`, ThunderPhone שולח בקשה **חוסמת**
`telephony.incoming` / `web.incoming` אל
[כתובת ה-webhook הישנה שלכם](/api-reference/organizations#legacy-single-url-webhook)
וממתין לתגובת תצורה: עד **13 שניות** עבור
שיחת טלפון, כולל ניסיון חוזר אחד, ועד **10 שניות** עבור סשן וידג'ט
(ראו [זמני קציבה וניסיונות חוזרים](#timeouts-and-retries)). השתמשו
בחילוף זה כדי לבחור באופן דינמי הנחיה, קול וכלים לכל שיחה —
ראו את [המדריך לתצורת שיחות דינמית](/he/guides/dynamic-call-config)
לתבנית המלאה מקצה לקצה.

<Note>
  [נקודות קצה של וובהוק](/he/webhooks/endpoints) שנרשמו כמנויים מקבלות גם
  `telephony.incoming` / `web.incoming` — עבור **כל** שיחה נכנסת
  וסשן אינטרנט, בין שהוגדר בהם סוכן ובין שלא — אך מסירות אלה הן
  התראות שנשלחות ללא המתנה, עם `event_id`, ולעולם אינן חוסמות.
  רק הוובהוק הישן בעל כתובת יחידה נושא את החלפת התצורה המתוארת
  בעמוד זה. מבני התראות נקודות הקצה מופיעים ב[קטלוג
  האירועים](/he/webhooks/events).
</Note>

## פסקי זמן וניסיונות חוזרים

ענו במהירות: המתקשר ממתין על הקו בזמן שאתם מחליטים.

לשיחת טלפון (`telephony.incoming`):

- הניסיון הראשון עשוי להימשך עד **10 שניות**.
- אם מתרחש פסק זמן, לא ניתן להתחבר, או שמתקבלת תגובת
  `5xx`, `408` או `429`, ThunderPhone מנסה פעם נוספת. הניסיון החוזר מקבל את הזמן
  שנותר מתוך תקציב של **13 שניות** לכל ההחלפה: כ-3 שניות לאחר
  ניסיון ראשון שפסק זמנו, וכמעט כל 13 השניות לאחר כשל מהיר.
  לא מתבצע ניסיון חוזר כאשר נותרו פחות מ-2 שניות.
- כל תגובת `4xx` אחרת, תגובה החורגת מ-
  [מגבלת הגודל](#response-size-limit), או תגובת `2xx` שגופה אינו
  תצורה תקפה, הן סופיות ולא מתבצע עבורן ניסיון חוזר.
- שני הניסיונות שולחים את אותו גוף, את אותו `X-ThunderPhone-Signature`,
  ואת אותה כותרת `X-ThunderPhone-Idempotency-Key`
  (`telephony-incoming-<call_id>`), כך שמטפל בעל תופעות לוואי
  יכול לזהות את הניסיון החוזר.

אין סוכן גיבוי. אם לא מתקבלת תצורה שמישה, השיחה מסתיימת מיד במקום
להשאיר את המתקשר על קו שקט. היא מופיעה בהיסטוריית השיחות כשיחה שנכשלה
ולא חויבה, עם `end_reason` של `inbound_config_webhook_failed`, ונשלח
האירוע הרגיל [`telephony.complete`](/he/webhooks/call-complete).

סשן וידג'ט (`web.incoming`) מקבל ניסיון יחיד של עד 10
שניות. אם הוא נכשל, בקשת הסשן נכשלת עם `502` או `422`.

<Warning>
  **שיחות שמוגדרות באמצעות וובהוק אינן כוללות הודעת הסכמה של ThunderPhone.**
  שיחות שמוגדרות דרך החלפה זו עוקפות את הודעת תחילת השיחה ברמת
  הסוכן ומוחרגות במפורש ממסגרת הודעות ההסכמה של ThunderPhone
  (תנאי השירות, סעיף "הקלטה והסכמה"). הארגון שלכם אחראי באופן
  בלעדי לכל הודעה והסכמה הנדרשות בשיחות אלה לגבי הקלטה, ניטור,
  השתתפות של AI וזיהוי המתקשר — עדיין ניתן להקליט, לתמלל, לנתח
  ולטפל בשיחות באמצעות AI. בנו את הגילויים הנדרשים לתוך זרימת
  השיחות שלכם לפני הפעלת נתיב זה.
</Warning>

## מטען הבקשה

עבור שיחות טלפון (`telephony.incoming`):

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

| שדה | סוג | תיאור |
|-------|------|-------------|
| `call_id` | מספר שלם | מזהה שיחה — יציב בכל האירועים של שיחה זו |
| `from_number` | מחרוזת | מספר המתקשר בפורמט E.164 |
| `to_number` | מחרוזת | יעד בפורמט E.164 (אחד ממספרי ThunderPhone שלכם) |

עבור סשנים של וידג'ט אינטרנט (`web.incoming`), השדה `data` מזהה את
העמוד המטמיע במקום מספרי טלפון:

```json
{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
```

| שדה | סוג | תיאור |
|-------|------|-------------|
| `call_id` | מספר שלם | מזהה השיחה |
| `origin_domain` | מחרוזת | מקור הדף שמארח את הווידג'ט, כפי שנשלח על ידי הדפדפן. לקוח שאינו דפדפן יכול לשלוח כל ערך, לכן אין להתייחס אליו כהוכחה למקור הבקשה |
| `publishable_key_prefix` | מחרוזת | התווים הראשונים של מפתח הפרסום שפתח את הסשן |
| `language`, `primary_language` | מחרוזת | קיים כאשר סשן הווידג'ט ביקש דריסת שפה |
| `voice` | מחרוזת | קיים כאשר סשן הווידג'ט ביקש דריסת קול |
| `website_context` | מחרוזת | קיים כאשר הווידג'ט העביר הקשר דף לכל סשן |

שדות הדריסה (`language`, `voice`, `website_context`, וכל
`variables` של הדפדפן) מגיעים רק כאשר מפתח הפרסום מאפשר אותם במסגרת
[דריסות הדפדפן](/he/guides/embed-web-widget) שלו. בקשת
סשן הכוללת דריסה שהמפתח אינו מאפשר נדחית לפני שהוובהוק הזה מופעל.

<Note>
  וידג'טים במצב וובהוק מוסרים בקשה זו אל `webhook_url` של המפתח
  הניתן לפרסום עצמו כאשר הוא מוגדר, ובמקרה שאין כזה משתמשים
  בכתובת הוובהוק ברמת הארגון. בכל מקרה, הבקשה חתומה באמצעות
  ה-`secret` של וובהוק הארגון.
</Note>

---

## סכמת תגובה

החזירו אובייקט JSON המתאר את תצורת הסוכן עבור שיחה זו.
`prompt` ו-`voice` נדרשים; כל היתר אופציונלי.

```json
{
  "prompt":  "You are a helpful booking assistant for Acme Restaurant.",
  "voice":   "john",
  "product": "spark",
  "background_track": null,
  "tools":   []
}
```

| שדה | סוג | נדרש | תיאור |
|-------|------|----------|-------------|
| `prompt` | מחרוזת | כן | הנחיית המערכת שמנחה את הסוכן |
| `voice` | מחרוזת | כן | מזהה קול מתוך [`GET /v1/voices`](/api-reference/agents#voices), למשל `john`. `voice_name` מתקבל גם ככינוי. קולות לא מוכרים נכשלים באימות ודוחים את השיחה |
| `product` | מחרוזת | לא | ברירת המחדל היא `spark`. ערכים מותרים: `spark`, `bolt`, `storm-base`, `storm-base-with-ack`, `storm-extra`, `storm-extra-with-ack` |
| `thinking_level` | מחרוזת | לא | `minimal`, `base` (ברירת מחדל) או `extra`. מוחלף עבור מוצרי Storm: ‏`storm-extra*` כופה `extra`, וערכי `storm-*` אחרים כופים `base` |
| `audio_context_mode` | מחרוזת | לא | `full` (ברירת מחדל) או `reduced` |
| `watchdog_enabled` | בוליאני | לא | הפעלת פיקוח עבור שיחה זו. ברירת המחדל היא `false` |
| `additional_audio_context` | בוליאני \| null | לא | כללו את התורות האחרונות של שמע המתקשר במקום רק את התור העדכני ביותר, כדי לשפר תיקונים ואיסוף נתונים עתירי איות או מספרים, בתוספת קטנה של השהיה ועלות. ברירת המחדל מופעלת עבור סשנים נכנסים ומושבתת עבור שיחות טלפון יוצאות; `null` שומר על ברירת המחדל |
| `storm_feedback_mode` | מחרוזת | לא | `none`, `acknowledgement` (ברירת מחדל) או `tick` |
| `language` | מחרוזת | לא | קיצור עבור `primary_language` |
| `primary_language` | מחרוזת | לא | קוד שפה מנורמל (ברירת המחדל היא `en`). קודים שלא ניתן לפענח דוחים את השיחה |
| `has_additional_languages` | בוליאני | לא | ברירת המחדל היא `false` |
| `additional_languages` | מערך של מחרוזות | לא | שפות נוספות שהסוכן יכול לעבור אליהן |
| `native_voice_switching` | בוליאני | לא | ברירת המחדל היא `false`. כאשר השיחה עוברת לשפה אחרת, החליפו לקול מקומי של אותה שפה (מותאם לפי מגדר) במקום לשמור על הקול שהוגדר |
| `language_switching` | מחרוזת \| null | לא | `ask_first` (ברירת מחדל) או `follow_caller`; ‏`null` זהה ל-`ask_first`. אופן הטיפול של סוכן רב-לשוני באדם השני המדבר בשפה אחרת מבין שפותיו. `ask_first` עובר מיד כאשר הם מבקשים את השפה או אומרים בה משפט מלא, ושואל אם להמשיך בה לאחר אמירה קצרה, כגון "כן". `follow_caller` עובר לכל שפה מוגדרת שהם מדברים בה, אפילו מילה אחת. חל רק כאשר `additional_languages` מוגדר |
| `background_track` | מחרוזת \| null | לא | מזהה שמע סביבתי או `null` |
| `acknowledgement_prompt_mode` | מחרוזת | לא | `auto` (ברירת מחדל) או `manual` (מוצרי Storm עם ack) |
| `acknowledgement_prompt` | מחרוזת | לא | בשימוש כאשר `acknowledgement_prompt_mode="manual"` |
| `silence_interval_seconds` | מספר שלם \| null | לא | 5–120. שניות של שקט מצד המתקשר לפני בדיקת מצב |
| `silence_max_checkins` | מספר שלם \| null | לא | 1–10 |
| `silence_checkins_enabled` | בוליאני | לא | ברירת המחדל היא `true` |
| `connect_tone_enabled` | בוליאני | לא | ברירת המחדל היא `false` |
| `pronunciation_dicts` | בוליאני \| null | לא | ברירת המחדל היא `false`; ‏`null` זהה ל-`false`. כאשר הערך הוא `true`, הדיבור של Cartesia בשיחה משתמש במילון ההגייה של ThunderPhone עבור שפת השיחה, כאשר קיים כזה. פועל עבור שיחות טלפון ושיחות בווידג'ט. חל רק על קולות Cartesia של ThunderPhone, ולא על קולות במפתח API משלכם של Cartesia. אינו בשימוש עם `agent_id`, שבו חלות הגדרות הסוכן השמור |
| `voicemail_action` | מחרוזת | לא | `prompt` (ברירת מחדל), `hangup` או `message` |
| `voicemail_message` | מחרוזת | לא | בשימוש כאשר `voicemail_action="message"` |
| `agent_name` | מחרוזת | לא | שם תצוגה שמדווח ללוחות המחוונים ולווידג'ט |
| `org_name` | מחרוזת | לא | שם תצוגה של הארגון עבור הדמות של הסוכן |
| `tools` | מערך | לא | סכמות מוטמעות של כלי פונקציה (ראו [כלי פונקציה](/he/tools/overview)) |
| `transfer_destinations` | מערך של אובייקטים \| null | לא | עד 50 רשומות `{name, number}` שאליהן שיחה זו יכולה להעביר, המאומתות כמו [מספרי ההעברה](/api-reference/agents#transfer-numbers) של סוכן. הסוכן מעביר לפי שם ורק אליהן; `[]` פירושו שאין העברות. השמיטו שדה זה או שלחו `null` כדי לאפשר לסוכן להעביר למספר שהוא בוחר |
| `timezone` | מחרוזת | לא | אזור זמן של IANA עבור שיחה זו, כגון `America/Chicago`. הסוכן מציין את התאריך והשעה בו, לפני אזור הזמן של הסוכן עצמו. מותר גם לצד `agent_id`. ערכים שאינם אזורי IANA מתעלמים מהם. ראו [הגדרת אזור הזמן לכל שיחה](/he/guides/dynamic-call-config) |
| `call_id` | מספר שלם | לא | הד אופציונלי של מזהה השיחה בבקשה; מתעלמים ממנו |

<Note>
  מפתחות ברמה העליונה שאינם מוכרים **מתעלמים** מהם בשקט — שם שדה עם שגיאת הקלדה
  אינו דוחה את התצורה, הוא פשוט אינו מוחל. סדר הדיבור
  ו-`max_hold_seconds` אינם מתקבלים כאן; ניתן להגדיר אותם רק עבור
  ה-[סוכן](/api-reference/agents) עצמו.
</Note>

מכיוון ש-`prompt` ו-`voice` נדרשים, החזרת `{}` או כל
תגובה שנכשלת באימות דוחה את השיחה: שיחת טלפון מסתיימת
כמתואר ב-[זמני קצוב וניסיונות חוזרים](#timeouts-and-retries), ובקשת הפעלת
ווידג'ט נכשלת עם `422`. בנתיב זה אין חלופה של סוכן סטטי
(למספר או למפתח במצב וובהוק אין סוכן משויך).

---

## מגבלת גודל תגובה

<Warning>
  תגובות תצורה מוגבלות ל-**5 MiB**. אם מטפל
  מחזיר תגובה גדולה יותר, כולל תגובה עם סטטוס `2xx`,
  ThunderPhone מדווחת שהתגובה חרגה מהמגבלה ודוחה את השיחה או את סשן הווידג'ט. שמרו את התגובה לשדות
  הנדרשים להגדרת השיחה; אחסנו נתונים גדולים מאחורי כלי פונקציה או
  שירות אחר במקום להטמיע אותם בתצורה.
</Warning>

---

## מטפל לדוגמה

<CodeGroup>
```python Python (FastAPI)
import hashlib
import hmac
import json
import os

from fastapi import FastAPI, HTTPException, Request

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

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

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

    event = json.loads(body)
    if event["type"] == "telephony.incoming":
        caller = event["data"]["from_number"]
        prompt = (
            "Greet the caller as a San Francisco local…"
            if caller.startswith("+1415")
            else "You are a friendly customer support agent…"
        )
        return {
            "prompt": prompt,
            "voice": "john",
            "product": "spark",
        }
    if event["type"] == "web.incoming":
        return {
            "prompt": "You are the website's helpful voice assistant…",
            "voice": "john",
            "product": "spark",
        }
    return {}
```

```javascript Node.js (Express)
import crypto from "node:crypto";
import express from "express";

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

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

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

    if (event.type === "telephony.incoming" || event.type === "web.incoming") {
      const caller = event.data.from_number || "web";
      const prompt = caller.startsWith("+1415")
        ? "Greet the caller as a San Francisco local…"
        : "You are a friendly customer support agent…";
      return res.json({
        prompt,
        voice: "john",
        product: "spark",
      });
    }
    res.json({});
  },
);
```
</CodeGroup>

---

## תגובה עם כלי פונקציה

צרפו כלים כדי שה-AI יוכל לקרוא לממשקי ה-API שלכם במהלך השיחה:

```json
{
  "prompt":  "You are a booking assistant. Use the available tools to help customers schedule appointments.",
  "voice":   "john",
  "product": "spark",
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_appointments",
        "description": "Find available appointment slots",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "service": { "type": "string" }
          },
          "required": ["date"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/search",
        "method": "POST",
        "headers": {
          "X-Api-Key": "your-key"
        }
      }
    }
  ]
}
```

<Tip>
  בקשות לנקודות קצה של כלים נחתמות באמצעות **אותו סוד
  וובהוק של הארגון** שחתם על חילופי הדברים האלה. עיינו ב-[כלי פונקציה](/he/tools/overview) לקבלת המבנה המדויק ותבנית
  הבקשה החתומה.
</Tip>

---

## דף עזר לרמות המוצר

| מוצר | השהיה | הסקה | אישור קבלה |
|---------|---------|-----------|-----------------|
| `spark` | הנמוכה ביותר | בסיסית | — |
| `bolt` | נמוכה | משופרת | — |
| `storm-base` | בינונית | חזקה | — |
| `storm-base-with-ack` | בינונית | חזקה | מענה ביניים אוטומטי בזמן החשיבה |
| `storm-extra` | גבוהה יותר | עמוקה | — |
| `storm-extra-with-ack` | גבוהה יותר | עמוקה | מענה ביניים אוטומטי בזמן החשיבה |

---

## קשור

<CardGroup cols={2}>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/he/webhooks/call-complete">
    אירוע סיום השיחה שאינו חוסם.
  </Card>
  <Card title="כלי פונקציה" icon="screwdriver-wrench" href="/he/tools/overview">
    סכמת JSON מלאה עבור `tools[]` וחוזה נקודת הקצה החתום.
  </Card>
  <Card title="נקודות קצה של Webhook" icon="bolt" href="/he/webhooks/endpoints">
    הירשמו כתובות URL מרובות ל-`telephony.incoming` / `web.incoming`.
  </Card>
  <Card title="תצורת שיחה דינמית" icon="wand-magic-sparkles" href="/he/guides/dynamic-call-config">
    דפוסים להנחיות, כלים ובדיקות A/B לכל מתקשר.
  </Card>
</CardGroup>
