ThunderPhone 2.0 on nyt julkaistu.Ota käyttöön itse – alkaen 2 ¢/min.Lue lisää julkistuksesta

Webhooks

telephony.incoming / web.incoming

Estävä webhook, joka määrittää saapuvan puhelun asetukset reaaliajassa.

Kun saapuva puhelu saapuu numeroon ilman määritettyä agenttia tai verkkowidgetin istunto käynnistyy julkisella avaimella tilassa mode="webhook", ThunderPhone lähettää estävän telephony.incoming / web.incoming -pyynnön vanhaan webhook-URL-osoitteeseesi ja odottaa määritysvastausta: puhelulle enintään 13 sekuntia, sisältäen yhden uudelleenyrityksen, ja widgetin istunnolle enintään 10 sekuntia (katso Aikakatkaisut ja uudelleenyritykset). Käytä tätä vaihtoa kehotteen, äänen ja työkalujen dynaamiseen valintaan puhelukohtaisesti — katso kokonaisvaltainen toimintamalli dynaamisen puhelumäärityksen oppaasta.

Aikakatkaisut ja uudelleenyritykset

Vastaa nopeasti: soittaja odottaa linjalla, kun teet päätöstä.

Puhelussa (telephony.incoming):

  • Ensimmäinen yritys voi kestää enintään 10 sekuntia.
  • Jos se aikakatkaistaan, yhteyttä ei voida muodostaa tai se saa vastauksen 5xx, 408 tai 429, ThunderPhone yrittää vielä kerran. Uudelleenyritys saa käyttöönsä sen osuuden koko vaihdolle varatusta 13 sekunnin ajasta, joka on jäljellä: noin 3 sekuntia aikakatkaistun ensimmäisen yrityksen jälkeen ja lähes kaikki 13 sekuntia nopean epäonnistumisen jälkeen. Uudelleenyritystä ei tehdä, jos aikaa olisi jäljellä alle 2 sekuntia.
  • Mikä tahansa muu 4xx-vastaus, kokorajan ylittävä vastaus tai 2xx-vastaus, jonka runko ei ole kelvollinen määritys, on lopullinen eikä sitä yritetä uudelleen.
  • Molemmat yritykset lähettävät saman rungon, saman X-ThunderPhone-Signature-otsakkeen ja saman X-ThunderPhone-Idempotency-Key-otsakkeen (telephony-incoming-<call_id>), joten sivuvaikutuksia aiheuttava käsittelijä voi tunnistaa uudelleenyrityksen.

Varapuheagenttia ei ole. Jos käyttökelpoista määritystä ei saada, puhelu lopetetaan heti sen sijaan, että soittaja jätettäisiin hiljaiselle linjalle. Se näkyy puheluhistoriassa epäonnistuneena, laskuttamattomana puheluna, jonka end_reason on inbound_config_webhook_failed, ja tavallinen telephony.complete-tapahtuma lähetetään.

Widget-istunto (web.incoming) saa yhden, enintään 10 sekuntia kestävän yrityksen. Jos se epäonnistuu, istuntopyyntö epäonnistuu koodilla 502 tai 422.

Pyynnön sisältö

Puheluille (telephony.incoming):

{
  "type": "telephony.incoming",
  "data": {
    "call_id":     987654321,
    "from_number": "+14155550199",
    "to_number":   "+15551234567"
  }
}
KenttäTyyppiKuvaus
call_idintegerPuhelutunnus — pysyy samana tämän puhelun kaikissa tapahtumissa
from_numberstringSoittajan E.164-numero
to_numberstringKohteen E.164-numero (yksi ThunderPhone-numeroistasi)

Web-widget-istunnoissa (web.incoming) data tunnistaa puhelinnumeroiden sijaan upottavan sivun:

{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
KenttäTyyppiKuvaus
call_idkokonaislukuPuhelun tunnus
origin_domainmerkkijonoSivun alkuperä, jolla widgetiä isännöidään, selaimen lähettämänä. Muu kuin selainasiakas voi lähettää minkä tahansa arvon, joten älä pidä sitä todisteena siitä, mistä pyyntö tuli
publishable_key_prefixmerkkijonoIstunnon avanneen julkaistavan avaimen ensimmäiset merkit
language, primary_languagemerkkijonoMukana, kun widget-istunto pyysi kieliohittamista
voicemerkkijonoMukana, kun widget-istunto pyysi äänen ohittamista
website_contextmerkkijonoMukana, kun widget välitti istuntokohtaisen sivukontekstin

Ohituskentät (language, voice, website_context ja mahdolliset selaimen variables) saapuvat vain, kun julkaistava avain sallii ne browser overrides -asetuksissaan. Istuntopyyntö, joka sisältää avaimen kieltämän ohituksen, hylätään ennen kuin tätä webhookia kutsutaan.


Vastausskeema

Palauta JSON-objekti, joka kuvaa tämän puhelun agentin määrityksen. prompt ja voice ovat pakollisia; kaikki muu on valinnaista.

{
  "prompt":  "You are a helpful booking assistant for Acme Restaurant.",
  "voice":   "john",
  "product": "spark",
  "background_track": null,
  "tools":   []
}
KenttäTyyppiPakollinenKuvaus
promptstringkylläAgenttia ohjaava järjestelmäkehote
voicestringkylläÄänitunnus kohteesta GET /v1/voices, esim. john. voice_name hyväksytään aliaksena. Tuntemattomat äänet eivät läpäise validointia ja puhelu hylätään
productstringeiOletusarvo on spark. Sallitut arvot: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack
thinking_levelstringeiminimal, base (oletus) tai extra. Ohitetaan Storm-tuotteissa: storm-extra* pakottaa arvon extra, muut storm-*-tuotteet pakottavat arvon base
audio_context_modestringeifull (oletus) tai reduced
watchdog_enabledbooleaneiOta valvonta käyttöön tässä puhelussa. Oletusarvo on false
additional_audio_contextboolean | nulleiSisällytä soittajan äänen viimeiset muutamat vuorot pelkän viimeisimmän vuoron sijaan. Tämä parantaa korjauksia sekä oikeinkirjoitus- ja numeropainotteista tiedonkeruuta pienellä viive- ja kustannuslisällä. Oletusarvoisesti käytössä saapuvissa istunnoissa ja pois käytöstä lähtevissä puheluissa; null säilyttää oletusarvon
storm_feedback_modestringeinone, acknowledgement (oletus) tai tick. Määrittää myös, mitä soittaja kuulee, kun äänimallit käsittelevät vuoroa ja audio_tier on hearing
languagestringeiLyhenne kentälle primary_language
primary_languagestringeiKielikoodi normalisoituna (oletus en). Koodit, joita ei voida tulkita, hylkäävät puhelun
has_additional_languagesbooleaneiOletusarvo on false
additional_languagesarray of stringeiLisäkielet, joihin agentti voi vaihtaa
native_voice_switchingbooleaneiOletusarvo on false. Kun puhelu vaihtuu toiseen kieleen, vaihda kyseiselle kielelle natiiviin ääneen (sukupuolen mukaan vastaavaan) määritetyn äänen säilyttämisen sijaan
language_switchingstring | nulleiask_first (oletus) tai follow_caller; null vastaa arvoa ask_first. Määrittää, miten monikielinen agentti käsittelee toisen henkilön puhumista jollakin toisella sen kielistä. ask_first vaihtaa heti, kun henkilö pyytää kieltä tai sanoo sillä kokonaisen lauseen, ja kysyy jatketaanko sillä, jos henkilö sanoo jotain lyhyttä, kuten "sí". follow_caller vaihtaa mihin tahansa määritettyyn kieleen, jota henkilö puhuu, vaikka kyse olisi vain yhdestä sanasta. Koskee vain tilanteita, joissa additional_languages on asetettu
audio_tierstring | nulleiVain product: "bolt". standard (oletus; "" ja null tarkoittavat samaa) käyttää kolmea litteroijaa (PHI:tä käsittelevät puhelut käyttävät vain BAA-sopimuksen kattamia litteroijia). lean vähentää käytön yhteen litteroijaan, joka kuulee väärin useammin. hearing päivittää asetuksen tasolle standard ja lisää tehokkaan äänimallikokonaisuuden, joka kuuntelee soittajan ääntä joillakin vuoroilla. Nämä vuorot kestävät noin 1–2 sekuntia pidempään. Muut tuotteet ohittavat tämän
endpointingstring | nulleifaster (200 ms), fast (300 ms), normal (500 ms, oletus) tai patient (800 ms); null vastaa arvoa normal. Määrittää, kuinka kauan Bolt v2 -agentti odottaa soittajan lopetettua puhumisen ennen kuin se pyytää mallilta vastausta. Lyhyemmät odotusajat voivat vastata nopeammin, mutta lähettävät enemmän pyyntöjä, jotka soittajan seuraavat sanat vanhentavat, mikä kasvattaa mallin kustannuksia. Muut tuotteet ohittavat tämän
eagernessstring | nulleiVanhentunut: endpointing-kentän nimi 19. lokakuuta 2026 asti, mutta luetaan edelleen. Ohitetaan, kun endpointing on asetettu
intelligencestring | nulleiexpress, lite tai standard (oletus); null vastaa arvoa standard. bolt-agentin älykkyystaso Bolt v2 -putkessa: mikä malli kirjoittaa sen vastaukset. express on noin 600 ms ensimmäiseen sanaan, edullisempi kuin Standard ja noudattaa ohjeita vähiten luotettavasti; lite on noin 900 ms, halvin ja vähemmän luotettava; standard on noin 900 ms ja noudattaa ohjeita parhaiten. Express- ja Lite-vastaukset, jotka kutsuisivat vain työkalua, ohjataan Standard-mallille. Muut tuotteet ohittavat tämän
background_trackstring | nulleiTaustaäänen tunnus tai null
acknowledgement_prompt_modestringeiauto (oletus) tai manual (Storm-with-ack-tuotteet)
acknowledgement_promptstringeiKäytetään, kun acknowledgement_prompt_mode="manual"
silence_interval_secondsinteger | nullei5–120. Soittajan hiljaisuuden sekunnit ennen yhteydenottoa
silence_max_checkinsinteger | nullei1–10
silence_checkins_enabledbooleaneiOletusarvo on true
silence_final_actionstringeiViimeisen yhteydenoton jälkeen: hang_up (oletus) tai transfer kohteeseen silence_transfer_destination
silence_transfer_destinationstringeiTämän määrityksen transfer_destinations-luettelon merkinnän nimi; pakollinen arvon transfer kanssa. Ilman transfer_destinations-asetusta siirtoa ei voi tehdä, ja agentti katkaisee puhelun
silence_final_messagestringei≤ 300 merkkiä, luetaan kirjoitetussa muodossa; "" (oletus) käyttää oletusriviä
connect_tone_enabledbooleaneiOletusarvo on false
pronunciation_dictsboolean | nulleiOletusarvo on false; null vastaa arvoa false. Kun arvo on true, puhelun Cartesia-puhe käyttää ThunderPhonen ääntämissanakirjaa puhelun kielelle, jos sellainen on saatavilla. Toimii puhelin- ja widget-puheluissa. Koskee vain ThunderPhonen omia Cartesia-ääniä, ei omalla Cartesia API -avaimellasi olevia ääniä. Ei käytetä asetuksen agent_id kanssa, jolloin tallennetun agentin asetuksia käytetään
voicemail_actionstringeiprompt (oletus), hangup tai message
voicemail_messagestringeiKäytetään, kun voicemail_action="message"
agent_namestringeiNäyttönimi, joka ilmoitetaan koontinäytöille ja widgetille
org_namestringeiOrganisaation näyttönimi agentin personaa varten
toolsarrayeiUpotetut funktiotyökalujen skeemat (katso Funktiotyökalut)
transfer_destinationsarray of object | nulleiEnintään 50 {name, number}-merkintää, joihin tämä puhelu voidaan siirtää. Ne validoidaan kuten agentin siirtonumerot. Agentti siirtää nimen perusteella ja vain näihin kohteisiin; [] tarkoittaa, ettei siirtoja ole. Jätä pois tai lähetä null, jotta agentti voi siirtää valitsemaansa numeroon
timezonestringeiTämän puhelun IANA-aikavyöhyke, kuten America/Chicago. Agentti ilmoittaa päivämäärän ja kellonajan tällä aikavyöhykkeellä oman aikavyöhykkeensä sijaan. Sallitaan myös agent_id-kentän yhteydessä. Arvot, jotka eivät ole IANA-aikavyöhykkeitä, ohitetaan. Katso Aseta aikavyöhyke puhelukohtaisesti
call_idintegereiPyynnön puhelutunnuksen valinnainen kaiku; ohitetaan

Koska prompt ja voice ovat pakollisia, arvon {} tai minkä tahansa validoinnissa epäonnistuvan vastauksen palauttaminen hylkää puhelun: puhelu päätetään kohdassa Aikakatkaisut ja uudelleenyritykset kuvatulla tavalla, ja pienoisohjelmaistunnon pyyntö epäonnistuu koodilla 422. Tällä polulla ei ole staattisen agentin varavaihtoehtoa (webhook-tilassa olevalla numerolla tai avaimella ei ole määritettyä agenttia).


Vastauksen kokorajoitus


Esimerkkikäsittelijä

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 {}
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({});
  },
);

Vastaus toimintotyökaluilla

Liitä työkaluja, jotta tekoäly voi kutsua rajapintojasi keskustelun aikana:

{
  "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"
        }
      }
    }
  ]
}

Tuotetason pikaopas

TuoteViivePäättelyKuittaus
sparkPieninPerustaso—
boltMatalaParannettu—
storm-baseKeskitasoVahva—
storm-base-with-ackKeskitasoVahvaAutomaattinen täytesana ajattelun aikana
storm-extraKorkeampiSyvällinen—
storm-extra-with-ackKorkeampiSyvällinenAutomaattinen täytesana ajattelun aikana

Aiheeseen liittyvät