
# Webhookit

Webhookien avulla <span data-t="appName">Your AI Connector</span> voi ilmoittaa automaattisesti muille liiketoimintatyökaluillesi aina, kun jotain tärkeää tapahtuu – uusi yhteystieto luodaan, tapaaminen varataan tai viesti vastaanotetaan. Sen sijaan, että tarkistaisit päivitykset manuaalisesti, yhdistetyt järjestelmäsi saavat välittömän ilmoituksen heti, kun jotain tapahtuu.


---

## Mitä webhookit ovat?

Ajattele webhookia kuin automaattista tekstiviestiä kahden sovelluksen välillä. Kun <span data-t="appName">Your AI Connector</span>-palvelussa tapahtuu jotain (kuten uuden yhteystiedon rekisteröityminen), alusta lähettää välittömästi ilmoituksen valitsemaasi toiseen järjestelmään. Annat verkko-osoitteen (niin kutsuttu "webhook URL"), johon nämä ilmoitukset lähetetään – tämän osoitteen tarjoaa yleensä CRM-järjestelmäsi, automaatioalustasi tai kehittäjäsi.

> **Webhookit lähettävät tietoa vain <span data-t="appName">Your AI Connector</span>-palvelusta POIS.** Webhook on yksisuuntainen katu <span data-t="appName">Your AI Connector</span>-palvelusta muihin työkaluihisi. **Ei ole olemassa webhook-URL-osoitetta, joka lähettäisi liidejä, yhteystietoja tai viestejä alustalle.** Jos haluat tuoda uuden liidin sisään – verkkosivuston lomakkeelta, CRM-järjestelmästäsi tai GoHighLevelistä – järjestelmäsi tekee sen sijaan **API-kutsun**. Katso [API-käyttöoikeus](api-access.md) (toiminto *Luo yhteystieto*) ja [Suppilot](funnels.md). Ainoa asia, jota tarvitset sisääntulevaa liikennettä varten, on **API-avaimesi**, joka löytyy omasta osiostaan – katso [API-käyttöoikeus](api-access.md#generating-your-api-key). Tässä kuvattu **Webhookit**-sivu on tarkoitettu yksinomaan ulospäin suuntautuvalle liikenteelle.

::: note
**Huomautus:** Webhookien määrittäminen vaatii jonkin verran teknistä konfigurointia. Jos tämä ei tunnu luontevalta, jaa tämä sivu kehittäjäsi kanssa tai käytä automaatioalustaa, kuten Zapieria, Makea tai Pabblya, jotka tarjoavat webhook URL-osoitteet ilman koodausta.
:::


Yleisiä käyttötapoja ovat:

- Uusien yhteystietojen synkronointi CRM-järjestelmään.
- Työnkulun käynnistäminen Zapierissa, Makessa tai Pabblyssa, kun tunniste lisätään.
- Tiimin ilmoittaminen Slackissa, kun ihmisen apua tarvitaan.
- Kalenterijärjestelmän päivittäminen, kun aika varataan.
- Keskusteluyhteenvetojen tallentaminen tietokantaasi.

---

## Webhookien määrittäminen

1. Napsauta vasemmasta sivupalkista **Asetukset** (rataskuvake).
2. Napsauta Asetukset-sivupalkin **Integraatiot**-ryhmän alta **Webhookit**.


Tilillä, jolle ei ole vielä määritetty webhookeja, sivu näyttää tältä:


3. Napsauta **New webhook** oikeasta yläkulmasta. Lomake avautuu sivulle:


4. Täytä:
   - **Päätepisteen URL (Endpoint URL)** — verkko-osoite, johon <span data-t="appName">Your AI Connector</span> lähettää tapahtumailmoitukset. Saat tämän ulkoisesta järjestelmästäsi (CRM, automaatioalusta tai oma palvelin).
   - **Nimi** — tunniste, jonka tunnistat myöhemmin (esim. "Slack-hälytykset" tai "CRM-synkronointi"). Vain omaa viitettäsi varten.

> **Webhook URL-osoitteesi on oltava julkisesti tavoitettavissa oleva `https://`-osoite.** Tavalliset `http://`-osoitteet, `localhost`- tai yksityisverkon osoitteet sekä alustan sisäiset osoitteet hylätään tallennettaessa. Jos haluat testata omalta koneeltasi, käytä julkista tunnelia (webhook.site tai ngrok) localhostin sijaan.

5. Valitse **Tapahtumat**-kohdassa ne tapahtumat, jotka haluat tämän webhookin vastaanottavan – kaikki 22 on lueteltu kohdassa [22 webhook-tapahtumaa](#the-22-webhook-events).
6. *(Valinnainen)* Ota käyttöön **Yritä epäonnistuneita toimituksia uudelleen**, jos haluat <span data-t="appName">Your AI Connector</span>-palvelun yrittävän uudelleen väliaikaisen virheen sattuessa – katso [Epäonnistuneiden toimitusten uudelleenyrittäminen](#retrying-failed-deliveries).
7. Napsauta **Luo webhook**. Se ilmestyy lomakkeen alapuolella olevaan luetteloon, ja voit napsauttaa sen rivillä olevaa **Testaa**-painiketta milloin tahansa lähettääksesi näytehyötykuorman päätepisteeseesi.

> **Käyttöoikeus vaaditaan.** Webhookien lisääminen, muokkaaminen tai testaaminen vaatii Integraatioiden "muokkaus"-oikeuden (vain katseluoikeudella varustetut tiimin jäsenet näkevät lomakkeen sijasta vain luku -ilmoituksen).

> **Webhookin allekirjoittaminen** vaatii, että se on jo tallennettu – avaa olemassa olevan webhookin rivi muokataksesi sitä, jolloin **Allekirjoituksen salaisuus** -paneeli ilmestyy muokkauslomakkeen alaosaan. Upouudella, tallentamattomalla luonnoksella ei ole vielä allekirjoitusvaihtoehtoa – katso [Allekirjoitetut hyötykuormat](#signed-payloads-verifying-a-webhook-really-came-from-us) alta.

---

## Yksi webhook kaikille asiakastileillesi (toimistot)

Jos hallinnoit toimistoa, sinun ei tarvitse luoda samaa webhookia uudelleen jokaiselle asiakastilille. Toimistotilin webhook-lomakkeessa on ylimääräinen kytkin: **Käynnistä myös kaikille asiakastileille**. Kun otat sen käyttöön, tämä webhook vastaanottaa myös tapahtumia, jotka tapahtuvat kaikilla toimistosi alaisilla asiakastileillä – yksi päätepiste, koko toimisto.

Miten se toimii:

- **`user`-lohko kertoo, mille asiakkaalle tapahtuma kuuluu.** Jokainen ilmoitus sisältää jo `user`-lohkon, joka yksilöi tilin, jolla tapahtuma sattui, joten automaatiosi voi reitittää tiedot asiakaskohtaisesti.
- **Webhookisi omat asetukset pätevät kaikkialla.** Valitsemiasi tapahtumia, allekirjoitussalaisuutta ja uudelleenyritysasetusta käytetään myös asiakastilien toimituksissa.
- **Ei kaksoistoimituksia.** Jos asiakastilillä on oma webhook, joka osoittaa samaan URL-osoitteeseen, sitä käytetään kyseisen tilin tapahtumiin – sama tapahtuma ei koskaan saavu kahdesti samaan päätepisteeseen.
- **Asiakkaat eivät näe sitä.** Webhook ei näy asiakastilin omalla Webhooks-sivulla, eivätkä asiakkaat voi kytkeä sitä pois päältä – se on sinun hallittavissasi.
- **Luotettavuutta seurataan asiakastilikohtaisesti.** Jos päätepisteesi epäonnistuu toistuvasti, se kytketään automaattisesti pois päältä vain siltä tililtä, jonka toimitukset epäonnistuivat (katso [Webhookin luotettavuus](#webhook-reliability)), ei koko toimistolta kerralla.

Kytkin näkyy vain toimistotileillä. Sen asettaminen API:n kautta on myös tuettu – katso `apply_to_sub_accounts`-kenttä kohdasta [Webhooks API](../api/webhooks.md#one-subscription-for-all-client-accounts-agencies).

---

## Käytettävissä olevat käynnistystapahtumat

Voit ottaa kunkin 22 webhook-tapahtumasta käyttöön tai poistaa ne käytöstä itsenäisesti. Kun tapahtuma laukeaa, <span data-t="appName">Your AI Connector</span> lähettää ilmoituksen webhook-URL-osoitteeseesi asiaankuuluvien tietojen kera. Jokainen tapahtuma, sen merkitys ja `event`-koodi, jonka se lisää hyötykuormaan, on lueteltu yhdessä kohdassa [22 webhook-tapahtumaa](#the-22-webhook-events) alempana tällä sivulla.

> **Hyvä tietää:** **Tehtävä luotu**, **Tehtävä päivitetty** ja **Tehtävä suoritettu** ovat täysin valittavissa ja tallentuvat oikein. **Päivittäinen yhteenveto luotu** on myös hiljattain lisätty. Katso kyseisen hyötykuorman muoto kohdasta [Tehtävä suoritettu -webhook](#task-completed-webhook).

---

## Tunnisteisiin perustuvat webhook-käynnistimet

`subscribed_to_tags` ei rajaa webhookin tapahtumia tunnisteeseen. Se vain kaventaa sitä, mitkä tunnisteet tuottavat keskusteluyhteenvedon ilmoituksen. Jos haluat pyynnön tietyn tunnisteen lisäämisestä, määritä webhook-URL kyseiselle tunnisteelle agentin (tai kampanjan) **Tunnisteet**-välilehdellä.

Itse webhook-lomakkeessa ei ole tunnisteiden valintatyökalua, ei uutta webhookia luotaessa eikä olemassa olevaa muokattaessa, joten `subscribed_to_tags` voidaan lukea tai muuttaa vain [Webhooks API](../api/webhooks.md):n kautta tai pyytämällä tukea.

> **Hyvä tietää:** olemassa olevan webhookin muokkaaminen, jolla on `subscribed_to_tags`-luettelo (uudelleennimeäminen, tapahtumien muuttaminen, uudelleenyritysten vaihtaminen), ei enää tyhjennä kyseistä luetteloa — koska lomakkeessa ei ole tunnisteiden valintatyökalua, jota lähettää takaisin, tältä sivulta tallentaminen jättää nykyisen luettelon ennalleen. (Tämä oli todellinen virhe ennen **21. heinäkuuta 2026**: webhook-lomakkeesta tallentaminen pyyhki aiemmin luettelon, koska se lähetti aina tyhjän tunnisteiden luettelon. Jos webhook menetti `subscribed_to_tags`-luettelonsa ennen kyseistä päivämäärää, se on määritettävä uudelleen API:n kautta.)

### Luo yhteenveto tunnisteella merkityille yhteyshenkilöille

Jos webhookilla on `subscribed_to_tags`-luettelo, voit ottaa käyttöön **Luo yhteenveto**. Kun tämä on käytössä, <span data-t="appName">Your AI Connector</span> luo automaattisesti keskusteluyhteenvedon yhteyshenkilölle, kun jokin näistä tunnisteista lisätään, ja sisällyttää sen webhook-tietoihin — täysi konteksti ilman erillistä pyyntöä.

---

## Webhookin testaaminen

1. Avaa **Asetukset → Integraatiot → Webhookit**.
2. Napsauta webhookisi rivillä **Testaa**.
3. Tarkista ulkoisesta järjestelmästäsi, että se vastaanotti testitiedot.
4. Tarkista tietomuoto varmistaaksesi, että järjestelmäsi osaa jäsentää sen oikein.

Tee täydellinen päästä-päähän-testi lähettämällä viesti, joka käynnistäisi jonkin määritetyistä tapahtumistasi (lähetys tai saapuva viesti yhdistetyssä kanavassa), ja varmista, että webhook laukeaa todellisilla tiedoilla.

::: tip
**Vinkki:** Käytä kehityksen aikana [webhook.site](https://webhook.site)- tai [RequestBin](https://requestbin.com)-työkalua raa'an webhook-datan tarkasteluun ennen tuotantojärjestelmän yhdistämistä.
:::


### Mikä lasketaan onnistuneeksi toimitukseksi

Riippumatta siitä, napsautatko **Test**-painiketta vai tapahtuuko tapahtuma oikeasti, lähetämme saman asian:

- **POST**-pyyntö (ei koskaan GET), jonka runko on JSON-muodossa ja `Content-Type: application/json`.
- Otsikot, jotka on lueteltu kohdassa [Allekirjoitetut hyötykuormat](#signed-payloads-verifying-a-webhook-really-came-from-us). Allekirjoitusotsikot sisällytetään vain, kun olet määrittänyt allekirjoitussalaisuuden.

Pidämme toimitusta onnistuneena, kun:

- Päätepisteesi vastaa **millä tahansa 2xx-tilakoodilla** (200, 201, 204 — kaikki käyvät).
- Se vastaa **30 sekunnin kuluessa**.

Muutama asia, joka yllättää ihmiset:

- **Vastausrunkoa ei huomioida.** Sinun ei tarvitse palauttaa mitään tiettyä JSON-muotoa. Tyhjä 200-vastaus riittää.
- **Uudelleenohjaukset lasketaan epäonnistumiseksi.** Emme seuraa niitä, joten 301- tai 302-vastaus (mukaan lukien uudelleenohjaus vinoviivan puuttumisen vuoksi tai http-ohjaus https-osoitteeseen) kirjataan epäonnistuneeksi toimitukseksi. Tallenna lopullinen URL-osoite, älä sitä, joka ohjaa uudelleen.
- **Kyselymerkkijonoja tuetaan täysin.** `https://your-app.com/hook?token=abc123` lähetetään täsmälleen sellaisena kuin tallensit sen, joten tunnisteen lisääminen kyselymerkkijonoon toimii yhtä hyvin kuin sen lisääminen polkuun.
- **URL-osoitteesi on oltava `https://` ja julkisesti tavoitettavissa.** Osoitteet, jotka kuuluvat <span data-t="appName">Your AI Connector</span>:n omaan infrastruktuuriin, hylätään, mutta omat päätepisteesi Google Cloud Functionsissa, Cloud Runissa, App Enginessä, Firebase Hostingissa tai missä tahansa muualla toimivat hyvin.
- **Päätepisteesi edessä oleva palomuuri tai bottisuojauskerros voi estää meitä.** Yleisin tapaus on Cloudflare: jos vyöhykkeelläsi on päällä Bot Fight Mode tai hallittu haaste, pyyntömme saa "Just a moment..." -haastesivun ja 403-virheen sen sijaan, että se tavoittaisi palvelimesi – ja palvelimien välinen pyyntö ei voi koskaan läpäistä selainhaastetta, joten sekä **Test**-painike että todelliset tapahtumat epäonnistuvat samalla tavalla. Test-painike kertoo sinulle, kun näin tapahtuu ("Cloudflare is showing a bot challenge to our request"). Korjaa asia Cloudflaressa Security / WAF-säännöllä, joka ohittaa haasteet webhook-polullesi (tai `Webhook-Delivery/1.0`-käyttäjäagentille), ja napsauta sitten **Test** uudelleen.
- **Jos palomuurisi vaatii sen sijaan IP-sallittujen luettelon** (esimerkiksi Cloudflaren ilmaisessa paketissa, jossa tavallista Bot Fight Modea ei voi ohittaa WAF-säännöllä, mutta sallittuun IP-pääsysääntöön asetettu sääntö toimii sitä ennen), voimme auttaa: jokainen toimitus, olipa se peräisin **Test**-painikkeesta tai live-tapahtumasta, lähetetään yhdestä kiinteästä IPv4-osoitteesta (ei vaihteluvälejä, ei IPv6:ta, ei vaihtuvuutta). Ota yhteyttä tukeen, niin annamme sinulle osoitteen sallittujen luetteloon lisäämistä varten. Pidä [allekirjoituksen varmentaminen](#signed-payloads-verifying-a-webhook-really-came-from-us) varsinaisena luottamustarkistuksenasi, sillä se vahvistaa jokaisen hyötykuorman riippumatta siitä, mistä se on peräisin.
- **Testin tulos kertoo tarkalleen, mitä päätepisteesi vastasi.** Epäonnistunut testi näyttää nyt todellisen syyn (päätepisteesi palauttaman HTTP-tilan, aikakatkaisun tai sen, ettemme tavoittaneet osoitetta lainkaan) yleisen virheen sijaan, ja tallennetulle webhookille tehty testi lähetetään allekirjoitettuna, kun allekirjoitus on käytössä, aivan kuten live-tapahtumassa.

### n8n:n, Make:n tai Zapierin käyttäminen ("Test URL" vs "Production URL")

Automaatioalustat tarjoavat yleensä kaksi eri webhook-osoitetta, mikä aiheuttaa usein sekaannusta:

- **Testi-URL** (n8n:ssä se sisältää `/webhook-test/`). Tämä vastaanottaa tietoja vain silloin, kun tarkkailet työtilaa aktiivisesti ja olet juuri napsauttanut **Kuuntele testitapahtumaa** (tai **Testaa työnkulkua**). Se tallentaa yhden tapahtuman ja lopettaa sitten kuuntelun – joten **Testaa**-painikkeen napsauttaminen <span data-t="appName">Your AI Connector</span>-kohdassa useita kertoja peräkkäin tallentaa vain ensimmäisen, ja vain jos kuunteluikkuna on aktiivinen juuri sillä hetkellä. Testaa näin: napsauta ensin **Kuuntele testitapahtumaa** n8n:ssä, palaa sitten <span data-t="appName">Your AI Connector</span>-kohtaan ja napsauta **Testaa** kerran.
- **Tuotanto-URL** (n8n:ssä se sisältää `/webhook/`, ei `-test`). Tämä on osoite, joka liitetään <span data-t="appName">Your AI Connector</span>-kohtaan live-tapahtumia varten. Se toimii vasta, kun työnkulkusi on asetettu tilaan **Aktiivinen**. Jos työnkulku ei ole aktiivinen, n8n hylkää pyynnön virheellä "404 / webhook not registered", vaikka <span data-t="appName">Your AI Connector</span> lähetti tiedot oikein.

Lyhyesti: testaa Test-URL:lla kuuntelun aikana, mutta jotta webhook toimisi jatkossakin oikeiden yhteystietojen kanssa, tallenna **Tuotanto-URL** kohtaan <span data-t="appName">Your AI Connector</span> ja varmista, että työnkulku on **Active**.

---

## Webhook-tietomuoto

Kun webhook laukeaa, <span data-t="appName">Your AI Connector</span> lähettää jäsenneltyä tietoa (JSON) webhook URL-osoitteeseesi. Jos käytät automaatioalustaa, kuten Zapieria tai Makea, se jäsentää nämä tiedot puolestasi automaattisesti. Jos rakennat mukautettua integraatiota:

```json
{
  "event": "contactCreated",
  "contact": { "id": "<contact-id>", "first_name": "Jane", "...": "..." },
  "campaign": { "id": "<campaign-id>", "name": "AI Receptionist", "status": "Live" },
  "agent": { "id": "<agent-id>", "name": "Front Desk" },
  "user": { "id": "<account-id>", "email": "owner@example.com" }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | Tarkka tapahtumamerkkijono, joka laukaisi ilmoituksen (esimerkiksi `contactCreated`, `booked`). Tämä **ei** ole tapahtumaluettelossa näkyvä näyttönimi; jokainen nimi ja sitä vastaava koodi löytyvät kohdasta [22 webhook-tapahtumaa](#the-22-webhook-events). |
| `contact` | Yhteyshenkilö, jota tapahtuma koskee, tai `null` tapahtumille, joita ei ole sidottu yhteyshenkilöön (kuten `creditsRecharged`). |
| `campaign` | Kampanja, johon yhteyshenkilö kuuluu, tai `null`, jos sellaista ei ole. |
| `agent` | Keskustelua hoitava agentti tai `null`, jos sellaista ei ole. |
| `user` | Tiedot omistavan tilin perustunnistetiedot. |

> **`campaign` tai `agent` — yleensä toinen, ei molemmat.** Jos tilisi käyttää agentteja, yhteyshenkilösi ovat agentin eivätkä kampanjan hallinnassa, joten `campaign` saapuu muodossa `null` ja `agent` kertoo, kuka niitä käsitteli. Vanhemmat kampanjapohjaiset tilit näkevät tämän päinvastoin. Lue se kenttä, joka on täytetty; älä oleta, että `campaign` on aina olemassa.

> **`agent`-lohko saapui 15. elokuuta 2026.** Se sijaitsee `campaign`-kohdan rinnalla keskusteluun liittyvissä tapahtumissa – päättynyt keskustelu, älä häiritse -tila, jatkaminen, arkiston purku, tekoälyn tauottaminen, uusi viesti, keskustelun yhteenveto ja tunnisteeseen asetettava webhook – ja se sisältää käsittelevän agentin `id`- ja `name`-tiedot tai `null`-arvon, kun agenttia ei ole mukana. Se on täysin lisäluonteinen: jokainen jo vastaanottamasi kenttä pysyy muuttumattomana, joten ennen kyseistä päivämäärää rakentamasi vastaanotin toimii edelleen ilman päivitystarvetta.

Jotkut tapahtumat lisäävät oman ylimmän tason lohkonsa. Esimerkiksi **Appointment Booked** (Aika varattu) lisää `appointment`-lohkon (katso [Appointment Booked Webhook](#appointment-booked-webhook)), **New Message** (Uusi viesti) lisää täyden `message`-lohkon teksteineen (katso [New Message Webhook](#new-message-webhook)), ja **Deliveries** (Toimitukset) sekä **Reads** (Luetut) lisäävät lyhyen `message`-lohkon, joka sisältää vain viestin tunnisteen ja tilan (katso [Deliveries and Reads Webhook](#deliveries-and-reads-webhook)).

> **Deliveries- ja Reads-tapahtumat kertovat, mikä viesti on kyseessä, mutta eivät sen sisältöä.** Ne sisältävät `message`-lohkon, jossa on viestin `id` ja `status` — ja tämä `id` on sama `messageId`, jonka [lähetä viesti -päätepiste](../api/messages.md#send-a-message) palauttaa, joten voit yhdistää toimitus- tai lukukuittauksen juuri lähettämääsi viestiin — mutta viestin runko puuttuu. **Replies** (Vastaukset) ei sisällä lainkaan `message`-lohkoa. Jos tarvitset lähetettyjä tai vastaanotettuja sanoja, tilaa niiden lisäksi **New Message**.

> **Kaksi asiaa, jotka on hyvä tietää ennen vastaanottimen kirjoittamista.** Siinä ei ole `timestamp`-kenttää eikä `data`-käärettä. Jokainen lohko sijaitsee JSON-objektin ylimmällä tasolla, kuten yllä on esitetty.

### 22 webhook-tapahtumaa

22 webhook-tapahtumaa, näyttönimi, jonka valitset sovelluksessa, ja hyötykuormassa lähetettävä `event`-koodi. `event`-koodi on lyhyt merkkijono, joka **ei** vastaa näyttönimeä, joten määritä vastaanottimesi koodin, ei nimen perusteella:

| Näytettävä nimi (sovelluksessa) | `event`-koodi hyötykuormassa | Mitä se tarkoittaa |
|---|---|---|
| Contact Created | `contactCreated` | Uusi yhteystieto lisätään tilillesi (manuaalisesti, tuonnin kautta tai API:n kautta). |
| Contact Paused | `contact_paused` | Yhteystiedon keskustelu on keskeytetty (botti lakkaa vastaamasta). |
| Contact Resumed | `contact_resumed` | Keskeytetty keskustelu jatkuu. |
| Contact Do Not Disturb | `contact_do_not_disturb_changed` | Yhteystiedon Älä häiritse -asetus on kytketty päälle. |
| Contact Unarchived | `contact_unarchived` | Arkistoitu yhteystieto lähettää uuden viestin, mikä palauttaa hänet aktiiviseen postilaatikkoosi. |
| New Message | `new_message` | Mikä tahansa viesti lisätään keskusteluun millä tahansa kanavalla — sekä yhteystiedon sinulle lähettämät viestit että tekoälyn tai tiimisi heille lähettämät viestit. Tämä on ainoa tapahtuma, joka sisältää varsinaisen viestitekstin (katso [New Message Webhook](#new-message-webhook)). |
| Replies | `replied` | Yhteystieto vastaa viestiin. |
| Reads | `read` | Yhteystieto lukee viestin (kanavilla, jotka tukevat lukukuittauksia). Sisältää luetun viestin tunnisteen — katso [Deliveries and Reads Webhook](#deliveries-and-reads-webhook). |
| Deliveries | `delivered` tai `undelivered` | Viesti on toimitettu onnistuneesti yhteystiedolle (`undelivered`, jos toimitus epäonnistuu). Sisältää viestin tunnisteen — katso [Deliveries and Reads Webhook](#deliveries-and-reads-webhook). |
| Human Alerted | `humanAlerted` | Tekoälybotti toteaa, ettei se pysty käsittelemään keskustelua, ja merkitsee sen ihmisen huomiota vaativaksi. |
| Chat Concluded | `chat_concluded` | Tekoälybotti päättää, että keskustelu on päättynyt (varaus tehty, liidi hylätty jne.). |
| Appointment Booked | `booked` | Yhteystieto varaa ajan varausjärjestelmän kautta. |
| Credits Spent | `creditsSpent` | Krediittejä vähennetään tililtäsi. |
| Credits Recharged | `creditsRecharged` | Krediittejä lisätään tilillesi automaattisen latauksen tai manuaalisen oston kautta. |
| Low Credit Balance | `lowCreditBalance` **Test**-toimituksessa, `Low Credit Balance` oikeassa toimituksessa | Ennakkovaroitus siitä, että krediittisaldesi on laskenut hälytysrajan alapuolelle (100 krediittiä, ellet ole asettanut omaa rajaa). Suunnattu toimistoille, joiden alitilit käyttävät samaa krediittipoolia. Se sisältää `balance`, `threshold` ja `account_email` yhteystietolohkon sijaan, lähetetään enintään kerran 24 tunnissa saldon ollessa alhainen, ja aktivoituu uudelleen heti, kun saldo nousee takaisin rajan yläpuolelle. |
| Task Created | `taskCreated` | Tehtävä on luotu. |
| Task Updated | `taskUpdated` | Tehtävä muuttuu siirtymättä valmiusvaiheeseen. |
| Task Completed | `taskCompleted` | Tehtävä siirtyy vaiheeseen, joka on määritetty valmiusvaiheeksi. |
| Daily Summary Created | `dailySummaryCreated` | Päivittäinen yhteenvetoraporttisi on luotu. |
| Channel Connected | `channelConnected` | **Ei vielä lähetetä — valittavissa, mutta ei käytössä tällä hetkellä. Älä rakenna tämän varaan.** Tarkoitettu tilanteisiin, joissa viestintäkanavan yhdistäminen valmistuu. |
| Broadcast Started | `broadcastStarted` | Lähetys alkaa (tila muuttuu tilaan Sending). Laukeaa kerran per aloitus, myös silloin, kun keskeytetty lähetys jatkuu. Sisältää `broadcast`-lohkon yhteystietolohkon sijaan: id, nimi, kanava, tila, edellinen tila, kohdelista (`list_id`, `list_name`, `is_smart_list`), `scheduled_at`, `total_contacts`. |
| Broadcast Completed | `broadcastCompleted` | Lähetys valmistuu (tila muuttuu tilaan Sent tai Failed). Sama `broadcast`-lohko sekä `completed_at` ja, jos saatavilla, `completion_summary` (`total_sent`, `permanently_failed`, `unique_replied`, `failure_rate`, `had_errors`). Käytä näitä kahta yhdistääksesi Smart Broadcast -listan ulkoisiin työkaluihin. |

Kaksi muuta koodia ei koskaan näy kyseisessä luettelossa, koska et tilaa niitä: `contact_tags_updated`, jonka lähettää yksittäiselle tunnisteelle asetettu webhook-URL, ja `summary_generated`, joka lähetetään, kun keskusteluyhteenveto kirjoitetaan tunnisteelle webhookin `subscribed_to_tags`-luettelossa.

> **Kanava yhdistetty -tapahtumaa ei vielä lähetetä.** Se näkyy tapahtumaluettelossa, mutta mikään ei lähetä sitä tällä hetkellä. Älä rakenna toiminnallisuutta sen varaan.

Tunnisteisiin ja tehtäviin perustuvat ilmoitukset käyttävät omia erillisiä muotojaan. Katso [Contact Tags Updated](#contact-tags-updated-webhook) ja [Task Completed](#task-completed-webhook).

---

## Yhteystieto luotu -webhook

Lähetetään, kun **Yhteystieto luotu** -tapahtuma laukeaa (uusi yhteystieto lisätään manuaalisesti, tuonnin kautta tai API:n kautta).

### Tapahtuman nimi

`contactCreated`

### Hyötykuorman muoto

```json
{
  "event": "contactCreated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | Tässä tapahtumassa aina `contactCreated`. |
| `contact.id` | Uuden yhteyshenkilön yksilöllinen tunniste. |
| `contact.email` / `contact.phone_number` | Yhteyshenkilön sähköpostiosoite ja puhelinnumero, jos tiedossa (kumpi tahansa voi olla tyhjä kanavasta riippuen). |
| `contact.first_name` / `contact.last_name` | Yhteyshenkilön nimi, jos tiedossa. |
| `contact.human_alerted` / `contact.human_alert_reason` | Onko yhteyshenkilö merkitty vaatimaan ihmisen huomiota ja miksi. |
| `contact.is_bot_active` | Onko tekoälybotti tällä hetkellä aktiivinen tässä yhteyshenkilössä. |
| `contact.ad_referral` | Metan Click-to-WhatsApp-mainoksen attribuutio tai `null` — katso [Click-to-WhatsApp-mainoksen attribuutio](click-to-whatsapp-attribution.md). |
| `campaign` | Kampanja, jonka alla yhteyshenkilö luotiin, tai `null`. |
| `agent` | Yhteyshenkilölle määritetty agentti tai `null`. |
| `user` | Yhteyshenkilön omistavan tilin perustiedot. |

> **"Testi"-näyte ja todellinen tapahtuma näyttävät hieman erilaisilta.** Testipainike lähettää paikkamerkkitietoja (John Doe, esimerkkikampanja). Todellinen "Yhteystieto luotu" -tapahtuma sisältää yhteystiedon todelliset tiedot, ja jotkin kentät voivat olla tyhjiä kanavasta riippuen.

---

## New Message Webhook

Tämä webhook laukeaa joka kerta, kun viesti lisätään keskusteluun millä tahansa kanavalla. Se kattaa molemmat suunnat: yhteystiedon sinulle lähettämät viestit sekä tekoälyn, tiimisi tai kampanjan heille lähettämät viestit. Se on ainoa webhook, joka sisältää viestitekstin, joten käytä tätä, kun haluat peilata keskusteluja ulkoiseen järjestelmään.

### Tapahtuman nimi

`new_message`

### Hyötykuorman muoto

```json
{
  "event": "new_message",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "body": "Hi, are you open on Saturday?",
    "direction": "inbound",
    "status": "received",
    "created_at": "2026-07-30T17:27:06.000Z",
    "channel": "whatsapp_web"
  }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | Aina `new_message` tälle tapahtumalle. Huomaa, että tämä on täsmälleen lähetetty merkkijono — se ei ole näyttönimi "New Message". |
| `contact` | Yhteystieto, jonka keskusteluun viesti kuuluu. Sama muoto kuin [Contact Created](#contact-created-webhook) -tapahtumassa. |
| `agent` | Keskustelua käsittelevä agentti (`id` ja `name`), tai `null`, jos agenttia ei ole mukana. |
| `user` | Perustiedot tilistä, joka omistaa keskustelun. |
| `message.id` | Viestin yksilöllinen tunniste. |
| `message.body` | Viestin teksti. Tyhjä viestille, joka sisältää vain liitteen (kuva, ääniviesti, asiakirja). |
| `message.direction` | `inbound` yhteystiedon lähettämälle viestille, `outbound` tekoälyn tai tiimisi postilaatikosta lähettämälle viestille, ja `outbound-api` kampanjan, lähetyksen, mallipohjan tai API:n lähettämälle viestille. |
| `message.status` | Missä vaiheessa viestin elinkaari on: `received` saapuvalle, ja `queued` / `sent` / `delivered` / `read` / `failed` / `undelivered` lähtevälle. Tämä on tila viestin luontihetkellä, joten lähtevä viesti saapuu yleensä tässä muodossa `queued` tai `sent` ja saavuttaa tilan `delivered` myöhemmin — käytä **Deliveries**- ja **Reads**-tapahtumia, jos tarvitset näitä myöhempiä siirtymiä. Ne sisältävät saman `message.id`-tunnisteen kuin tämä lohko, joten voit yhdistää siirtymän tähän viestiin (katso [Deliveries and Reads Webhook](#deliveries-and-reads-webhook)). |
| `message.created_at` | Milloin viesti luotiin, UTC-ajassa (ISO 8601). |
| `message.channel` | Kanava, jota pitkin viesti kulki, esimerkiksi `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `messenger`, `telegram`, `email` tai `custom`. |

> **Tässä hyötykuormassa ei ole vieläkään `campaign`-lohkoa.** New Message lähettää `contact`-, `agent`-, `user`- ja `message`-tiedot. `agent`-lohko lisättiin **15. elokuuta 2026**, ja se kertoo, mikä agentti käsittelee keskustelua; jos tarvitset myös kampanjakontekstia, etsi yhteyshenkilö API:n kautta käyttämällä `contact.id`-tunnistetta.

> **Sisäiset tekoälytietueet eivät laukaise tätä webhookia.** Todellisten viestien ohella alusta pitää omia kirjanpitorivejään keskustelussa (tekoälyn työkalukutsut ja sisäiset vuorotietueet). Niitä ei koskaan lähetetä — vastaanotat vain viestit, jotka on todellisuudessa lähetetty tai vastaanotettu.

---

## Deliveries and Reads Webhook

Nämä kaksi tapahtumaa raportoivat, mitä viestille tapahtui sen jälkeen, kun se lähti <span data-t="appName">Your AI Connector</span>-päätepisteestä: **Deliveries** laukeaa, kun viesti saavuttaa yhteystiedon (tai epäonnistuu), ja **Reads** laukeaa, kun yhteystieto avaa sen, niillä kanavilla, jotka tukevat lukukuittauksia.

Molemmat sisältävät `message`-lohkon, jossa on tapahtumaa koskevan viestin tunniste, joten voit yhdistää päivityksen juuri lähettämääsi viestiin.

### Tapahtumien nimet

`delivered` ja `undelivered` tapahtumalle **Deliveries**, `read` tapahtumalle **Reads**.

### Hyötykuorman muoto

```json
{
  "event": "delivered",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "status": "delivered"
  }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | `delivered` tai `undelivered` tapahtumalle **Deliveries**, `read` tapahtumalle **Reads**. |
| `contact` | Yhteystieto, jolle viesti lähetettiin. |
| `campaign` | Kampanja, johon yhteystieto kuuluu, tai `null`. |
| `agent` | Keskustelua käsittelevä agentti, tai `null`. |
| `user` | Perustiedot tilistä, joka omistaa tiedot. |
| `message.id` | Tämän päivityksen kohteena olevan viestin tunniste. Se on sama arvo, jonka [lähetä viesti -päätepiste](../api/messages.md#send-a-message) palauttaa muodossa `messageId`, ja sama `message.id`, jonka [New Message](#new-message-webhook) -ilmoitus sisältää. |
| `message.status` | Uusi tila, aina sama merkkijono kuin `event` (`delivered`, `undelivered` tai `read`). |

> **Kuinka yhdistää päivitys lähettämääsi viestiin.** Tallenna `messageId`, jonka saat takaisin, kun lähetät viestin API:n kautta. Kun **Deliveries**- tai **Reads**-ilmoitus saapuu, etsi kyseinen tallennettu tunniste hyötykuorman `message.id`-kentästä — se on kyseisen viestin toimitus- tai lukukuittaus.

> **Tässä ei ole viestitekstiä.** `message`-lohko sisältää vain tunnisteen ja tilan. Tilaa [New Message](#new-message-webhook), jos tarvitset myös viestin rungon.

> **`message`-lohko on läsnä vain, kun tiedämme, mikä viesti on kyseessä.** Harvinaisissa päivityksissä, joita emme voi yhdistää tallennettuun viestiin, lohko jätetään kokonaan pois sen sijaan, että se lähetettäisiin tyhjänä — tarkista siis, että `message` on olemassa ennen kuin luet `message.id`-kentän.

> **Yksi ilmoitus per tilan muutos.** Yksittäinen lähtevä viesti tuottaa yleensä `delivered`-ilmoituksen ja sen jälkeen, lukukuittauksia tukevilla kanavilla, `read`-ilmoituksen. Epäonnistunut lähetys tuottaa sen sijaan `undelivered`-ilmoituksen.

---

## Appointment Booked Webhook

Laukeaa, kun yhteystieto varaa ajan. Se laukeaa samalla tavalla riippumatta siitä, varasiko tekoäly ajan keskustelun aikana, varasitko sen käsin vai tuliko se API:n kautta.

### Tapahtuman nimi

`booked`

### Hyötykuorman muoto

```json
{
  "event": "booked",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith"
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com"
  },
  "appointment": {
    "appointment_id": "<appointment-id>",
    "start_time": "2026-07-20T15:00:00.000Z",
    "end_time": "2026-07-20T15:30:00.000Z",
    "status": "confirmed",
    "room_name": "Room 1",
    "description": "Discovery call",
    "summary": "30 min intro",
    "google_calendar_event_id": null,
    "event": {
      "id": "<service-id>",
      "event_name": "Intro Call",
      "slot_duration": 30,
      "location": "Zoom",
      "meeting_link": "https://...",
      "event_type": "online"
    }
  }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | Aina `booked` tälle tapahtumalle. |
| `contact` | Henkilö, joka teki varauksen. `email` ja `phone_number` voivat olla tyhjiä kanavasta riippuen. |
| `appointment.appointment_id` | Varauksen yksilöllinen tunnus. |
| `appointment.start_time` / `end_time` | Varauksen alkamis- ja päättymisaika UTC-ajassa (ISO 8601). |
| `appointment.status` | Varauksen nykyinen tila. |
| `appointment.room_name` | Huone, johon varaus tehtiin, jos käytössä. |
| `appointment.description` / `summary` | Varauksen yhteydessä tallennetut vapaamuotoiset tiedot. |
| `appointment.google_calendar_event_id` | Google Kalenterin tunnus synkronoidulle tapahtumalle. Se on usein `null` Tapaaminen varattu -webhookissa, koska kalenteritapahtuma luodaan samalla hetkellä, kun ilmoitus lähetetään — hae tapaaminen uudelleen sen `appointment_id`-tunnuksella hetkeä myöhemmin, jos tarvitset sitä, ja odota pysyvää `null`-tunnusta tileillä, joihin ei ole yhdistetty Google Kalenteria. |
| `appointment.event` | Varattu palvelu: nimi, varauksen kesto, sijainti, kokouslinkki, tyyppi. |

> **`google_calendar_event_id` on tässä webhookissa usein `null`, ja se on normaalia.** Google Kalenterin tapahtuma luodaan samalla hetkellä, kun tämä ilmoitus lähtee, joten tunniste ei yleensä ole vielä valmis. Hae varaus uudelleen sen `appointment_id`-tunnisteella hetken kuluttua, jos tarvitset sitä. Se pysyy pysyvästi `null`-arvossa, jos tilille ei ole yhdistetty Google Kalenteria, joten älä odota sitä loputtomiin.

> **"Testi"-painike ei sisällä `appointment`-lohkoa.** Käytä sitä varmistaaksesi, että päätepisteesi vastaa, ja tee sitten yksi todellinen varaus nähdäksesi koko hyötykuorman.

> **Kaksi tapausta, joissa tämä webhook ei laukea:** ulkoisesta kalenterista tuodut tapaamiset ja Formitable-integraation kautta tulevat varaukset.

---

## Yhteystietotunnisteiden päivityksen webhook

Käynnistyy, kun tunniste **lisätään** yhteystietoon ja kyseiselle tunnisteelle on määritetty webhook-URL-osoite agentissa tai kampanjassa, johon yhteystieto kuuluu.

### Tapahtuman nimi

`contact_tags_updated`

### Milloin se laukeaa

- Tunniste lisätään yhteystietoon, jolle on määritetty agentti, kampanja tai molemmat.
- Ainakin yhdelle lisätyistä tunnisteista on määritetty webhook-URL-osoite kyseisen agentin tai kampanjan Tunnisteet-välilehdellä.

Jos yhteystiedolla on molemmat ja kampanjan tunnisteissa on webhook-URL-osoitteet, ne ovat ensisijaisia; muussa tapauksessa käytetään agentin tunnisteita.

Jos samassa päivityksessä lisätään useita tunnisteita, joilla on eri webhook-URL-osoitteet, jokaiselle URL-osoitteelle lähetetään yksi pyyntö, joka sisältää vain kyseiseen URL-osoitteeseen liittyvät tunnisteet.

**Tunnisteen poistaminen ei koskaan lähetä pyyntöä.** Useimmat käyttäjät ohjaavat nämä URL-osoitteet toimintoon – kuten talletuksen keräämiseen, ajan varaamiseen tai edustajan hälyttämiseen – joten tunnisteen poistaminen yhteystiedosta voisi käynnistää toiminnon uudelleen. Näin ei enää tapahdu. Poisto näkyy edelleen kohdassa `removed_tags`, kun se tapahtuu samassa päivityksessä kuin lisäys, joka menee samaan URL-osoitteeseen, joten molempia taulukoita lukeva automaatio säilyttää täyden tilannekuvan; se ei kuitenkaan koskaan näe pelkän poiston aiheuttamaa pyyntöä. (Muutettu **12. elokuuta 2026**. Sitä ennen poistot lähettivät myös pyynnön.)

### Hyötykuorman muoto

```json
{
  "event": "contact_tags_updated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "is_bot_active": true,
    "ad_referral": {
      "ctwa_clid": "ARAbc123...",
      "source_id": "120210000000000",
      "source_type": "ad",
      "source_url": "https://fb.me/xxxx",
      "headline": "Get 20% off today",
      "body": "Message us now to claim your discount",
      "channel": "whatsapp"
    }
  },
  "added_tags": ["qualified-lead"],
  "removed_tags": ["new-lead"],
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | Aina `contact_tags_updated` tälle webhookille. |
| `contact.id` | Sen yhteyshenkilön yksilöllinen tunniste, jonka tunnisteet muuttuivat. |
| `contact.email` / `contact.phone_number` | Yhteyshenkilön sähköposti/puhelinnumero, jos tiedossa. |
| `contact.first_name` / `contact.last_name` | Yhteyshenkilön nimi. |
| `contact.human_alerted` | Onko yhteyshenkilö tällä hetkellä merkitty vaatimaan ihmisen huomiota. |
| `contact.is_bot_active` | Onko tekoälybotti tällä hetkellä aktiivinen tämän yhteyshenkilön keskustelussa. |
| `contact.ad_referral` | Näkyy vain, kun yhteyshenkilö otti yhteyttä ensimmäisen kerran Metan Click-to-WhatsApp (CTWA) -mainoksen tai -julkaisun kautta. Muussa tapauksessa `null`. |
| `added_tags` | Tässä päivityksessä lisättyjen tunnisteiden nimet taulukkona. Ei koskaan tyhjä – lisäys on se, mikä laukaisee pyynnön. |
| `removed_tags` | Samassa päivityksessä poistettujen tunnisteiden nimet taulukkona, jos niitä on. Pelkkä poisto ei lähetä mitään. |
| `agent` | Yhteyshenkilön keskustelua käsittelevä agentti (`id` ja `name`) tai `null`, jos agenttia ei ole mukana. Lisätty **15. elokuuta 2026**. |
| `user` | Yhteyshenkilön omistavan tilin perustiedot. |

### Tunnisteen webhookin testaaminen

Tunnisteet-välilehden webhook-URL-kentän vieressä on **Testaa**-painike. Se lähettää näytehyötykuorman kyseiseen URL-osoitteeseen välittömästi, jotta voit varmistaa automaatiosi vastaanottavan sen ennen kuin odotat todellista keskustelua.

Testi lähettää saman `contact_tags_updated`-muodon, joka näkyy yllä, käyttäen paikkamerkkiyhteystietoa, testattavaa tunnistetta kohdassa `added_tags` ja tyhjää `removed_tags`-kenttää. Se, mitä automaatiosi näkee testissä, on sama, mitä se näkee tuotannossa.

Kaksi asiaa, jotka on hyvä tietää:

- **Tallenna tunniste ensin.** Testi etsii tunnisteen sen tallennetun nimen perusteella, joten upouutta tunnistetta tai tallentamatonta nimenmuutosta ei voi vielä testata. Painike pysyy harmaana, kunnes näytöllä oleva nimi vastaa tallennettua nimeä.
- **Epäonnistunut testi ei vaikuta webhookiisi.** Testit eivät koskaan vaikuta automaattiseen poiskytkentään toistuvien epäonnistumisten jälkeen, kuten kohdassa [Webhookin luotettavuus](#webhook-reliability) on kuvattu.

Jos testi epäonnistuu, viesti kertoo, mitä päätepisteesi vastasi (esimerkiksi `404` tai `500`), mikä yleensä riittää väärän URL-osoitteen tai pois päältä olevan työnkulun tunnistamiseen.

---

## Tehtävän suorittamisen webhook

> **Vain viitteeksi.** Tehtävä-webhookit (datana) on dokumentoitu tässä kehittäjiä varten; **Tehtävä luotu**, **Tehtävä päivitetty** ja **Tehtävä suoritettu** -tapahtumat ovat valittavissa webhook-lomakkeen tavallisessa tapahtumaluettelossa kuten mikä tahansa muu tapahtuma – katso [Käytettävissä olevat käynnistystapahtumat](#available-trigger-events) ja [22 webhook-tapahtumaa](#the-22-webhook-events).

Tämä hyötykuorma lähetetään, kun tehtävä siirtyy vaiheeseen, joka on merkitty suoritusvaiheeksi. Tehtävä, joka liikkuu muiden kuin suoritusvaiheiden välillä, lähettää sen sijaan `taskUpdated`-muodon.

### Tapahtuman nimi

`taskCompleted`

### Milloin se laukeaa

- Tehtävä päivitetään.
- Sen `stage`-arvo muuttui verrattuna edelliseen arvoonsa.
- Uusi vaihe on määritetty suoritusvaiheeksi tilin tehtävävaiheasetuksissa.

### Hyötykuorman muoto

```json
{
  "event": "taskCompleted",
  "contact": {
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<task-id>",
    "title": "Follow up with Jane",
    "description": "Confirm pricing and send proposal",
    "type": "follow_up",
    "priority": "high",
    "stage": "<stage-id>",
    "due_date": "2026-01-20T15:00:00Z",
    "source": "ai",
    "source_detail": "<source-detail>",
    "campaign_id": "<campaign-id>",
    "linked_human_alert": "<human-alert-id>",
    "tags": ["qualified-lead"],
    "notes": "Customer requested a callback"
  }
}
```

| Kenttä | Kuvaus |
|---|---|
| `event` | Aina `taskCompleted` tälle webhookille. Sama hyötykuorman muoto lähetetään muodossa `taskUpdated`, kun tehtävä muuttuu siirtymättä suoritusvaiheeseen. |
| `contact` | Tehtävään linkitetty yhteystieto, jos sellainen on. `null`, jos ei linkitetty. |
| `contact.human_alert_reason` | Syy sille, miksi yhteystieto merkittiin vaatimaan ihmisen huomiota, jos sovellettavissa. |
| `user` | Tehtävän omistavan tilin perustiedot. |
| `message.id` | Tehtävän yksilöllinen tunniste. |
| `message.title` / `description` | Tehtävän otsikko ja kuvaus. |
| `message.type` | Tehtävätyyppi (esimerkiksi `follow_up`, `call`, `custom`). |
| `message.priority` | Tehtävän prioriteetti (`low`, `medium`, `high`). |
| `message.stage` | Sen vaiheen tunniste, jossa tehtävä on nyt. |
| `message.due_date` | Tehtävän eräpäivä, jos asetettu. |
| `message.source` | Mikä loi tehtävän (`ai`, `manual`, `api`). |
| `message.source_detail` | Lisätietoja lähteestä. |
| `message.campaign_id` | Linkitetyn kampanjan tunniste tai `null`. |
| `message.linked_human_alert` | Linkitetyn ihmisen huomioilmoituksen tunniste, jos sellainen on. |
| `message.tags` | Tehtävään lisätyt tunnisteet. |
| `message.notes` | Vapaamuotoiset muistiinpanot tehtävästä. |

---

## Webhookin poistaminen käytöstä (tai poistaminen)

Jokaisella webhookilla on päälle/pois-kytkin suoraan sen rivillä. Sen kytkeminen **pois päältä** estää tapahtumien vastaanottamisen, mutta säilyttää kaiken määrittämäsi — URL-osoitteen, tapahtumat ja mahdollisen allekirjoitussalaisuuden. Kytke se takaisin päälle, niin se jatkaa siitä, mihin se jäi; mitään sen ollessa pois päältä tapahtunutta ei toimiteta jälkikäteen.

Käytä tätä, kun haluat keskeyttää toimitukset hetkeksi: päätepistettäsi rakennetaan uudelleen, vianmäärität häiriöitä aiheuttavaa integraatiota tai keskeytät automaation.

Webhookin **poistaminen** (roskakorikuvake sen rivillä) poistaa sen pysyvästi, mukaan lukien sen allekirjoitussalaisuuden. Jos haluat vain estää toimitukset, kytke se sen sijaan pois päältä — poisto on tarkoitettu tilanteisiin, joissa olet valmis päätepisteen kanssa kokonaan.

> **Tämä ei ole sama asia kuin webhookin kytkeminen automaattisesti pois päältä.** Jos poistamme webhookisi käytöstä toistuvien virheiden vuoksi (katso [Webhookin luotettavuus](#webhook-reliability)), yllä oleva valitsin ei palauta sitä. Kun päätepisteesi on korjattu, muokkaa webhookia ja tallenna se muutetulla URL-osoitteella (mikä tahansa URL-osoitteen muutos aktivoi sen uudelleen), tai kutsu [uudelleenaktivointipäätepistettä](../api/webhooks.md) API:n kautta – tai pyydä tukea, niin kytkemme sen takaisin puolestasi.

---

## Allekirjoitetut hyötykuormat (Webhookin alkuperän varmentaminen)

Kuka tahansa, joka saa selville webhook-URL-osoitteesi, voi lähettää siihen valepyyntöjä. Jos toimit webhookien perusteella automaattisesti — päivität laskutusta, luot CRM-tietueita — **allekirjoituksen** käyttöönotto antaa sinun varmistaa, että jokainen pyyntö tuli aidosti meiltä.

Allekirjoitus on **valinnainen ja oletusarvoisesti pois päältä**, ja kytket sen päälle webhook-kohtaisesti kyseisen webhookin muokkausnäkymästä (avaa tallennetun webhookin rivi).

### Allekirjoituksen käyttöönotto

1. Avaa webhook (Asetukset → Integraatiot → Webhookit → napsauta webhookisi riviä).
2. Napsauta **Allekirjoitussalaisuus**-osiossa **Luo**.
3. Kopioi salaisuus (se alkaa merkeillä `whsec_`) ja tallenna se vastaanottavaan järjestelmääsi. Käsittele sitä kuin salasanaa.

Voit palata takaisin ja paljastaa, kopioida, vaihtaa tai kytkeä salaisuuden pois päältä milloin tahansa samasta paneelista.

### Mitä lähetämme

Kun allekirjoitus on käytössä, jokainen webhook-toimitus sisältää nämä kaksi ylimääräistä HTTP-otsikkoa:

| Otsikko | Merkitys |
|---|---|
| `X-Webhook-Signature` | Allekirjoitus muodossa `v1=<hex>`. |
| `X-Webhook-Timestamp` | Lähetysajankohta Unix-aikaleimana sekunteina. |

Nämä kolme ovat mukana **jokaisessa** toimituksessa, riippumatta siitä, onko se allekirjoitettu vai ei:

| Otsikko | Merkitys |
|---|---|
| `X-Webhook-Delivery` | Tämän tapahtuman yksilöllinen tunniste. Pysyy samana uudelleenyritysten aikana, joten käytä tätä duplikaattien poistamiseen. |
| `X-Webhook-Attempt` | Mikä yrityskerta tämä on (`1` on ensimmäinen yritys). |
| `X-Webhook-Event` | Tapahtuman nimi, jotta voit reitittää viestin lukematta sen sisältöä. |

### Miten varmentaminen tapahtuu

Allekirjoitus on HMAC-SHA256-tiiviste merkkijonosta `<timestamp>.<raw request body>`, jossa käytetään allekirjoitussalaisuuttasi avaimena.

**Varmista raaka pyyntörunko — täsmälleen ne tavut, jotka vastaanotit.** Jos kehys jäsentää JSON-tiedoston ja sarjallistaa sen uudelleen ennen tarkistusta, tavut voivat muuttua eikä allekirjoitus täsmää.

Node.js-esimerkki:

```js
const crypto = require("crypto");

function verify(rawBody, headers, secret) {
  const timestamp = headers["x-webhook-timestamp"];
  const signature = headers["x-webhook-signature"]; // "v1=<hex>"

  // Reject anything older than 5 minutes so a captured request can't be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return crypto.timingSafeEqual(Buffer.from(signature.replace("v1=", "")), Buffer.from(expected));
}
```

Python-esimerkki:

```python
import hashlib, hmac, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    timestamp = headers["X-Webhook-Timestamp"]
    signature = headers["X-Webhook-Signature"].replace("v1=", "")

    # Reject anything older than 5 minutes so a captured request can't be replayed later.
    if abs(time.time() - int(timestamp)) > 300:
        return False

    expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()

    return hmac.compare_digest(signature, expected)
```

> **Vertaa allekirjoituksia ajoitusturvallisella funktiolla** (`timingSafeEqual` / `compare_digest`), älä `==`. Se ei maksa mitään ja estää hienovaraisen hyökkäysluokan.

### Salaisuuden vaihtaminen

Napsauta **Vaihda** (Rotate) korvataksesi salaisuuden. Vaihto tapahtuu välittömästi: heti seuraava lähetys allekirjoitetaan vain uudella salaisuudella. Jos päätepisteesi on käytössä, hyväksy **sekä** vanha että uusi salaisuus muutaman minuutin ajan, kunnes olet ottanut uuden käyttöön.

Allekirjoituksen poistaminen käytöstä estää vain allekirjoitusotsikoiden lähettämisen.

---

## Epäonnistuneiden lähetysten uudelleenyritykset

Oletusarvoisesti epäonnistunutta lähetystä ei yritetä uudelleen — jos järjestelmäsi on kyseisellä hetkellä alhaalla, kyseinen tapahtuma jää väliin.

Ota käyttöön **Yritä epäonnistuneet lähetykset uudelleen** webhookissa (luonti-/muokkauslomakkeessa), niin jatkamme yrittämistä:

| Yritys | Milloin |
|---|---|
| 1 | Välittömästi |
| 2 | 1 minuutti myöhemmin |
| 3 | 5 minuuttia myöhemmin |
| 4 | 30 minuuttia myöhemmin |
| 5 | 2 tuntia myöhemmin |

Tämä kestää yhteensä noin **2 tuntia ja 40 minuuttia**, joten webhook selviää huoltokatkosta tai lyhyestä käyttökatkosta päässäsi.

**Mitä yritetään uudelleen:** väliaikaiset ongelmat — palvelimesi palauttaa 5xx-virheen, aikakatkaisu tai yhteysvirhe.

**Mikä ei onnistu:** jos päätepisteesi hylkää itse pyynnön (mikä tahansa 4xx-virhe), emme yritä uudelleen – identtisen pyynnön lähettäminen uudelleen tuottaisi vain saman hylkäyksen.

**Mitkä tapahtumat yritetään uudelleen:** tunnisteiden webhookit (`contact_tags_updated`), kolme tehtävätapahtumaa ja päivittäinen yhteenveto. Muut lähetetään vain kerran, joten niiden kohdalla kytkimellä ei ole vaikutusta. Jokainen tapahtuma sisältää silti `X-Webhook-Delivery`-tunnisteen, joten yksi duplikaattien poistamissääntö kattaa ne kaikki.

> **Ota uudelleenyritykset käyttöön vain, jos päätepisteesi on idempotentti.** Uudelleenyritykset tarkoittavat, että sama tapahtuma voi saapua useammin kuin kerran. Käytä `X-Webhook-Delivery`-otsikkoa toiston tunnistamiseen: se pysyy samana jokaisessa yrityksessä yhden tapahtuman kohdalla, joten voit turvallisesti jättää huomiotta tunnisteen, jonka olet jo käsitellyt.

Uudelleenyritykset toimivat toistuvien epäonnistumisten jälkeisen automaattisen poiskytkennän kanssa (katso [Webhookin luotettavuus](#webhook-reliability)) juuri niin kuin haluat: epäonnistumislaskuri laskee **kokonaisen toimituksen** vasta sen jälkeen, kun jokainen uudelleenyritys on käytetty — ei jokaista yksittäistä yritystä.

---

## Webhookin luotettavuus

- <span data-t="appName">Your AI Connector</span> lähettää webhookit suojatun yhteyden (HTTPS) kautta. Varmista, että antamasi verkko-osoite käyttää HTTPS-protokollaa.
- Jos järjestelmäsi palauttaa virheen, toimitus katsotaan epäonnistuneeksi.
- Seuraa vastaanottavan järjestelmäsi käytettävyyttä välttääksesi tapahtumien menettämisen.
- Kriittisiä työnkulkuja varten ota käyttöön [Epäonnistuneiden toimitusten uudelleenyrittäminen](#retrying-failed-deliveries) ja harkitse myös varamekanismia.

> **Webhookit kytkeytyvät automaattisesti pois päältä toistuvien virheiden jälkeen.** Jos webhook-URL-osoitteesi epäonnistuu toistuvasti (noin 5 virhettä peräkkäin tai 3 peräkkäistä konfiguraatiovirhettä), <span data-t="appName">Your AI Connector</span> lopettaa automaattisesti tapahtumien lähettämisen kyseiseen URL-osoitteeseen. Kun päätepisteesi on taas kunnossa, voit palauttaa sen toimintaan seuraavasti: muokkaa webhookia ja tallenna se muutetulla URL-osoitteella (mikä tahansa URL-osoitteen muutos aktivoi sen uudelleen), tai käytä [uudelleenaktivointipäätepistettä](../api/webhooks.md) API:n kautta – pelkkä uudelleentallennus samalla URL-osoitteella ei riitä. Myös tuki voi aktivoida sen puolestasi.

---

## Vianmääritys

| Ongelma | Ratkaisu |
|---|---|
| Webhook ei laukea | Tarkista ensin, ettei webhookia ole kytketty **pois päältä** sen riviltä. Varmista sitten, että oikeat tapahtumat on valittu ja että URL-osoitteesi on tavoitettavissa internetistä. |
| Testitapahtuma toimii, mutta oikeat tapahtumat eivät | Varmista, että kyseinen tapahtumatyyppi on käytössä. Jos odotit pyyntöä, kun tunniste lisätään, huomaa, että `subscribed_to_tags` ei rajaa webhookin tapahtumia tunnisteeseen — se vain kaventaa, mitkä tunnisteet tuottavat keskusteluyhteenvedon ilmoituksen. Saadaksesi pyynnön, kun tietty tunniste lisätään, aseta webhook-URL kyseiselle tunnisteelle agentin (tai kampanjan) **Tunnisteet**-välilehdellä — katso [Yhteystietojen tunnisteet päivitetty -webhook](#contact-tags-updated-webhook). |
| Mitään ei saavu n8n:ään / Makeen / Zapieriin | Käytät todennäköisesti alustan **testi-URL-osoitetta**, joka kuuntelee vain yhtä tapahtumaa heti "Kuuntele testitapahtumaa" -painikkeen napsauttamisen jälkeen. Live-tapahtumia varten tallenna **tuotanto-URL** ja kytke työnkulku **Aktiiviseksi**. |
| Vastaanotat päällekkäisiä tapahtumia | Tarkista, onko useita webhookeja osoittamassa samaan URL-osoitteeseen. Jos **Yritä epäonnistuneet toimitukset uudelleen** on päällä, toisto on odotettavissa aina, kun päätepisteesi hyväksyi tapahtuman, mutta ei vastannut ajoissa — poista duplikaatit `X-Webhook-Delivery` avulla. |
| Allekirjoituksen tarkistus epäonnistuu aina | Lähes aina siksi, että runko sarjallistettiin uudelleen ennen tarkistusta. Varmista **raaka** pyynnön runko, allekirjoita `<timestamp>.<body>` ja varmista, että käytät nykyistä salaisuutta, jos olet vaihtanut sen äskettäin. |
| Uudelleenyritykset eivät tapahdu | Uudelleenyritykset eivät ole päällä, ellei niitä ole otettu käyttöön kyseisessä webhookissa. Emme yritä uudelleen 4xx-vastauksia. |
| `campaign`-lohko on aina `null` | Odotettavissa, jos tilisi käyttää agentteja: yhteystiedot ovat agentin eivätkä kampanjan hallinnassa. Lue sen sijaan `agent`-lohko — katso [Webhookin tietomuoto](#webhook-data-format). |
| Data on tyhjää tai virheellistä | Varmista, että vastaanottava järjestelmäsi hyväksyy JSON-muodon. Tarkista palvelimesi lokit jäsennysvirheiden varalta. |
| Webhook-URL palauttaa virheitä | Testaa URL-osoitettasi työkalulla, kuten Postman tai [webhook.site](https://webhook.site). |
| Webhook lakkasi laukeamasta kokonaan katkoksen jälkeen | Toistuvat epäonnistumiset poistavat webhookin käytöstä automaattisesti. Uudelleentallennus ei kytke sitä takaisin päälle — korjaa päätepisteesi ja ota sitten yhteys tukeen. |
| Tallennus tai testaus antaa käyttöoikeusvirheen | Tarvitset Integraatioiden "muokkaus"-oikeuden. Pyydä tilin omistajaa myöntämään se. |
| Webhookin `subscribed_to_tags`-luettelo palautui tyhjänä | `subscribed_to_tags` ei rajaa webhookin tapahtumia tunnisteeseen — se vain kaventaa, mitkä tunnisteet tuottavat keskusteluyhteenvedon ilmoituksen. Webhook-lomakkeelta muokkaaminen ei enää tyhjennä kyseistä luetteloa (korjattu 21. heinäkuuta 2026). Jos webhook menetti luettelonsa ennen kyseistä päivämäärää, aseta `subscribed_to_tags` uudelleen [Webhooks API](../api/webhooks.md):n kautta — katso [Tunnisteisiin perustuvat webhook-käynnistimet](#tag-based-webhook-triggers). |

---

## Seuraavat vaiheet

- [GoHighLevel-integraatio](ghl-integration.md) — käytä webhookeja <span data-t="appName">Your AI Connector</span>-palvelun integroimiseen GHL:n kanssa.
- [API-käyttöoikeus](api-access.md) — yhdistä webhookit ja API tehokkaita automaatioita varten.
- [Tunnisteiden käyttäminen yhteystietojen merkitsemiseen](../get-started/creating-tags.md) — määritä tunnisteita, jotka laukaisevat webhookisi.
