---
title: "Dinamiska konfigurācija katram zvanam"
description: "Katram ienākošajam zvanam atsevišķi izvēlieties atbildētāju balss aģentu vai pārrakstiet tā uzvedni un iestatījumus, izmantojot pielāgotu loģiku jūsu kontrolētā tīmekļa aizķerē."
---

Pēc noklusējuma katram tālruņa numuram un publicējamajai atslēgai ir piešķirts statisks aģents. Ja nepieciešama **katram zvanītājam** vai **katram apmeklētājam** pielāgota konfigurācija — VIP maršrutēšana, pieteikta lietotāja konteksts, A/B uzvedņu testi — pārslēdzieties uz tīmekļa aizķeres režīmu un ļaujiet serverim pieņemt lēmumu.

## Kā tas darbojas

1. Jūs abonējat [`telephony.incoming`](/lv/webhooks/events)
   (tālrunis) vai [`web.incoming`](/lv/webhooks/events) (logrīks)
   notikumu. Abi ir **bloķējoši** webhooki: ThunderPhone gaida jūsu
   atbildi, pirms turpināt zvanu — līdz 13 sekundēm tālruņa
   zvanam (ieskaitot vienu atkārtotu mēģinājumu) un 10 sekundēm logrīka sesijai.
2. ThunderPhone nosūta jums `{call_id, from_number, to_number}` (logrīka
   sesijās numuru vietā tiek izmantoti logrīkam specifiski lauki — skatiet
   [pieprasījuma shēmu](/lv/webhooks/call-incoming)).
3. Jūsu serveris atbild ar balss aģenta konfigurāciju (uzvedne, balss,
   produkts, rīki). ThunderPhone izmanto šo konfigurāciju zvanam.
4. Nav rezerves balss aģenta. Ja atgriežat `{}` vai nederīgu
   konfigurāciju vai pieprasījums joprojām neizdodas pēc
   [atkārtota mēģinājuma](/lv/webhooks/call-incoming), tālruņa
   zvans tiek nekavējoties pārtraukts un reģistrēts ar `end_reason`
   `inbound_config_webhook_failed`; logrīka sesijas pieprasījums neizdodas.

<Note>
  Tālruņa zvaniem (`telephony.incoming`) un logrīka sesijām
  (`web.incoming`) tas darbojas identiski neatkarīgi no tā, vai notikums tiek
  piegādāts tīmekļa aizķeres galapunktam vai mantotajai viena URL tīmekļa aizķerei.
</Note>

<Warning>
  **Zvaniem, kas konfigurēti tieši tīmekļa aizķerē, netiek atskaņots neviens
  ThunderPhone piekrišanas paziņojums.** Šajā plūsmā tiek apiets aģenta līmeņa
  zvana sākuma paziņojums, un tā ir skaidri izslēgta no ThunderPhone piekrišanas
  paziņojumu sistēmas (Pakalpojumu sniegšanas noteikumu sadaļa "Ierakstīšana un
  piekrišana"). Jūsu organizācija ir atbildīga par visiem šo zvanu ierakstīšanas,
  uzraudzības, mākslīgā intelekta līdzdalības un zvanītāja identifikācijas
  paziņojumiem un piekrišanām. Nodrošiniet tos savā plūsmā — piemēram, uzvednes
  sākuma skriptā — pirms tiešās tīmekļa aizķeres režīma iespējošanas. Tīmekļa
  aizķeres atbilde, kas atsaucas uz saglabātu `agent_id`, izmanto šī aģenta
  parasto ierakstīšanas un informācijas atklāšanas politiku.
</Warning>

## 1. Konfigurējiet tīmekļa aizķeres galamērķi

<Tabs>
<Tab title="Tālruņa zvani">
Tālruņa numuriem abonējiet savu galapunktu notikumam `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"]
  }'
```

Atbildē ir vienreiz lietojams `secret` — saglabājiet to; tas būs nepieciešams
paraksta verifikācijai.
</Tab>
<Tab title="Tīmekļa logrīks">
Logrīka sesijām izveidojiet publicējamu atslēgu ar `mode="webhook"`,
kurā ir iekļauts jūsu galapunkta URL:

```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"]
  }'
```

Logrīks katras sesijas sākumā veiks POST pieprasījumu uz šo URL.
</Tab>
</Tabs>

## 2. Ieviesiet apstrādātāju

Trīs pamatprincipi:

- **Pārbaudiet parakstu** katram pieprasījumam (skatiet
  [Tīmekļa aizķeru parakstu pārbaude](/lv/guides/verify-webhook-signatures)).
  Neizlaidiet to izstrādes vidē — ieviesiet pareizi vienreiz un izmantojiet atkārtoti.
- **Atbildiet ātri**. Tālruņa zvana pirmais mēģinājums tiek pārtraukts pēc 10
  sekundēm, bet visa apmaiņa — pēc 13 sekundēm, un katra sekunde zvanītājam ir klusums.
  Ja nepieciešams, veiciet datubāzes uzmeklēšanu, bet nesauciet pakārtotos LLM sinhroni —
  ja vēlaties dinamisku uzvednes ģenerēšanu, iepriekš aprēķiniet un kešojiet.
- **Korekti izmantojiet rezerves variantu**. Jebkuram neparedzētam stāvoklim atbildiet ar
  noklusējuma `prompt` un `voice` (vai saglabātu `agent_id`). Atgriežot `{}`
  vai kļūdas statusu, zvans tiek pārtraukts.

<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. Atbildes shēma

Atbildes pamatteksts precīzi atbilst
[ienākošā zvana atbildes shēmai](/lv/webhooks/call-incoming).
Bieži izmantotie lauki:

| Lauks | Tips | Apraksts |
|-------|------|-------------|
| `prompt` | virkne (obligāts) | Balss aģenta sistēmas uzvedne |
| `voice` | virkne (obligāts) | Balss ID no [`GET /v1/voices`](/api-reference/agents#voices) |
| `product` | virkne | Pēc noklusējuma ir `spark`. Eksperimentālie produkti ir pieejami tikai organizācijām atļauju sarakstā. |
| `background_track` | virkne \| null | Fona audio ID |
| `acknowledgement_prompt_mode` | virkne | `auto` vai `manual` (tikai Storm ar apstiprinājumu) |
| `acknowledgement_prompt` | virkne | Obligāts, ja režīms ir `manual` |
| `language_switching` | virkne | Daudzvalodu balss aģentiem: `ask_first` vai `follow_caller` |
| `tools` | masīvs | Iekļautās funkciju rīku shēmas — skatiet [Funkciju rīki](/lv/tools/overview) |

<Note>
  Katram zvanam atsevišķa runas secība un `max_hold_seconds` nav pieejami
  webhook atbildē. Iestatiet tos norādītajam
  [balss aģentam](/api-reference/agents).
</Note>

### Saglabājiet balss aģentu un nododiet mainīgos

Atgrieziet `{"agent_id": 12, "variables": {"name": "Ada"}}`, lai izmantotu šīs organizācijas
saglabāto balss aģentu ar katra izsaukuma datiem. Tā uzvednē var būt `{{name}}` vai
`{{name|Friend}}`. Tīmekļa aizķeres mainīgie tiek apvienoti ar pieprasījuma līmeņa mainīgajiem; null
izmanto viettura noklusējuma vērtību vai tukšu tekstu, ja tāda nav norādīta. Galīgās
vērtības un neatrisinātie nosaukumi tiek parādīti izsaukuma detalizētajā informācijā un pabeigšanas tīmekļa aizķerēs.
Saglabātā balss aģenta atbildes pieņem tikai `agent_id`, `variables` un `timezone`. Ja ir
norādīts `prompt`, atbilde izmanto iekļauto konfigurāciju un ignorē `agent_id` (tostarp
null vai neveselu skaitļu metadatus); iekļautajai uzvednei joprojām jābūt derīgai. Iekļautās
konfigurācijas atbildēs var būt arī `variables`. Saglabātā balss aģenta atbildes izmanto
aģenta izvietoto A/B sadalījumu gan tālruņa, gan logrīka izsaukumiem un pēc tam atveido mainīgos. Skatiet [izsaukuma mainīgos](/lv/guides/call-variables),
lai uzzinātu par ierobežojumiem un sesijas API atbalstu. Bloķējošā konfigurācija tiek iegūta no mantotā
tālruņa numura/organizācijas URL vai tīmekļa aizķeres režīma logrīka atslēgas; galapunktu sistēmā
ienākošie notikumi ir tikai paziņojumi.

### Iestatiet laika joslu katram zvanam

Viens balss aģents var atbildēt kontaktpersonām dažādās laika joslās. Pievienojiet `timezone` — IANA nosaukumu — saglabātā aģenta vai iekļautajai atbildei, un aģents šim zvanam norādīs datumu un laiku, kā arī piedāvās laikus šajā joslā, nevis aģenta paša laika joslā:

```json
{"agent_id": 12, "timezone": "America/Chicago", "variables": {"name": "Ada"}}
```

Sūtiet joslu, nevis laikspiedolu laukā `variables`: aģenta pulkstenis zvana laikā turpina darboties, un jūsu nodotais laiks noveco. Vērtība, kas nav IANA josla, tiek ignorēta, un zvans tiek savienots aģenta laika joslā.

## Modeļi

### Pieteikušās personas konteksts

Webhook režīma logrīkos apmeklētāja lapa jau zina, kas viņš ir.
Izsauciet savu webhook ar vaicājuma virknes parametru, ko logrīka SDK
pārsūta (`?customer_id=123`), un atrodiet klientu servera pusē.

### A/B uzvedņu ieviešana

Pirms veidojat to manuāli, ņemiet vērā, ka ThunderPhone ir vietējā
[Eksperimentu](/lv/guides/concepts) funkcija
(`/dashboard/experiments` un balss aģenta veidotāja cilne **A/B**), kas
definē variantus, sadala datplūsmu un salīdzina rezultātus katram variantam —
webhook nav nepieciešams.

Ja tomēr nepieciešama vadība webhook pusē: jauciet `call_id` → segments;
apkalpojiet uzvedni A vērtībām `0..49` un uzvedni B vērtībām `50..99`. Saglabājiet,
kuru segmentu izvēlējāties, savā datubāzē un vēlāk sasaistiet to ar
pabeigtā zvana vērtējumu.

### Maršrutēšana pēc laika

Darba laikā → balss aģents “tiešais atbalsts”; ārpus darba laika → balss aģents “ziņas pieņemšana”.
Vienkārša pārslēgšana uz `new Date().getUTCHours()` jūsu apstrādātājā.

---

## Nākamie soļi

<CardGroup cols={2}>
  <Card title="Ienākošā zvana webhook atsauce" icon="phone" href="/lv/webhooks/call-incoming">
    Precīzas pieprasījuma un atbildes shēmas, tostarp katra konfigurācijas atslēga.
  </Card>
  <Card title="Pārbaudiet webhook parakstus" icon="shield-check" href="/lv/guides/verify-webhook-signatures">
    Vienreiz pareizi iestatiet HMAC; izmantojiet to atkārtoti visur.
  </Card>
  <Card title="Izveidojiet rīka integrāciju" icon="screwdriver-wrench" href="/lv/guides/build-tool-integration">
    Apvienojiet dinamisko maršrutēšanu ar balss aģentu rīkiem.
  </Card>
  <Card title="Piegādes semantika" icon="bolt" href="/lv/webhooks/overview">
    Atkārtoti mēģinājumi, secība, taimauti.
  </Card>
</CardGroup>
