---
title: "telephony.incoming / web.incoming"
description: "Webhook blocant care configurează în timp real o apelare de intrare."
---

Când un apel telefonic primit ajunge la un număr **fără un agent
atribuit** sau când o sesiune de widget web începe pe o cheie publicabilă în
`mode="webhook"`, ThunderPhone trimite o solicitare **blocantă**
`telephony.incoming` / `web.incoming` către
[adresa URL webhook veche](/api-reference/organizations#legacy-single-url-webhook)
și așteaptă un răspuns de configurare: până la **13 secunde** pentru un
apel telefonic, inclusiv o reîncercare, și până la **10 secunde** pentru o
sesiune de widget (consultați [Expirări și reîncercări](#timeouts-and-retries)). Utilizați acest
schimb pentru a alege dinamic un prompt, o voce și instrumente pentru fiecare apel —
consultați [ghidul de configurare dinamică a apelurilor](/ro/guides/dynamic-call-config)
pentru modelul complet.

<Note>
  [Endpointurile webhook](/ro/webhooks/endpoints) abonate primesc, de asemenea,
  `telephony.incoming` / `web.incoming` — pentru **fiecare** apel de intrare
  și sesiune web, configurată cu agent sau nu — însă aceste livrări sunt
  notificări fire-and-forget cu un `event_id`, niciodată blocante.
  Doar webhook-ul tradițional cu un singur URL gestionează schimbul de
  configurare de pe această pagină. Formatele notificărilor endpointurilor sunt în
  [catalogul de evenimente](/ro/webhooks/events).
</Note>

## Expirări de timp și reîncercări

Răspundeți rapid: apelantul așteaptă pe linie în timp ce decideți.

Pentru un apel telefonic (`telephony.incoming`):

- Prima încercare poate dura până la **10 secunde**.
- Dacă expiră, nu se poate conecta sau primește un răspuns
  `5xx`, `408` ori `429`, ThunderPhone încearcă încă o dată. Reîncercarea primește timpul
  rămas dintr-un buget de **13 secunde** pentru întregul schimb: aproximativ 3 secunde după
  o primă încercare care a expirat, aproape toate cele 13 secunde după un eșec rapid.
  Nu există reîncercare dacă ar rămâne mai puțin de 2 secunde.
- Orice alt răspuns `4xx`, un răspuns care depășește
  [limita de dimensiune](#response-size-limit) sau un răspuns `2xx` al cărui corp nu este o
  configurație validă este final și nu este reîncercat.
- Ambele încercări trimit același corp, același antet `X-ThunderPhone-Signature`
  și același antet `X-ThunderPhone-Idempotency-Key`
  (`telephony-incoming-<call_id>`), astfel încât un handler cu efecte secundare
  poate recunoaște reîncercarea.

Nu există agent de rezervă. Dacă nu sosește o configurație utilizabilă,
apelul este încheiat imediat, în loc ca apelantul să rămână pe o linie
silențioasă. Acesta apare în istoricul apelurilor ca un apel eșuat, nefacturat, cu
`end_reason` `inbound_config_webhook_failed`, iar evenimentul obișnuit
[`telephony.complete`](/ro/webhooks/call-complete) este trimis.

O sesiune de widget (`web.incoming`) primește o singură încercare de până la 10
secunde. Dacă aceasta eșuează, solicitarea sesiunii eșuează cu `502` sau `422`.

<Warning>
  **Apelurile configurate prin webhook nu includ niciun anunț de consimțământ
  ThunderPhone.** Apelurile configurate prin acest schimb ocolesc anunțul de
  început al apelului la nivel de agent și sunt excluse în mod expres din
  cadrul ThunderPhone pentru anunțuri de consimțământ (Termenii serviciului,
  secțiunea „Înregistrare și consimțământ”). Organizația dumneavoastră este singura
  responsabilă pentru fiecare notificare și consimțământ privind înregistrarea,
  monitorizarea, participarea AI și identificarea apelantului necesare pentru aceste apeluri —
  apelurile pot fi în continuare înregistrate, transcrise, analizate și gestionate
  de AI. Includeți informările necesare în propriul flux de apel înainte
  de a activa această cale.
</Warning>

## Încărcătura solicitării

Pentru apelurile telefonice (`telephony.incoming`):

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

| Câmp | Tip | Descriere |
|-------|------|-------------|
| `call_id` | integer | ID-ul apelului — stabil în toate evenimentele pentru acest apel |
| `from_number` | string | Numărul E.164 al apelantului |
| `to_number` | string | Destinația E.164 (unul dintre numerele dumneavoastră ThunderPhone) |

Pentru sesiunile widgetului web (`web.incoming`), `data` identifică
pagina de încorporare în locul numerelor de telefon:

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

| Câmp | Tip | Descriere |
|-------|------|-------------|
| `call_id` | integer | ID apel |
| `origin_domain` | string | Originea paginii care găzduiește widgetul, așa cum a transmis-o browserul. Un client care nu este browser poate trimite orice valoare, așadar nu o tratați drept dovadă a originii solicitării |
| `publishable_key_prefix` | string | Primele caractere ale cheii publicabile care a deschis sesiunea |
| `language`, `primary_language` | string | Prezente când sesiunea widgetului a solicitat o suprascriere a limbii |
| `voice` | string | Prezent când sesiunea widgetului a solicitat o suprascriere a vocii |
| `website_context` | string | Prezent când widgetul a transmis contextul paginii pentru fiecare sesiune |

Câmpurile de suprascriere (`language`, `voice`, `website_context` și orice
`variables` din browser) sosesc numai când cheia publicabilă le permite în
[suprascrierile din browser](/ro/guides/embed-web-widget). O
solicitare de sesiune care conține una pe care cheia nu o permite este respinsă înainte
ca acest webhook să fie apelat.

<Note>
  Widgeturile în modul webhook livrează această solicitare către propriul
  `webhook_url` al cheii publicabile atunci când este setat, revenind la URL-ul
  webhook de la nivelul organizației. În ambele cazuri, solicitarea este semnată cu
  `secret` webhook-ului organizației.
</Note>

---

## Schema de răspuns

Returnați un obiect JSON care descrie configurația agentului pentru acest apel.
`prompt` și `voice` sunt obligatorii; toate celelalte câmpuri sunt opționale.

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

| Câmp | Tip | Obligatoriu | Descriere |
|-------|------|----------|-------------|
| `prompt` | șir | da | Promptul de sistem care ghidează agentul |
| `voice` | șir | da | ID-ul vocii din [`GET /v1/voices`](/api-reference/agents#voices), de exemplu `john`. `voice_name` este acceptat ca alias. Vocile necunoscute nu trec validarea și resping apelul |
| `product` | șir | nu | Valoarea implicită este `spark`. Permise: `spark`, `bolt`, `storm-base`, `storm-base-with-ack`, `storm-extra`, `storm-extra-with-ack` |
| `thinking_level` | șir | nu | `minimal`, `base` (implicit) sau `extra`. Suprascris pentru produsele Storm: `storm-extra*` impune `extra`, iar alte `storm-*` impun `base` |
| `audio_context_mode` | șir | nu | `full` (implicit) sau `reduced` |
| `watchdog_enabled` | boolean | nu | Activați supravegherea pentru acest apel. Valoarea implicită este `false` |
| `additional_audio_context` | boolean \| null | nu | Includeți ultimele câteva schimburi de audio ale apelantului, în loc doar de cel mai recent schimb, îmbunătățind corecturile și colectarea de date cu multe litere sau numere, cu un mic cost suplimentar de latență și preț. Este activat implicit pentru sesiunile de intrare și dezactivat pentru apelurile telefonice de ieșire; `null` păstrează valoarea implicită |
| `storm_feedback_mode` | șir | nu | `none`, `acknowledgement` (implicit) sau `tick`. De asemenea, ce aude apelantul în timp ce modelele audio procesează un schimb atunci când `audio_tier` este `hearing` |
| `language` | șir | nu | Formă prescurtată pentru `primary_language` |
| `primary_language` | șir | nu | Cod de limbă, normalizat (implicit `en`). Codurile care nu pot fi rezolvate resping apelul |
| `has_additional_languages` | boolean | nu | Valoarea implicită este `false` |
| `additional_languages` | matrice de șiruri | nu | Limbi suplimentare la care agentul poate trece |
| `native_voice_switching` | boolean | nu | Valoarea implicită este `false`. Când apelul trece la altă limbă, înlocuiți vocea configurată cu o voce nativă pentru limba respectivă (potrivită după gen) |
| `language_switching` | șir \| null | nu | `ask_first` (implicit) sau `follow_caller`; `null` este echivalent cu `ask_first`. Modul în care un agent multilingv gestionează situația în care cealaltă persoană vorbește o altă limbă a sa. `ask_first` trece imediat când persoana cere limba respectivă sau spune o propoziție completă în ea și întreabă dacă să continue în acea limbă după ceva scurt, cum ar fi un „da”. `follow_caller` trece la orice limbă configurată pe care o vorbește persoana, chiar și pentru un singur cuvânt. Se aplică numai când este definit `additional_languages` |
| `audio_tier` | șir \| null | nu | Numai pentru `product: "bolt"`. `standard` (implicit; `""` și `null` au același sens) rulează trei transcriitori (apelurile care procesează PHI folosesc numai transcriitori acoperiți de BAA). `lean` reduce la un singur transcriitor, care aude greșit mai des. `hearing` adaugă la `standard` un ansamblu puternic de modele audio care ascultă audio-ul apelantului în unele schimburi, care durează cu aproximativ 1–2 secunde mai mult. Alte produse ignoră această opțiune |
| `endpointing` | șir \| null | nu | `faster` (200 ms), `fast` (300 ms), `normal` (500 ms, implicit) sau `patient` (800 ms); `null` este echivalent cu `normal`. Cât timp așteaptă un agent Bolt v2 după ce apelantul se oprește înainte de a cere modelului un răspuns. Așteptările mai scurte pot răspunde mai repede, dar trimit mai multe cereri pe care următoarele cuvinte ale apelantului le fac depășite, ceea ce crește costul modelului. Alte produse ignoră această opțiune |
| `eagerness` | șir \| null | nu | Depreciat: denumirea lui `endpointing` până la 19 octombrie 2026, încă citită. Este ignorat când este definit `endpointing` |
| `intelligence` | șir \| null | nu | `express`, `lite` sau `standard` (implicit); `null` este echivalent cu `standard`. Nivelul de inteligență al unui agent `bolt` pe fluxul Bolt v2: ce model îi scrie răspunsurile. `express` are aproximativ 600 ms până la primul cuvânt, este mai ieftin decât Standard și urmează instrucțiunile cu cea mai mică fiabilitate; `lite` are aproximativ 900 ms, este cel mai ieftin și mai puțin fiabil; `standard` are aproximativ 900 ms și urmează cel mai bine instrucțiunile. Răspunsurile Express și Lite care ar apela doar un instrument sunt predate modelului Standard. Alte produse ignoră această opțiune |
| `background_track` | șir \| null | nu | ID de audio ambiental sau `null` |
| `acknowledgement_prompt_mode` | șir | nu | `auto` (implicit) sau `manual` (produse Storm-with-ack) |
| `acknowledgement_prompt` | șir | nu | Utilizat când `acknowledgement_prompt_mode="manual"` |
| `silence_interval_seconds` | întreg \| null | nu | 5–120. Secunde de tăcere ale apelantului înainte de o verificare |
| `silence_max_checkins` | întreg \| null | nu | 1–10 |
| `silence_checkins_enabled` | boolean | nu | Valoarea implicită este `true` |
| `silence_final_action` | șir | nu | După ultima verificare: `hang_up` (implicit) sau `transfer` către `silence_transfer_destination` |
| `silence_transfer_destination` | șir | nu | Numele unei intrări din `transfer_destinations` al acestei configurații; obligatoriu cu `transfer`. Fără `transfer_destinations`, transferul nu poate fi efectuat, iar agentul închide apelul |
| `silence_final_message` | șir | nu | ≤ 300 de caractere, citit exact cum este scris; `""` (implicit) folosește mesajul implicit |
| `connect_tone_enabled` | boolean | nu | Valoarea implicită este `false` |
| `pronunciation_dicts` | boolean \| null | nu | Valoarea implicită este `false`; `null` este echivalent cu `false`. Când este `true`, vocea Cartesia a apelului utilizează dicționarul de pronunție ThunderPhone pentru limba apelului, acolo unde există. Funcționează pentru apeluri telefonice și prin widget. Se aplică numai vocilor Cartesia proprii ThunderPhone, nu vocilor de pe propria cheie API Cartesia. Nu este utilizat cu `agent_id`, unde se aplică setările agentului salvat |
| `voicemail_action` | șir | nu | `prompt` (implicit), `hangup` sau `message` |
| `voicemail_message` | șir | nu | Utilizat când `voicemail_action="message"` |
| `agent_name` | șir | nu | Nume afișat raportat în tablourile de bord și în widget |
| `org_name` | șir | nu | Numele afișat al organizației pentru persona agentului |
| `tools` | matrice | nu | Scheme de instrumente de funcții inline (consultați [Instrumente de funcții](/ro/tools/overview)) |
| `transfer_destinations` | matrice de obiecte \| null | nu | Până la 50 de intrări `{name, number}` către care acest apel poate fi transferat, validate ca [numerele de transfer](/api-reference/agents#transfer-numbers) ale unui agent. Agentul transferă după nume și numai către acestea; `[]` înseamnă fără transferuri. Omiteți-l sau trimiteți `null` pentru a permite agentului să transfere către un număr ales de acesta |
| `timezone` | șir | nu | Fus orar IANA pentru acest apel, cum ar fi `America/Chicago`. Agentul indică data și ora în acel fus, în locul propriului fus orar al agentului. Este permis și alături de `agent_id`. Valorile care nu sunt zone IANA sunt ignorate. Consultați [Setarea fusului orar pentru fiecare apel](/ro/guides/dynamic-call-config) |
| `call_id` | întreg | nu | Ecou opțional al ID-ului apelului din cerere; ignorat |

<Note>
  Cheile de nivel superior necunoscute sunt **ignorate** în mod silențios — un nume
  de câmp scris greșit nu respinge configurația, pur și simplu nu se aplică. Ordinea
  de vorbire și `max_hold_seconds` nu sunt acceptate aici; acestea pot fi
  configurate numai pe [Agent](/api-reference/agents).
</Note>

Deoarece `prompt` și `voice` sunt obligatorii, returnarea `{}` sau a oricărui răspuns care nu trece validarea respinge apelul: un apel telefonic este încheiat conform descrierii din [Expirări și reîncercări](#timeouts-and-retries), iar o solicitare de sesiune pentru widget eșuează cu `422`. Nu există o rezervă către un agent static pe această cale (un număr sau o cheie în modul webhook nu are un agent atribuit).

---

## Limită de dimensiune a răspunsului

<Warning>
  Răspunsurile de configurare sunt limitate la **5 MiB**. Dacă un handler
  returnează un răspuns mai mare, inclusiv cu un status `2xx`,
  ThunderPhone raportează că răspunsul a depășit limita și
  respinge apelul sau sesiunea widgetului. Păstrați în răspuns doar câmpurile
  necesare pentru configurarea apelului; găzduiți datele mari în spatele unor instrumente de funcții sau
  al altui serviciu, în loc să le încorporați în configurare.
</Warning>

---

## Exemplu de handler

<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>

---

## Răspuns cu instrumente de funcții

Atașați instrumente astfel încât AI-ul să vă poată apela API-urile în timpul conversației:

```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>
  Solicitările către endpointurile instrumentelor sunt semnate cu **același secret
  webhook al organizației** care a semnat acest schimb. Consultați
  [Instrumente de funcții](/ro/tools/overview) pentru structura exactă și formatul
  solicitării semnate.
</Tip>

---

## Fișă rapidă a nivelurilor de produs

| Produs | Latență | Raționament | Confirmare |
|---------|---------|-----------|-----------------|
| `spark` | Cea mai mică | De bază | — |
| `bolt` | Mică | Îmbunătățit | — |
| `storm-base` | Medie | Puternic | — |
| `storm-base-with-ack` | Medie | Puternic | Text de umplere automat în timpul procesării |
| `storm-extra` | Mai mare | Profund | — |
| `storm-extra-with-ack` | Mai mare | Profund | Text de umplere automat în timpul procesării |

---

## Asociate

<CardGroup cols={2}>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/ro/webhooks/call-complete">
    Evenimentul neblocant de finalizare a apelului.
  </Card>
  <Card title="Instrumente de funcții" icon="screwdriver-wrench" href="/ro/tools/overview">
    Schema JSON completă pentru `tools[]` și contractul endpointului semnat.
  </Card>
  <Card title="Endpointuri webhook" icon="bolt" href="/ro/webhooks/endpoints">
    Abonați mai multe URL-uri la `telephony.incoming` / `web.incoming`.
  </Card>
  <Card title="Configurare dinamică a apelului" icon="wand-magic-sparkles" href="/ro/guides/dynamic-call-config">
    Modele pentru prompturi, instrumente și teste A/B pentru fiecare apelant.
  </Card>
</CardGroup>
