
# Webhook-rajapinta

Webhookien avulla alusta voi ilmoittaa muille järjestelmillesi heti, kun jotain tapahtuu – esimerkiksi uusi yhteystieto, vastaus, varattu tapaaminen tai muuta. Tämä rajapinta hallinnoi itse **tilauksia**: mitkä URL-osoitteet vastaanottavat mitkäkin tapahtumat. Lisätietoja päätepisteen vastaanottamien hyötykuormien vastaanottamisesta ja todentamisesta on kohdassa [Webhookit](../integrations/webhooks.md).

Kaikki alla olevat polut ovat suhteessa rajapinnan perus-URL-osoitteeseen:

```
https://api.youraiconnector.com/v1
```

Jokainen pyyntö on todennettava. Katso kohdasta [Todennus](authentication.md) neljä hyväksyttyä menetelmää. Tässä olevissa esimerkeissä käytetään `X-API-Key`-otsikkoa (ja yhtä kyselyparametrimuotoa cURL-kutsulle).

::: note
**Huomautus:** Webhookien on oltava käytössä tililläsi. Jos niitä ei ole otettu käyttöön, nämä päätepisteet palauttavat virheen `403`.
:::


---

## Tilausten osoittaminen

Jokaisella tilauksella on `id` ja valinnainen `name`. Kumpaa tahansa voidaan käyttää `{webhookId}`-tunnisteena polussa päivitystä, poistoa, testausta, tilaa ja uudelleenaktivointia varten.

> **Suosi nimeä.** Tilaustunnisteet ovat sijaintikohtaisia, joten ne voivat muuttua, kun toinen tilaus poistetaan. Jos määrität pysyvän `name`-nimen tilausta luodessasi, käytä sitä viittaamiseen yllätysten välttämiseksi.

---

## Listaa tilaukset

`GET /webhooks`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Vastaus**

```json
{
  "success": true,
  "webhooks": [
    {
      "id": "0",
      "name": "Order updates hook",
      "url": "https://hooks.example.com/incoming",
      "subscribed_to": ["Contact Created", "Replies"],
      "subscribed_to_tags": [],
      "created_at": "2026-06-09T12:00:00.000Z",
      "signing_enabled": true,
      "signing_secret_created_at": "2026-07-15T09:30:00.000Z",
      "retries_enabled": true,
      "enabled": true,
      "apply_to_sub_accounts": false
    }
  ]
}
```

`signing_enabled` ja `retries_enabled` ovat tilauskohtaisia valintoja, jotka ovat oletuksena pois päältä, ellet kytke niitä päälle. Katso [Allekirjoitetut hyötykuormat](#signed-payloads) ja [Uudelleenyritykset](#retries).

`apply_to_sub_accounts` on toimiston perintäasetus (opt-in) — katso [Yksi tilaus kaikille asiakastileille](#one-subscription-for-all-client-accounts-agencies). Oletusarvoisesti pois päältä, eikä sillä ole vaikutusta tileillä, joilla ei ole asiakastilejä.

`enabled` on tilauksen päälle/pois-kytkin — katso [Tilauksen kytkeminen pois päältä](#switching-a-subscription-off). Pois kytketyt tilaukset näkyvät edelleen tässä luettelossa.

Itse allekirjoitussalaisuutta ei koskaan sisällytetä tähän — lue se kohdasta [`GET /webhooks/{id}/signing-secret`](#read-the-signing-secret).

---

## Listaa tilattavissa olevat tapahtumatyypit

Palauttaa tarkat merkkijonot, joita voit käyttää `subscribed_to`-kohdassa. Käytä tätä kelvollisten tapahtumanimien löytämiseen sen sijaan, että koodaisit ne kiinteästi.

`GET /webhooks/events`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks/events" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/events", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks/events",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Vastaus**

Vastaus on `{"success": true, "events": [...]}`, jossa `events` sisältää tällä hetkellä 22 tarkkaa merkkijonoa: Contact Created, Human Alerted, Appointment Booked, Replies, Reads, Deliveries, Credits Spent, Credits Recharged, Low Credit Balance, Contact Paused, Contact Do Not Disturb, Contact Unarchived, New Message, Contact Resumed, Chat Concluded, Task Created, Task Updated, Task Completed, Daily Summary Created, Channel Connected, Broadcast Started ja Broadcast Completed (Channel Connected hyväksytään kohdassa `subscribed_to`, mutta mikään ei lähetä sitä tällä hetkellä, joten älä rakenna sen varaan).

Tietoa kunkin tapahtuman merkityksestä ja sen hyötykuormassa lähettämästä `event`-koodista löydät kohdasta [22 Webhook-tapahtumaa](../integrations/webhooks.md#the-22-webhook-events). Tämä päätepiste on virallinen ja ajantasainen lähde – lue se dynaamisesti sen sijaan, että koodaisit nimet kiinteästi.

---

## Luo tilaus

`POST /webhooks`

| Kenttä | Pakollinen | Kuvaus |
|---|---|---|
| `url` | Kyllä | HTTPS-URL-osoite, joka vastaanottaa tapahtumien hyötykuormat `POST`-protokollan kautta. On oltava julkisesti tavoitettavissa. |
| `subscribed_to` | Kyllä | Ei-tyhjä taulukko tapahtumien nimistä (katso `/webhooks/events`). |
| `name` | Ei | Näyttönimi. Voidaan käyttää myöhemmin myös tunnisteena `{webhookId}`. Oletuksena aikaleimattu nimi. |
| `subscribed_to_tags` | Ei | Tunniste-ID:t, jotka rajaavat, mitkä tunnisteet tuottavat keskusteluyhteenvedon ilmoituksen. Tämä ei rajoita tilauksen tapahtumia kyseisiin tunnisteisiin – jos haluat pyynnön tietyn tunnisteen lisäämisestä, määritä webhook-URL kyseiselle tunnisteelle agentin (tai kampanjan) **Tunnisteet**-välilehdellä. |
| `retries_enabled` | Ei | Totuusarvo, oletusarvo `false`. Ota käyttöön epäonnistuneiden toimitusten [uudelleenyritykset](#retries). |
| `generate_signing_secret` | Ei | Totuusarvo, oletusarvo `false`. Luo HMAC-[allekirjoitussalaisuus](#signed-payloads) tilauksen yhteydessä. Salaisuus palautetaan kerran vastauksen ylimmän tason `signing_secret`-kentässä. |
| `enabled` | Ei | Totuusarvo, oletusarvo `true`. Välitä `false` luodaksesi tilauksen pois päältä kytkettynä. Katso [Tilauksen kytkeminen pois päältä](#switching-a-subscription-off). |
| `apply_to_sub_accounts` | Ei | Totuusarvo, oletusarvo `false`. Toimistotilillä `true` saa tämän tilauksen vastaanottamaan tapahtumia myös jokaiselta asiakastililtä – katso [Yksi tilaus kaikille asiakastileille](#one-subscription-for-all-client-accounts-agencies). |

> **URL-säännöt:** URL-osoitteen on käytettävä `https://` ja sen on oltava julkisesti tavoitettavissa. Tavalliset `http://`, `localhost`, yksityisverkon osoitteet ja alustan sisäiset osoitteet hylätään `400`-virheellä.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "name": "Order updates hook"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://hooks.example.com/incoming",
    subscribed_to: ["Contact Created", "Replies"],
    name: "Order updates hook",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://hooks.example.com/incoming",
        "subscribed_to": ["Contact Created", "Replies"],
        "name": "Order updates hook",
    },
)
data = res.json()
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "1",
  "webhook": {
    "id": "1",
    "name": "Order updates hook",
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

---

## Tilausasetusten päivittäminen

Anna vähintään yksi seuraavista: `url`, `subscribed_to`, `name`, `subscribed_to_tags`, `retries_enabled`, `enabled` tai `apply_to_sub_accounts`. Pois jätetyt kentät säilyttävät nykyiset arvonsa. `subscribed_to` ja `subscribed_to_tags` ovat korvaavia, eivät yhdistettäviä arvoja.

`PUT /webhooks/{webhookId}`

> Tilauksen päivittäminen ei koskaan vaikuta sen allekirjoitussalaisuuteen — hallitse sitä [allekirjoitussalaisuuden reittien](#signed-payloads) kautta.

> Kun URL-osoite muuttuu, uuden URL-osoitteen toimitus otetaan automaattisesti uudelleen käyttöön, mikä antaa aiemmin epäonnistuneelle päätepisteelle uuden alun.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/Order%20updates%20hook" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/v2/incoming",
    "subscribed_to": ["Replies", "Chat Concluded"]
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  `https://api.youraiconnector.com/v1/webhooks/${encodeURIComponent("Order updates hook")}`,
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      url: "https://hooks.example.com/v2/incoming",
      subscribed_to: ["Replies", "Chat Concluded"],
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/webhooks/Order updates hook",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://hooks.example.com/v2/incoming",
        "subscribed_to": ["Replies", "Chat Concluded"],
    },
)
data = res.json()
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "0",
  "webhook": {
    "id": "0",
    "name": "Order updates hook",
    "url": "https://hooks.example.com/v2/incoming",
    "subscribed_to": ["Replies", "Chat Concluded"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Tuntematon tunnus tai nimi palauttaa `404` ja `{ "success": false, "error": "Webhook not found" }`.

---

## Tilauksen poistaminen

Poistaa tilauksen, jolloin sen URL-osoite lakkaa vastaanottamasta hyötykuormia. Sen toimituksen tilan laskurit nollataan, joten saman URL-osoitteen lisääminen myöhemmin alkaa puhtaalta pöydältä.

`DELETE /webhooks/{webhookId}`

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/webhooks/0",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Vastaus**

```json
{
  "success": true
}
```

---

## Testihyötykuorman lähettäminen

Lähettää näytehyötykuorman tilauksen URL-osoitteeseen, jotta voit varmistaa vastaanottimesi toimivuuden päästä päähän. Voit valita `event`-parametrin, jolla määrität, mitä tapahtumatyyppiä näyte simuloi. Testitoimitukset eivät koskaan vaikuta tilauksen tilan laskureihin.

`POST /webhooks/{webhookId}/test`

Vastaus palauttaa aina `200` ja raportoi tuloksen `delivered`-lipulla – epäonnistunut testi **ei** palauta virhetilaa. Kun `delivered` on `false`, vastaus sisältää epäonnistumisen tiedot.

| Kenttä | Pakollinen | Kuvaus |
|---|---|---|
| `event` | Ei | Simuloitava tapahtumatyyppi (on oltava jokin seuraavista: `/webhooks/events`). Oletuksena toimitustapahtuma. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/test?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "event": "Contact Created" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/test", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ event: "Contact Created" }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks/0/test",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"event": "Contact Created"},
)
data = res.json()
```

**Vastaus** (toimitettu)

```json
{
  "success": true,
  "webhook_id": "0",
  "delivered": true
}
```

**Vastaus** (epäonnistui)

```json
{
  "success": true,
  "webhook_id": "0",
  "delivered": false,
  "failure_type": "permanent",
  "status_code": 404,
  "error_message": "Request failed with status code 404"
}
```

`failure_type` on jokin seuraavista: `permanent`, `temporary`, `timeout`, `network` tai `unknown`.

---

## Tarkista toimituksen tila

Palauttaa tilauksen URL-osoitteen toimituksen tilaa koskevat tiedot: kuinka monta toimitusta on onnistunut ja epäonnistunut, onko toimitus tällä hetkellä keskeytetty toistuvien virheiden vuoksi, sekä tiedot viimeisimmästä virheestä. Palauttaa `"health": null`, kun toimituksia ei ole vielä yritetty.

`GET /webhooks/{webhookId}/health`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks/0/health" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/health", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks/0/health",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "0",
  "url": "https://hooks.example.com/incoming",
  "health": {
    "consecutive_failures": 0,
    "total_failures": 2,
    "total_successes": 120,
    "is_disabled": false,
    "disabled_at": null,
    "disabled_reason": null,
    "last_failure": null,
    "last_success_at": "2026-06-09T12:00:00.000Z",
    "created_at": "2026-05-01T08:00:00.000Z",
    "updated_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Kun `is_disabled` on `true`, toimitus URL-osoitteeseen on keskeytetty automaattisesti toistuvien virheiden vuoksi. Korjaa vastaanottimesi ja ota se sitten uudelleen käyttöön (alla).

---

## Ota toimitus uudelleen käyttöön

Jatkaa toimitusta webhookille, jonka URL-osoite keskeytettiin automaattisesti toistuvien virheiden vuoksi. Tämä nollaa keskeytyslipun ja virhelaskurit, mutta **ei** yritä toimitusta – käytä sen jälkeen testipäätepistettä varmistaaksesi, että vastaanottimesi toimii jälleen oikein.

`POST /webhooks/{webhookId}/reenable`

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/reenable?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/reenable", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks/0/reenable",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "0"
}
```

---

## Tilauksen kytkeminen pois päältä

`enabled` on tilauksen oma päälle/pois-kytkin. Sen kytkeminen pois päältä pysäyttää toimitukset, mutta säilyttää URL-osoitteen, tapahtumaluettelon ja allekirjoitussalaisuuden ennallaan.

```bash
# Off
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

# Back on
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'
```

- **Puuttuva arvo tarkoittaa päällä.** Ennen tämän kentän käyttöönottoa luodulla tilauksella ei ole tallennettua `enabled`-arvoa, ja se toimittaa viestit normaalisti. `GET /webhooks` raportoi aina konkreettisen totuusarvon.
- Pois kytketyt tilaukset **näkyvät edelleen** `GET /webhooks`-luettelossa — näin löydät ne kytkeäksesi ne takaisin päälle.
- Ennen poiskytkentää jonoon asetettu [uudelleenyritys](#retries) ei jatku: uudelleenyritys lukee tilauksen uudelleen lähetyshetkellä ja hylkää sen, jos se on kytketty pois päältä.
- Mitään poiskytkennän aikana estettyä ei toisteta, kun kytket tilauksen takaisin päälle.

> Tämä on eri asia kuin toistuvien epäonnistumisten jälkeinen automaattinen poistaminen käytöstä, josta raportoidaan [`GET /webhooks/{id}/health`](#check-delivery-health)-kohdassa arvolla `is_disabled` ja joka tyhjennetään [`POST /webhooks/{id}/reenable`](#re-enable-delivery)-kohdalla. `enabled` on tilin kytkin; `is_disabled` on meidän kytkimemme. Kumpikaan ei ohita toista — tilauksen on oltava sekä kytkettynä päälle että ei-automaattisesti-poistettu, jotta toimitus voi tapahtua.

---

## Yksi tilaus kaikille asiakastileille (toimistot)

Aseta toimistotilillä `apply_to_sub_accounts: true` tilaukselle (luontihetkellä tai `PUT`-toiminnon kautta), niin se vastaanottaa myös tapahtumia, jotka tapahtuvat jokaisella toimiston asiakastilillä – yksi päätepiste kattaa koko toimiston, eikä tilausta tarvitse luoda uudelleen jokaiselle asiakastilille.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"apply_to_sub_accounts": true}'
```

Miten se toimii:

- **`user`-lohko erottelee tilit toisistaan.** Jokaisen hyötykuorman `user`-lohko yksilöi tilin, jolla tapahtuma todellisuudessa tapahtui, joten vastaanottimesi voi reitittää tiedot asiakaskohtaisesti.
- **Toimistotilauksen omat asetukset pätevät kaikkialla.** Sen tapahtumaluetteloa, [allekirjoitussalaisuutta](#signed-payloads) ja [uudelleenyrityksen](#retries) valintaa käytetään myös perityissä toimituksissa.
- **Asiakastilin oma tilaus samaan URL-osoitteeseen on ensisijainen.** Jos asiakastilillä on oma tilaus, joka osoittaa samaan URL-osoitteeseen, sitä käytetään kyseisen tilin tapahtumiin – samaa tapahtumaa ei koskaan toimiteta kahdesti yhteen päätepisteeseen.
- **Asiakastilit eivät näe sitä.** Perityt tilaukset eivät näy asiakastilin omassa webhook-luettelossa, eikä asiakas voi kytkeä niitä pois päältä – vain toimisto hallinnoi niitä.
- **Toimitusten tilaa seurataan asiakastilikohtaisesti.** Päätepiste, joka epäonnistuu toistuvasti, poistetaan automaattisesti käytöstä vain siltä tililtä, jonka toimitukset epäonnistuivat, ei koko toimistolta.
- **`subscribed_to_tags` ei periydy.** Tunnisteluettelo viittaa toimiston omiin tunnisteisiin, joita ei ole olemassa asiakastileillä – keskusteluyhteenvedon rajaus koskee vain toimiston omia tapahtumia.
- **Ei vaikutusta muualla.** Tilillä, jolla ei ole asiakastilejä, lippu tallentuu normaalisti, mutta ei tee mitään.

---

## Otsikot jokaisessa toimituksessa

Nämä kolme otsikkoa lähetetään jokaisessa toimituksessa, riippumatta siitä, onko tilaus allekirjoitettu vai ei:

| Otsikko | Merkitys |
|---|---|
| `X-Webhook-Delivery` | Loogisen tapahtuman pysyvä tunniste. Identtinen uudelleenyritysten välillä – käytä tätä duplikaattien poistoon. |
| `X-Webhook-Attempt` | 1-pohjainen yritysnumero. |
| `X-Webhook-Event` | Tapahtuman nimi. |

---

## Allekirjoitetut hyötykuormat

Allekirjoitus on valinnainen, oletuksena pois päältä, ja se määritetään tilauskohtaisesti. Kun tilauksella on allekirjoitussalaisuus, jokainen toimitus sisältää kaksi lisäotsikkoa niiden kolmen lisäksi, jotka lähetetään jokaisessa toimituksessa (`X-Webhook-Delivery`, `X-Webhook-Attempt` ja `X-Webhook-Event`):

| Otsikko | Merkitys |
|---|---|
| `X-Webhook-Signature` | `v1=<hex>` – HMAC-SHA256 merkkijonosta `"<timestamp>.<raw request body>"`, avaimena webhook-kohtainen allekirjoitussalaisuus, jonka luot ja kierrätät kohdassa `GET/POST/DELETE /v1/webhooks/{webhookId}/signing-secret`. |
| `X-Webhook-Timestamp` | Lähetysaika, Unix-sekunteina. Sidottu allekirjoitukseen, joten sitä ei voi muuttaa itsenäisesti. |

Vahvista laskemalla HMAC-SHA256 uudelleen raa'asta rungosta salaisuudellasi ja vertaamalla sitä otsikkoon. Vahvista **raakaa** pyynnön runkoa vasten. Jäsennellyn JSON-tiedoston uudelleenserialisointi muuttaa tavuja ja rikkoo vertailun. Hylkää toimitukset, joiden aikaleima on tuoreusikkunan ulkopuolella (300 sekuntia on järkevä oletus) toistohyökkäysten estämiseksi, ja vertaa ajoitusturvallisella funktiolla.

Katso [Allekirjoitetut hyötykuormat](../integrations/webhooks.md#signed-payloads-verifying-a-webhook-really-came-from-us) nähdäksesi täydelliset Node- ja Python-esimerkit tarkistuksesta.

> **Allekirjoitus ei ole sama asia kuin API-todennus.** Itse REST API todentautuu API-avaimilla OAuthin sijaan (OAuth 2.1 on olemassa MCP-palvelimille, jotka rekisteröit bottityökaluiksi), eikä virallisia npm- tai PyPI SDK-paketteja ole vielä olemassa – kutsu päätepisteitä millä tahansa HTTP-asiakasohjelmalla.

### Lue allekirjoitussalaisuus

`GET /webhooks/{id}/signing-secret`

```bash
curl "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": true,
  "signing_secret": "whsec_1a2b3c...",
  "signing_secret_created_at": "2026-07-15T09:30:00.000Z"
}
```

Kun allekirjoitus on pois päältä, `signing_enabled` on `false` ja `signing_secret` on `null`.

### Luo tai kierrätä allekirjoitussalaisuus

`POST /webhooks/{id}/signing-secret`

Luo salaisuuden (ottaa allekirjoituksen käyttöön) tai korvaa olemassa olevan. Palauttaa uuden salaisuuden.

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": true,
  "signing_secret": "whsec_9f8e7d...",
  "signing_secret_created_at": "2026-07-15T10:00:00.000Z"
}
```

Kierto astuu voimaan välittömästi — seuraava toimitus allekirjoitetaan vain uudella salaisuudella. Hyväksy molemmat salaisuudet lyhyen aikaa, kunnes otat muutoksen käyttöön tuotantopäätepisteessä.

Voit myös luoda salaisuuden luontihetkellä välittämällä `"generate_signing_secret": true` kohteeseen `POST /webhooks`; vastaus sisältää tällöin ylimmän tason `signing_secret`-kentän.

### Poista allekirjoitus käytöstä

`DELETE /webhooks/{id}/signing-secret`

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Vastaus**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": false
}
```

> Kaikki kolme allekirjoitussalaisuuden reittiä vaativat integraatioiden **muokkausoikeuden** (edit), mukaan lukien `GET` — salaisuus on tunnistetieto, jolla voi väärentää toimituksia, joten sitä ei näytetä vain luku -rooleille.

---

## Uudelleenyritykset

Valinnainen, oletuksena pois päältä, ja asetetaan tilauskohtaisesti `retries_enabled`-totuusarvolla kohteessa `POST /webhooks` tai `PUT /webhooks/{id}`.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"retries_enabled": true}'
```

Kun toiminto on käytössä, epäonnistunut toimitus yritetään uudelleen **1 min, 5 min, 30 min ja 2 tunnin** kuluttua ensimmäisestä yrityksestä (yhteensä noin 2 tuntia 40 minuuttia).

- **Uudelleenyritykset:** 5xx-vastaukset, aikakatkaisut ja yhteysvirheet.
- **Ei uudelleenyrityksiä:** kaikki 4xx-vastaukset. Vastaanottaja hylkää itse pyynnön, joten sen toistaminen muuttumattomana vain toistaa hylkäyksen.

Uudelleenyritykset mahdollistavat duplikaattitoimitukset — päätepiste, joka käsitteli tapahtuman mutta aikakatkaistiin ennen vastaamista, näkee sen uudelleen. Käytä duplikaattien poistamiseen tunnisteita `X-Webhook-Delivery`, joka pysyy samana kaikissa yrityksissä. Tästä syystä uudelleenyritykset ovat valinnaisia.

[Toimituksen tilan](#check-delivery-health) laskurit laskevat koko toimituksen, eivät jokaista yritystä: virhe kirjataan vasta, kun kaikki uudelleenyritykset on käytetty, joten uudelleenyritysten käyttöönotto ei nopeuta automaattista poistamista käytöstä.

---

## Virheet

Kaikki virheet käyttävät vakioitua kirjekuorta:

```json
{
  "success": false,
  "error": "Webhook not found"
}
```

Yleisiä tapauksia: sallimaton URL-osoite, tyhjä/virheellinen `subscribed_to` tai puuttuvat kentät palauttavat `400`; tuntematon tunnus tai nimi palauttaa `404`; ja `403` tarkoittaa, että webhookeja ei ole otettu käyttöön tililläsi. Katso täydellinen luettelo kohdasta [Virheet](errors-and-pagination.md).

---

## Seuraavat vaiheet

- [Webhooks (hyötykuormien vastaanottaminen)](../integrations/webhooks.md) — määritä vastaanottimesi ja ymmärrä hyötykuorman rakenne.
- [Todennus](authentication.md) — neljä tapaa todentaa pyyntö.
- [Virheet ja nopeusrajoitukset](errors-and-pagination.md) — tilakoodit ja 300 pyyntöä/minuutti -rajoitus.
