---
title: "telephony.incoming / web.incoming"
description: "Blockerande webhook som formar konfigurationen för ett inkommande samtal i realtid."
---

När ett inkommande telefonsamtal når ett nummer **utan en tilldelad
röstagent**, eller när en webbwidgets-session startar med en publicerbar nyckel i
`mode="webhook"`, skickar ThunderPhone en **blockerande**
`telephony.incoming` / `web.incoming`-begäran till din
[äldre webhook-URL](/api-reference/organizations#legacy-single-url-webhook)
och väntar på ett konfigurationssvar: upp till **13 sekunder** för ett
telefonsamtal, inklusive ett återförsök, och upp till **10 sekunder** för en
widgetsession (se [Timeouter och återförsök](#timeouts-and-retries)). Använd detta
utbyte för att dynamiskt välja en prompt, röst och verktyg per samtal —
se guiden för [dynamisk samtalskonfiguration](/sv/guides/dynamic-call-config)
för flödet från början till slut.

<Note>
  Prenumererade [webhook-slutpunkter](/sv/webhooks/endpoints) tar också emot
  `telephony.incoming` / `web.incoming` — för **varje** inkommande samtal
  och webbsession, oavsett om en röstagent är konfigurerad eller inte — men
  dessa leveranser är brand-och-glöm-notiser med ett `event_id`, aldrig
  blockerande. Endast den äldre webhooken med en enda URL hanterar
  konfigurationsutbytet på denna sida. Format för slutpunktsnotiser finns i
  [händelsekatalogen](/sv/webhooks/events).
</Note>

## Tidsgränser och återförsök

Svara snabbt: uppringaren väntar kvar i samtalet medan du bestämmer dig.

För ett telefonsamtal (`telephony.incoming`):

- Det första försöket kan ta upp till **10 sekunder**.
- Om det får en timeout, inte kan ansluta eller får ett svar med `5xx`, `408` eller `429` försöker ThunderPhone en gång till. Återförsöket får det som återstår av en budget på **13 sekunder** för hela utbytet: cirka 3 sekunder efter ett första försök som fick timeout, nästan alla 13 efter ett snabbt fel. Inget återförsök görs när mindre än 2 sekunder skulle återstå.
- Alla andra `4xx`-svar, ett svar över [storleksgränsen](#response-size-limit) eller ett `2xx` vars brödtext inte är en giltig konfiguration är slutgiltiga och försöks inte igen.
- Båda försöken skickar samma brödtext, samma `X-ThunderPhone-Signature` och samma `X-ThunderPhone-Idempotency-Key`-header (`telephony-incoming-<call_id>`), så att en hanterare med sidoeffekter kan känna igen återförsöket.

Det finns ingen reservröstagent. Om ingen användbar konfiguration kommer fram avslutas samtalet direkt i stället för att låta uppringaren vänta i en tyst linje. Det visas i samtalshistoriken som ett misslyckat, ej debiterat samtal med `end_reason` `inbound_config_webhook_failed`, och det vanliga [`telephony.complete`](/sv/webhooks/call-complete)-eventet skickas.

En widgetsessions (`web.incoming`) får ett enda försök på upp till 10 sekunder. Om det misslyckas misslyckas sessionsbegäran med `502` eller `422`.

<Warning>
  **Webhook-konfigurerade samtal innehåller inget samtyckesmeddelande från
  ThunderPhone.** Samtal som konfigureras via detta utbyte kringgår
  meddelandet vid samtalsstart på agentnivå och är uttryckligen undantagna från
  ThunderPhones ramverk för samtyckesmeddelanden (användarvillkor, avsnittet
  "Inspelning och samtycke"). Din organisation är ensam ansvarig för alla
  meddelanden och samtycken om inspelning, övervakning, AI-deltagande och
  identifiering av den som ringer som krävs för dessa samtal — samtalen kan
  fortfarande spelas in, transkriberas, analyseras och hanteras av AI. Bygg in
  de obligatoriska upplysningarna i ditt eget samtalsflöde innan du aktiverar
  denna väg.
</Warning>

## Begärans nyttolast

För telefonsamtal (`telephony.incoming`):

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

| Fält | Typ | Beskrivning |
|-------|------|-------------|
| `call_id` | integer | Samtals-ID — stabilt i alla händelser för detta samtal |
| `from_number` | string | E.164-nummer för den som ringer |
| `to_number` | string | E.164-destination (ett av dina ThunderPhone-nummer) |

För webbsessioner i webbwidgeten (`web.incoming`) identifierar `data`
inbäddningssidan i stället för telefonnummer:

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

| Fält | Typ | Beskrivning |
|-------|------|-------------|
| `call_id` | heltal | Samtals-id |
| `origin_domain` | sträng | Sidans ursprung som är värd för widgeten, enligt vad webbläsaren skickade. En klient som inte är en webbläsare kan skicka vilket värde som helst, så behandla det inte som bevis på var begäran kom ifrån |
| `publishable_key_prefix` | sträng | De första tecknen i den publicerbara nyckel som öppnade sessionen |
| `language`, `primary_language` | sträng | Finns när widgetsessionen begärde en språköverstyrning |
| `voice` | sträng | Finns när widgetsessionen begärde en röstöverstyrning |
| `website_context` | sträng | Finns när widgeten skickade sidkontext per session |

Överstyrningsfälten (`language`, `voice`, `website_context` och eventuella
`variables` från webbläsaren) skickas endast när den publicerbara nyckeln tillåter dem i
sina [webbläsaröverstyrningar](/sv/guides/embed-web-widget). En
sessionsbegäran som innehåller en överstyrning som nyckeln inte tillåter avvisas innan
denna webhook anropas.

<Note>
  Widgetar i webhook-läge levererar denna begäran till den publicerbara
  nyckelns egen `webhook_url` när en sådan är angiven och använder annars
  webhook-URL:en på organisationsnivå. Oavsett vilket signeras den med
  organisationens webhook-`secret`.
</Note>

---

## Svarsschema

Returnera ett JSON-objekt som beskriver agentkonfigurationen för det här samtalet.
`prompt` och `voice` krävs; allt annat är valfritt.

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

| Fält | Typ | Krävs | Beskrivning |
|-------|------|----------|-------------|
| `prompt` | sträng | ja | Systemprompt som styr agenten |
| `voice` | sträng | ja | Röst-id från [`GET /v1/voices`](/api-reference/agents#voices), t.ex. `john`. `voice_name` accepteras som alias. Okända röster klarar inte valideringen och samtalet avvisas |
| `product` | sträng | nej | Standardvärdet är `spark`. Tillåtna värden: `spark`, `bolt`, `storm-base`, `storm-base-with-ack`, `storm-extra`, `storm-extra-with-ack` |
| `thinking_level` | sträng | nej | `minimal`, `base` (standard) eller `extra`. Åsidosätts för Storm-produkter: `storm-extra*` tvingar `extra`, andra `storm-*` tvingar `base` |
| `audio_context_mode` | sträng | nej | `full` (standard) eller `reduced` |
| `watchdog_enabled` | boolesk | nej | Aktivera övervakning för det här samtalet. Standardvärdet är `false` |
| `additional_audio_context` | boolesk \| null | nej | Inkludera de senaste turerna av uppringarens ljud i stället för bara den senaste turen, vilket förbättrar korrigeringar och insamling av uppgifter med mycket stavning eller siffror med en liten ökning av latens och kostnad. Är aktiverat som standard för inkommande sessioner och inaktiverat för utgående telefonsamtal; `null` behåller standardvärdet |
| `storm_feedback_mode` | sträng | nej | `none`, `acknowledgement` (standard) eller `tick`. Anger även vad uppringaren hör medan ljudmodellerna bearbetar en tur när `audio_tier` är `hearing` |
| `language` | sträng | nej | Förkortning för `primary_language` |
| `primary_language` | sträng | nej | Språkkod, normaliserad (standardvärde `en`). Koder som inte kan lösas upp avvisar samtalet |
| `has_additional_languages` | boolesk | nej | Standardvärdet är `false` |
| `additional_languages` | matris av strängar | nej | Ytterligare språk som agenten kan växla till |
| `native_voice_switching` | boolesk | nej | Standardvärdet är `false`. När samtalet växlar till ett annat språk byter du till en röst med det språket som modersmål (matchad efter kön) i stället för att behålla den konfigurerade rösten |
| `language_switching` | sträng \| null | nej | `ask_first` (standard) eller `follow_caller`; `null` är samma som `ask_first`. Anger hur en flerspråkig agent hanterar när den andra personen talar ett annat av agentens språk. `ask_first` växlar direkt när personen ber om språket eller säger en hel mening på det, och frågar om den ska fortsätta på språket efter något kort, som ett "ja". `follow_caller` växlar till vilket konfigurerat språk personen än talar, även vid ett enda ord. Gäller endast när `additional_languages` är angivet |
| `audio_tier` | sträng \| null | nej | Endast `product: "bolt"`. `standard` (standard; `""` och `null` betyder samma sak) kör tre transkriberare (samtal som behandlar PHI använder endast transkriberare som omfattas av BAA). `lean` sänker till en transkriberare, som hör fel oftare. `hearing` uppgraderar till `standard` plus en kraftfull ensemble av ljudmodeller som lyssnar på uppringarens ljud under vissa turer, vilka tar omkring 1–2 sekunder längre. Andra produkter ignorerar detta |
| `endpointing` | sträng \| null | nej | `faster` (200 ms), `fast` (300 ms), `normal` (500 ms, standard) eller `patient` (800 ms); `null` är samma som `normal`. Anger hur länge en Bolt v2-agent väntar efter att uppringaren slutat tala innan modellen ombeds om ett svar. Kortare väntetider kan svara tidigare men skickar fler begäranden som uppringarens nästa ord gör inaktuella, vilket ökar modellkostnaden. Andra produkter ignorerar detta |
| `eagerness` | sträng \| null | nej | Föråldrat: namnet på `endpointing` fram till den 19 oktober 2026, läses fortfarande. Ignoreras när `endpointing` är angivet |
| `intelligence` | sträng \| null | nej | `express`, `lite` eller `standard` (standard); `null` är samma som `standard`. Intelligensnivån för en `bolt`-agent i Bolt v2-pipelinen: vilken modell som skriver dess svar. `express` är ~600 ms till första ordet, billigare än Standard och följer instruktioner minst tillförlitligt; `lite` är ~900 ms, billigast och mindre tillförlitlig; `standard` är ~900 ms och bäst på att följa instruktioner. Express- och Lite-svar som bara skulle anropa ett verktyg skickas till Standard-modellen. Andra produkter ignorerar detta |
| `background_track` | sträng \| null | nej | Id för bakgrundsljud eller `null` |
| `acknowledgement_prompt_mode` | sträng | nej | `auto` (standard) eller `manual` (Storm-with-ack-produkter) |
| `acknowledgement_prompt` | sträng | nej | Används när `acknowledgement_prompt_mode="manual"` |
| `silence_interval_seconds` | heltal \| null | nej | 5–120. Sekunder av tystnad från uppringaren före en avstämning |
| `silence_max_checkins` | heltal \| null | nej | 1–10 |
| `silence_checkins_enabled` | boolesk | nej | Standardvärdet är `true` |
| `silence_final_action` | sträng | nej | Efter den sista avstämningen: `hang_up` (standard) eller `transfer` till `silence_transfer_destination` |
| `silence_transfer_destination` | sträng | nej | Namnet på en post i den här konfigurationens `transfer_destinations`; krävs med `transfer`. Utan `transfer_destinations` kan överföringen inte genomföras och agenten lägger på |
| `silence_final_message` | sträng | nej | ≤ 300 tecken, läses upp som skrivet; `""` (standard) använder standardraden |
| `connect_tone_enabled` | boolesk | nej | Standardvärdet är `false` |
| `pronunciation_dicts` | boolesk \| null | nej | Standardvärdet är `false`; `null` är samma som `false`. När värdet är `true` använder samtalets Cartesia-tal ThunderPhones uttalslexikon för samtalets språk, där ett finns. Fungerar för telefon- och widget-samtal. Gäller endast ThunderPhones egna Cartesia-röster, inte röster på din egen Cartesia API-nyckel. Används inte med `agent_id`, där den sparade agentens inställningar gäller |
| `voicemail_action` | sträng | nej | `prompt` (standard), `hangup` eller `message` |
| `voicemail_message` | sträng | nej | Används när `voicemail_action="message"` |
| `agent_name` | sträng | nej | Visningsnamn som rapporteras till instrumentpaneler och widgeten |
| `org_name` | sträng | nej | Organisationens visningsnamn för agentens persona |
| `tools` | matris | nej | Infogade scheman för funktionsverktyg (se [Funktionsverktyg](/sv/tools/overview)) |
| `transfer_destinations` | matris av objekt \| null | nej | Upp till 50 poster med `{name, number}` som det här samtalet kan överföras till, validerade som en agents [överföringsnummer](/api-reference/agents#transfer-numbers). Agenten överför efter namn och endast till dessa; `[]` betyder inga överföringar. Utelämna det eller skicka `null` för att låta agenten överföra till ett nummer som den väljer |
| `timezone` | sträng | nej | IANA-tidszon för det här samtalet, till exempel `America/Chicago`. Agenten anger datum och tid i den, före agentens egen tidszon. Tillåts även tillsammans med `agent_id`. Värden som inte är IANA-zoner ignoreras. Se [Ange tidszonen per samtal](/sv/guides/dynamic-call-config) |
| `call_id` | heltal | nej | Valfritt eko av begärans samtals-id; ignoreras |

<Note>
  Okända nycklar på toppnivå **ignoreras** tyst — ett felstavat fältnamn
  avvisar inte konfigurationen, det tillämpas bara inte. Talordning
  och `max_hold_seconds` accepteras inte här; de kan endast
  konfigureras på själva [agenten](/api-reference/agents).
</Note>

Eftersom `prompt` och `voice` krävs avvisas samtalet om du returnerar `{}` eller ett
svar som inte klarar valideringen: ett telefonsamtal avslutas enligt beskrivningen i
[Timeouts och återförsök](#timeouts-and-retries), och en begäran om en widgetsession misslyckas med `422`. Det finns ingen reservlösning med statisk agent
på den här vägen (ett nummer eller en nyckel i webhook-läge har ingen tilldelad
agent).

---

## Begränsning av svarsstorlek

<Warning>
  Konfigurationssvar är begränsade till **5 MiB**. Om en hanterare
  returnerar ett större svar, även med statusen `2xx`, rapporterar
  ThunderPhone att svaret överskred gränsen och
  avvisar samtals- eller widgetsessionen. Begränsa svaret till de fält
  som behövs för samtalskonfiguration; lagra stora datamängder bakom funktionsverktyg eller
  en annan tjänst i stället för att bädda in dem i konfigurationen.
</Warning>

---

## Exempel på hanterare

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

Koppla verktyg så att AI:n kan anropa dina API:er mitt i samtalet:

```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>
  Begäranden till verktygsändpunkter signeras med **samma organisations webhook-hemlighet**
  som signerade denna begäran. Se
  [Funktionsverktyg](/sv/tools/overview) för den exakta strukturen och det signerade
  begärandeformatet.
</Tip>

---

## Snabbguide till produktnivåer

| Produkt | Latens | Resonemang | Bekräftelse |
|---------|---------|-----------|-----------------|
| `spark` | Lägst | Grundläggande | — |
| `bolt` | Låg | Förbättrat | — |
| `storm-base` | Medel | Starkt | — |
| `storm-base-with-ack` | Medel | Starkt | Automatisk utfyllnad medan den tänker |
| `storm-extra` | Högre | Djupgående | — |
| `storm-extra-with-ack` | Högre | Djupgående | Automatisk utfyllnad medan den tänker |

---

## Relaterat

<CardGroup cols={2}>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/sv/webhooks/call-complete">
    Den icke-blockerande händelsen när samtalet avslutas.
  </Card>
  <Card title="Funktionsverktyg" icon="screwdriver-wrench" href="/sv/tools/overview">
    Fullständigt JSON-schema för `tools[]` och det signerade endpoint-kontraktet.
  </Card>
  <Card title="Webhook-endpoints" icon="bolt" href="/sv/webhooks/endpoints">
    Prenumerera med flera URL:er på `telephony.incoming` / `web.incoming`.
  </Card>
  <Card title="Dynamisk samtalskonfiguration" icon="wand-magic-sparkles" href="/sv/guides/dynamic-call-config">
    Mönster för prompts, verktyg och A/B-tester per uppringare.
  </Card>
</CardGroup>
