---
title: "telephony.incoming / web.incoming"
description: "Blokerende webhook, der former konfigurationen for et indgående opkald i realtid."
---

Når et indgående telefonopkald når et nummer **uden en tilknyttet
agent**, eller en webwidgetsession starter på en publicerbar nøgle i
`mode="webhook"`, sender ThunderPhone en **blokerende**
`telephony.incoming` / `web.incoming`-anmodning til din
[ældre webhook-URL](/api-reference/organizations#legacy-single-url-webhook)
og venter på et konfigurationssvar: op til **13 sekunder** for et
telefonopkald, inklusive ét genforsøg, og op til **10 sekunder** for en
widgetsession (se [Timeouts and retries](#timeouts-and-retries)). Brug denne
udveksling til dynamisk at vælge en prompt, stemme og værktøjer pr. opkald —
se [vejledningen til dynamisk opkaldskonfiguration](/da/guides/dynamic-call-config)
for det fulde mønster.

<Note>
  Abonnerede [webhookslutpunkter](/da/webhooks/endpoints) modtager også
  `telephony.incoming` / `web.incoming` — for **hvert** indgående opkald
  og hver websession, uanset om der er konfigureret en agent eller ej —
  men disse leveringer er fire-and-forget-meddelelser med et `event_id`,
  aldrig blokerende. Kun den ældre webhook med én URL indeholder
  konfigurationsudvekslingen på denne side. Formerne for
  slutpunktmeddelelser findes i [hændelseskataloget](/da/webhooks/events).
</Note>

## Tidsgrænser og genforsøg

Svar hurtigt: Personen, der ringer, venter på linjen, mens du beslutter dig.

For et telefonopkald (`telephony.incoming`):

- Det første forsøg kan tage op til **10 sekunder**.
- Hvis det får timeout, ikke kan oprette forbindelse eller modtager et `5xx`-, `408`- eller `429`-svar, prøver ThunderPhone én gang til. Genforsøget får den resterende tid af et budget på **13 sekunder** for hele udvekslingen: omkring 3 sekunder efter et første forsøg med timeout, næsten alle 13 efter en hurtig fejl.
  Der foretages ikke noget genforsøg, hvis der ville være mindre end 2 sekunder tilbage.
- Ethvert andet `4xx`-svar, et svar over
  [størrelsesgrænsen](#response-size-limit) eller et `2xx`-svar, hvis brødtekst ikke er en
  gyldig konfiguration, er endeligt og prøves ikke igen.
- Begge forsøg sender den samme brødtekst, den samme `X-ThunderPhone-Signature`
  og den samme `X-ThunderPhone-Idempotency-Key`-header
  (`telephony-incoming-<call_id>`), så en handler med bivirkninger
  kan genkende genforsøget.

Der er ingen fallback-agent. Hvis der ikke modtages en brugbar konfiguration, afsluttes
opkaldet straks i stedet for at lade personen, der ringer, vente på en stille
linje. Det vises i opkaldshistorikken som et mislykket, ikke-faktureret opkald med
`end_reason` `inbound_config_webhook_failed`, og det sædvanlige
[`telephony.complete`](/da/webhooks/call-complete)-event sendes.

En widgetsession (`web.incoming`) får ét forsøg på op til 10
sekunder. Hvis det mislykkes, mislykkes sessionsanmodningen med `502` eller `422`.

<Warning>
  **Webhookkonfigurerede opkald indeholder ingen
  samtykkemeddelelse fra ThunderPhone.** Opkald, der konfigureres via denne
  udveksling, omgår agentniveauets meddelelse ved opkaldsstart og er
  udtrykkeligt udelukket fra ThunderPhones ramme for samtykkemeddelelser
  (Vilkår for brug, afsnittet "Optagelse og samtykke"). Din organisation
  er eneansvarlig for alle meddelelser og samtykker om optagelse,
  overvågning, AI-deltagelse og identifikation af opkalderen, som kræves
  ved disse opkald — opkaldene kan stadig optages, transskriberes,
  analyseres og håndteres af AI. Indbyg de nødvendige oplysninger i dit
  eget opkaldsflow, før du aktiverer denne sti.
</Warning>

## Anmodningspayload

For telefonopkald (`telephony.incoming`):

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

| Felt | Type | Beskrivelse |
|-------|------|-------------|
| `call_id` | integer | Opkalds-id — stabilt på tværs af alle hændelser for dette opkald |
| `from_number` | string | Opkaldernummer i E.164-format |
| `to_number` | string | Destination i E.164-format (et af dine ThunderPhone-numre) |

For webwidgetsessioner (`web.incoming`) identificerer `data`
indlejringssiden i stedet for telefonnumre:

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

| Felt | Type | Beskrivelse |
|-------|------|-------------|
| `call_id` | integer | Opkalds-id |
| `origin_domain` | string | Sidens oprindelse, der hoster widgetten, som browseren sendte den. En klient, der ikke er en browser, kan sende en vilkårlig værdi, så betragt den ikke som bevis på, hvor anmodningen kom fra |
| `publishable_key_prefix` | string | Første tegn i den publicerbare nøgle, der åbnede sessionen |
| `language`, `primary_language` | string | Findes, når widgetsessionen har anmodet om en sprogtilsidesættelse |
| `voice` | string | Findes, når widgetsessionen har anmodet om en stemmetilsidesættelse |
| `website_context` | string | Findes, når widgetten har sendt sidekontekst pr. session |

Tilsidesættelsesfelterne (`language`, `voice`, `website_context` og eventuelle
browser-`variables`) ankommer kun, når den publicerbare nøgle tillader dem i
sine [browsertilsidesættelser](/da/guides/embed-web-widget). En
sessionsanmodning med en tilsidesættelse, som nøglen ikke tillader, afvises,
før denne webhook kaldes.

<Note>
  Widgets i webhooktilstand leverer denne anmodning til den publicerbare
  nøgles egen `webhook_url`, når en sådan er angivet, og falder ellers
  tilbage til webhook-URL'en på organisationsniveau. I begge tilfælde er
  den signeret med organisationens webhook-`secret`.
</Note>

---

## Svarskema

Returner et JSON-objekt, der beskriver agentkonfigurationen for dette opkald.
`prompt` og `voice` er påkrævede; alt andet er valgfrit.

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

| Felt | Type | Påkrævet | Beskrivelse |
|-------|------|----------|-------------|
| `prompt` | streng | ja | Systemprompt, der styrer agenten |
| `voice` | streng | ja | Stemme-id fra [`GET /v1/voices`](/api-reference/agents#voices), f.eks. `john`. `voice_name` accepteres som et alias. Ukendte stemmer fejler validering og afviser opkaldet |
| `product` | streng | nej | Standard er `spark`. Tilladt: `spark`, `bolt`, `storm-base`, `storm-base-with-ack`, `storm-extra`, `storm-extra-with-ack` |
| `thinking_level` | streng | nej | `minimal`, `base` (standard) eller `extra`. Tilsidesættes for Storm-produkter: `storm-extra*` tvinger `extra`, andre `storm-*` tvinger `base` |
| `audio_context_mode` | streng | nej | `full` (standard) eller `reduced` |
| `watchdog_enabled` | boolesk | nej | Aktivér overvågning for dette opkald. Standard er `false` |
| `additional_audio_context` | boolesk \| null | nej | Medtag de seneste par runder af opkalderens lyd i stedet for kun den seneste runde, hvilket forbedrer rettelser og indsamling af data med mange stavemåder eller tal med en lille meromkostning i latenstid og pris. Er som standard slået til for indgående sessioner og slået fra for udgående telefonopkald; `null` bevarer standardindstillingen |
| `storm_feedback_mode` | streng | nej | `none`, `acknowledgement` (standard) eller `tick`. Angiver også, hvad opkalderen hører, mens lydmodellerne behandler en runde, når `audio_tier` er `hearing` |
| `language` | streng | nej | Forkortelse for `primary_language` |
| `primary_language` | streng | nej | Sprogkode, normaliseret (standard er `en`). Koder, der ikke kan fortolkes, afviser opkaldet |
| `has_additional_languages` | boolesk | nej | Standard er `false` |
| `additional_languages` | array af strenge | nej | Ekstra sprog, som agenten kan skifte til |
| `native_voice_switching` | boolesk | nej | Standard er `false`. Når opkaldet skifter til et andet sprog, skal der skiftes til en stemme med det pågældende sprog som modersmål (matchet efter køn) i stedet for at beholde den konfigurerede stemme |
| `language_switching` | streng \| null | nej | `ask_first` (standard) eller `follow_caller`; `null` er det samme som `ask_first`. Angiver, hvordan en flersproget agent håndterer, at den anden person taler et andet af dens sprog. `ask_first` skifter straks, når personen beder om sproget eller siger en hel sætning på det, og spørger, om samtalen skal fortsætte på det efter noget kort, som et "ja". `follow_caller` skifter til ethvert konfigureret sprog, personen taler, selv ved et enkelt ord. Gælder kun, når `additional_languages` er angivet |
| `audio_tier` | streng \| null | nej | Kun `product: "bolt"`. `standard` (standard; `""` og `null` betyder det samme) kører tre transskriberingsmodeller (opkald, der behandler PHI, bruger kun BAA-dækkede transskriberingsmodeller). `lean` nedgraderer til én transskriberingsmodel, som fejlhører oftere. `hearing` opgraderer til `standard` plus et kraftfuldt ensemble af lydmodeller, der lytter til opkalderens lyd i nogle runder, som tager ca. 1–2 sekunder længere. Andre produkter ignorerer det |
| `endpointing` | streng \| null | nej | `faster` (200 ms), `fast` (300 ms), `normal` (500 ms, standard) eller `patient` (800 ms); `null` er det samme som `normal`. Angiver, hvor længe en Bolt v2-agent venter, efter opkalderen stopper, før modellen bedes om et svar. Kortere ventetid kan svare hurtigere, men sender flere anmodninger, som opkalderens næste ord gør forældede, hvilket øger modelomkostningen. Andre produkter ignorerer det |
| `eagerness` | streng \| null | nej | Forældet: navnet på `endpointing` indtil 19. oktober 2026, læses stadig. Ignoreres, når `endpointing` er angivet |
| `intelligence` | streng \| null | nej | `express`, `lite` eller `standard` (standard); `null` er det samme som `standard`. Intelligensniveauet for en `bolt`-agent på Bolt v2-pipelinen: hvilken model der skriver dens svar. `express` bruger ca. 600 ms til første ord, er billigere end Standard og følger instruktioner mindst pålideligt; `lite` bruger ca. 900 ms, er billigst og mindre pålidelig; `standard` bruger ca. 900 ms og er bedst til at følge instruktioner. Express- og Lite-svar, der kun ville kalde et værktøj, sendes videre til Standard-modellen. Andre produkter ignorerer det |
| `background_track` | streng \| null | nej | Id for baggrundslyd eller `null` |
| `acknowledgement_prompt_mode` | streng | nej | `auto` (standard) eller `manual` (Storm-with-ack-produkter) |
| `acknowledgement_prompt` | streng | nej | Bruges, når `acknowledgement_prompt_mode="manual"` |
| `silence_interval_seconds` | heltal \| null | nej | 5–120. Sekunder med stilhed fra opkalderen før en opfølgning |
| `silence_max_checkins` | heltal \| null | nej | 1–10 |
| `silence_checkins_enabled` | boolesk | nej | Standard er `true` |
| `silence_final_action` | streng | nej | Efter den sidste opfølgning: `hang_up` (standard) eller `transfer` til `silence_transfer_destination` |
| `silence_transfer_destination` | streng | nej | Navn på en post i denne konfigurations `transfer_destinations`; kræves med `transfer`. Uden `transfer_destinations` kan viderestillingen ikke gennemføres, og agenten lægger på |
| `silence_final_message` | streng | nej | ≤ 300 tegn, læses op som skrevet; `""` (standard) bruger standardlinjen |
| `connect_tone_enabled` | boolesk | nej | Standard er `false` |
| `pronunciation_dicts` | boolesk \| null | nej | Standard er `false`; `null` er det samme som `false`. Når værdien er `true`, bruger opkaldets Cartesia-tale ThunderPhones udtaleordbog for opkaldets sprog, hvor en findes. Fungerer for telefon- og widgetopkald. Gælder kun ThunderPhones egne Cartesia-stemmer, ikke stemmer på din egen Cartesia API-nøgle. Bruges ikke med `agent_id`, hvor den gemte agents indstillinger gælder |
| `voicemail_action` | streng | nej | `prompt` (standard), `hangup` eller `message` |
| `voicemail_message` | streng | nej | Bruges, når `voicemail_action="message"` |
| `agent_name` | streng | nej | Visningsnavn, der rapporteres til dashboards og widgetten |
| `org_name` | streng | nej | Organisationens visningsnavn for agentens persona |
| `tools` | array | nej | Integrerede skemaer for funktionsværktøjer (se [Funktionsværktøjer](/da/tools/overview)) |
| `transfer_destinations` | array af objekt \| null | nej | Op til 50 poster med `{name, number}`, som dette opkald kan viderestilles til, valideret som en agents [viderestillingsnumre](/api-reference/agents#transfer-numbers). Agenten viderestiller efter navn og kun til disse; `[]` betyder ingen viderestillinger. Udelad feltet eller send `null` for at lade agenten viderestille til et nummer, den vælger |
| `timezone` | streng | nej | IANA-tidszone for dette opkald, f.eks. `America/Chicago`. Agenten angiver dato og klokkeslæt i den frem for agentens egen tidszone. Tilladt også sammen med `agent_id`. Værdier, der ikke er IANA-zoner, ignoreres. Se [Angiv tidszonen pr. opkald](/da/guides/dynamic-call-config) |
| `call_id` | heltal | nej | Valgfrit ekko af anmodningens opkalds-id; ignoreres |

<Note>
  Ukendte nøgler på øverste niveau **ignoreres** uden fejl — et felt
  med stavefejl afviser ikke konfigurationen, det anvendes bare ikke. Talerækkefølge
  og `max_hold_seconds` accepteres ikke her; de kan kun
  konfigureres på selve [Agent](/api-reference/agents).
</Note>

Da `prompt` og `voice` er påkrævet, afviser returnering af `{}` eller et
svar, der fejler valideringen, opkaldet: Et telefonopkald afsluttes
som beskrevet i [Timeouts og genforsøg](#timeouts-and-retries), og en
widget-sessionsforespørgsel fejler med `422`. Der er ingen fallback til en
statisk agent på denne sti (et nummer eller en nøgle i webhook-tilstand har ingen tildelt
agent).

---

## Grænse for svarstørrelse

<Warning>
  Konfigurationssvar er begrænset til **5 MiB**. Hvis en handler
  returnerer et større svar, også med en `2xx`-status,
  rapporterer ThunderPhone, at svaret overskred grænsen, og
  afviser opkaldet eller widgetsessionsen. Begræns svaret til de felter,
  der er nødvendige for opsætning af opkald; host store data bag funktionsværktøjer eller
  en anden tjeneste i stedet for at indlejre dem i konfigurationen.
</Warning>

---

## Eksempel på 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>

---

## Svar med funktionsværktøjer

Tilknyt værktøjer, så AI'en kan kalde dine API'er midt i samtalen:

```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>
  Anmodninger til værktøjsendepunkter signeres med den **samme organisations-webhook-
  hemmelighed**, som signerede denne udveksling. Se
  [Funktionsværktøjer](/da/tools/overview) for den nøjagtige struktur og det signerede
  anmodningsformat.
</Tip>

---

## Produktniveauer – hurtig oversigt

| Produkt | Latens | Ræsonnering | Bekræftelse |
|---------|---------|-------------|-------------|
| `spark` | Lavest | Grundlæggende | — |
| `bolt` | Lav | Forbedret | — |
| `storm-base` | Mellem | Stærk | — |
| `storm-base-with-ack` | Mellem | Stærk | Automatisk udfyldning, mens der tænkes |
| `storm-extra` | Højere | Dyb | — |
| `storm-extra-with-ack` | Højere | Dyb | Automatisk udfyldning, mens der tænkes |

---

## Relateret

<CardGroup cols={2}>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/da/webhooks/call-complete">
    Den ikke-blokerende hændelse ved opkaldets afslutning.
  </Card>
  <Card title="Funktionsværktøjer" icon="screwdriver-wrench" href="/da/tools/overview">
    Fuld JSON-schema for `tools[]` og den signerede endpoint-kontrakt.
  </Card>
  <Card title="Webhook-endpoints" icon="bolt" href="/da/webhooks/endpoints">
    Abonner flere URL'er på `telephony.incoming` / `web.incoming`.
  </Card>
  <Card title="Dynamisk opkaldskonfiguration" icon="wand-magic-sparkles" href="/da/guides/dynamic-call-config">
    Mønstre til prompts, værktøjer og A/B-tests pr. opkalder.
  </Card>
</CardGroup>
