---
title: "telephony.incoming / web.incoming"
description: "Blokirajući webhook koji u stvarnom vremenu oblikuje konfiguraciju dolaznog poziva."
---

Kada dolazni telefonski poziv stigne na broj **bez dodijeljenog
agenta** ili kada sesija web widgeta započne na javnom ključu u
`mode="webhook"`, ThunderPhone šalje **blokirajući**
zahtjev `telephony.incoming` / `web.incoming` na Vaš
[URL naslijeđenog web-dojavnika](/api-reference/organizations#legacy-single-url-webhook)
i čeka do **10 sekundi** na odgovor s konfiguracijom. Upotrijebite ovu
razmjenu za dinamički odabir upute, glasa i alata za svaki poziv —
pogledajte [vodič za dinamičku konfiguraciju poziva](/hr/guides/dynamic-call-config)
za cjelovit obrazac.

<Note>
  Pretplaćene [krajnje točke web-dojavnika](/hr/webhooks/endpoints) također primaju
  `telephony.incoming` / `web.incoming` — za **svaki** dolazni poziv
  i web sesiju, bez obzira na to je li agent konfiguriran — ali te su isporuke
  obavijesti tipa „pošalji i zaboravi” s `event_id`, nikada blokirajuće.
  Samo naslijeđeni web-dojavnik s jednim URL-om prenosi razmjenu konfiguracije
  opisanu na ovoj stranici. Oblici obavijesti krajnjih točaka nalaze se u
  [katalogu događaja](/hr/webhooks/events).
</Note>

Blokirajuća razmjena nema rezervnu opciju: ako Vaš obrađivač vrati
status koji nije 2xx, istekne mu vrijeme ili vrati konfiguraciju koja
ne prođe provjeru valjanosti, poziv se odbija (telefonski se poziv ne
uspostavlja; zahtjev za sesiju widgeta ne uspijeva s `502`/`422`).
Odgovorite brzo — pozivatelj čuje signal zvonjenja dok odlučujete.

<Warning>
  **Pozivi konfigurirani putem web-dojavnika ne uključuju ThunderPhoneovu
  obavijest o pristanku.** Pozivi konfigurirani putem ove razmjene zaobilaze
  obavijest na početku poziva na razini agenta i izričito su isključeni iz
  ThunderPhoneova okvira za obavijesti o pristanku (Uvjeti pružanja usluge,
  odjeljak „Snimanje i pristanak”). Vaša je organizacija isključivo
  odgovorna za svaku obavijest i pristanak za snimanje, nadzor, sudjelovanje
  umjetne inteligencije i identifikaciju pozivatelja koji su potrebni za te
  pozive — pozivi se i dalje mogu snimati, transkribirati, analizirati i
  obrađivati umjetnom inteligencijom. Ugradite potrebne obavijesti u vlastiti
  tijek poziva prije omogućavanja ove opcije.
</Warning>

## Sadržaj zahtjeva

Za telefonske pozive (`telephony.incoming`):

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

| Polje | Vrsta | Opis |
|-------|------|-------------|
| `call_id` | cijeli broj | ID poziva — nepromjenjiv u svim događajima za ovaj poziv |
| `from_number` | niz | E.164 broj pozivatelja |
| `to_number` | niz | E.164 odredište (jedan od Vaših ThunderPhone brojeva) |

Za sesije web widgeta (`web.incoming`) `data` umjesto telefonskih
brojeva identificira stranicu na koju je widget ugrađen:

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

| Polje | Vrsta | Opis |
|-------|------|-------------|
| `call_id` | cijeli broj | ID poziva |
| `origin_domain` | niz | Izvorište stranice koja hostira widget |
| `publishable_key_prefix` | niz | Prvi znakovi javnog ključa koji je otvorio sesiju |
| `language`, `primary_language` | niz | Prisutan kada je sesija widgeta zatražila nadjačavanje jezika |
| `voice` | niz | Prisutan kada je sesija widgeta zatražila nadjačavanje glasa |
| `website_context` | niz | Prisutan kada je widget proslijedio kontekst stranice za pojedinačnu sesiju |

<Note>
  Widgeti u načinu rada web-dojavnika šalju ovaj zahtjev na vlastiti
  `webhook_url` javnog ključa kada je postavljen, a inače koriste URL
  web-dojavnika na razini organizacije. U oba je slučaja potpisan tajnom
  `secret` web-dojavnika organizacije.
</Note>

---

## Shema odgovora

Vratite JSON objekt koji opisuje konfiguraciju agenta za ovaj poziv.
`prompt` i `voice` su obavezni; sve ostalo nije obavezno.

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

| Polje | Vrsta | Obavezno | Opis |
|-------|------|----------|-------------|
| `prompt` | string | da | Sistemski prompt koji upravlja agentom |
| `voice` | string | da | ID glasa iz [`GET /v1/voices`](/api-reference/agents#voices), npr. `john`. `voice_name` prihvaća se kao alias. Nepoznati glasovi ne prolaze provjeru valjanosti i odbijaju poziv |
| `product` | string | ne | Zadano je `spark`. Dopušteno: `spark`, `bolt`, `storm-base`, `storm-base-with-ack`, `storm-extra`, `storm-extra-with-ack` |
| `thinking_level` | string | ne | `minimal`, `base` (zadano) ili `extra`. Nadjačano za Storm proizvode: `storm-extra*` prisiljava `extra`, ostali `storm-*` prisiljavaju `base` |
| `audio_context_mode` | string | ne | `full` (zadano) ili `reduced` |
| `watchdog_enabled` | boolean | ne | Omogućite nadzor za ovaj poziv. Zadano je `false` |
| `additional_audio_context` | boolean \| null | ne | Uključite posljednjih nekoliko izmjena zvuka pozivatelja umjesto samo najnovije izmjene, čime se poboljšavaju ispravci i prikupljanje podataka s mnogo slovkanja/brojeva uz malo veće kašnjenje i trošak. Zadano je uključeno za dolazne sesije, a isključeno za odlazne telefonske pozive; `null` zadržava zadanu vrijednost |
| `storm_feedback_mode` | string | ne | `none`, `acknowledgement` (zadano) ili `tick` |
| `language` | string | ne | Skraćeni naziv za `primary_language` |
| `primary_language` | string | ne | Jezični kôd, normaliziran (zadano `en`). Nerazrješivi kôdovi odbijaju poziv |
| `has_additional_languages` | boolean | ne | Zadano je `false` |
| `additional_languages` | array of string | ne | Dodatni jezici na koje se agent može prebaciti |
| `native_voice_switching` | boolean | ne | Zadano je `false`. Kada se poziv prebaci na drugi jezik, zamijenite glas glasom izvornog govornika tog jezika (usklađenim prema rodu) umjesto da zadržite konfigurirani glas |
| `background_track` | string \| null | ne | ID ambijentalnog zvuka ili `null` |
| `acknowledgement_prompt_mode` | string | ne | `auto` (zadano) ili `manual` (Storm-with-ack proizvodi) |
| `acknowledgement_prompt` | string | ne | Koristi se kada je `acknowledgement_prompt_mode="manual"` |
| `silence_interval_seconds` | integer \| null | ne | 5–120. Sekunde tišine pozivatelja prije provjere |
| `silence_max_checkins` | integer \| null | ne | 1–10 |
| `silence_checkins_enabled` | boolean | ne | Zadano je `true` |
| `connect_tone_enabled` | boolean | ne | Zadano je `false` |
| `voicemail_action` | string | ne | `prompt` (zadano), `hangup` ili `message` |
| `voicemail_message` | string | ne | Koristi se kada je `voicemail_action="message"` |
| `agent_name` | string | ne | Naziv za prikaz koji se prijavljuje nadzornim pločama i widgetu |
| `org_name` | string | ne | Naziv organizacije za prikaz za personu agenta |
| `tools` | array | ne | Ugrađene sheme funkcijskih alata (pogledajte [Funkcijski alati](/hr/tools/overview)) |
| `call_id` | integer | ne | Neobavezni odjek ID-a poziva iz zahtjeva; zanemaruje se |

<Note>
  Nepoznati ključevi najviše razine tiho se **zanemaruju** — pogrešno napisani naziv
  polja ne odbija konfiguraciju, samo se ne primjenjuje. Redoslijed govora
  i `max_hold_seconds` ovdje se ne prihvaćaju; mogu se konfigurirati samo
  na samom [Agentu](/api-reference/agents).
</Note>

Budući da su `prompt` i `voice` obavezni, vraćanje `{}` ili bilo kojeg
odgovora koji ne prođe provjeru valjanosti odbija poziv s `422` — na ovom
putu nema zamjenskog statičkog agenta (broj ili ključ u načinu rada webhooka
nema dodijeljenog agenta).

---

## Ograničenje veličine odgovora

<Warning>
  Odgovori konfiguracije ograničeni su na **5 MiB**. Ako obrađivač
  vrati veći odgovor, uključujući odgovor sa statusom `2xx`,
  ThunderPhone prijavljuje da je odgovor premašio ograničenje i
  odbija poziv ili sesiju widgeta. U odgovoru zadržite samo polja
  potrebna za postavljanje poziva; velike podatke smjestite iza funkcijskih alata ili
  druge usluge umjesto da ih ugrađujete u konfiguraciju.
</Warning>

---

## Primjer obrađivača

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

---

## Odgovor s funkcijskim alatima

Priložite alate kako bi AI mogao pozivati vaše API-je usred razgovora:

```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>
  Zahtjevi prema krajnjoj točki alata potpisani su **istom tajnom
  webhooka organizacije** kojom je potpisana ova razmjena. Pogledajte
  [Funkcijski alati](/hr/tools/overview) za točan oblik i format potpisanog
  zahtjeva.
</Tip>

---

## Brzi pregled razina proizvoda

| Proizvod | Latencija | Raspon zaključivanja | Potvrda |
|---------|---------|-----------|-----------------|
| `spark` | Najniža | Osnovno | — |
| `bolt` | Niska | Poboljšano | — |
| `storm-base` | Srednja | Snažno | — |
| `storm-base-with-ack` | Srednja | Snažno | Automatska dopuna tijekom razmišljanja |
| `storm-extra` | Viša | Duboko | — |
| `storm-extra-with-ack` | Viša | Duboko | Automatska dopuna tijekom razmišljanja |

---

## Povezano

<CardGroup cols={2}>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/hr/webhooks/call-complete">
    Neblokirajući događaj završetka poziva.
  </Card>
  <Card title="Alati funkcija" icon="screwdriver-wrench" href="/hr/tools/overview">
    Potpuna JSON shema za `tools[]` i ugovor potpisane krajnje točke.
  </Card>
  <Card title="Krajnje točke webhooka" icon="bolt" href="/hr/webhooks/endpoints">
    Pretplatite više URL-ova na `telephony.incoming` / `web.incoming`.
  </Card>
  <Card title="Dinamička konfiguracija poziva" icon="wand-magic-sparkles" href="/hr/guides/dynamic-call-config">
    Obrasci za upite, alate i A/B testove za svakog pozivatelja.
  </Card>
</CardGroup>
