---
title: "Przegląd webhooków"
description: "Jak ThunderPhone dostarcza zdarzenia w czasie rzeczywistym, jak weryfikować podpisy oraz jak wypada porównanie starszego modelu dostarczania z modelem opartym na punktach końcowych."
---

ThunderPhone wysyła żądania HTTP `POST` do Twojego serwera, gdy coś
dzieje się podczas połączenia — rozpoczyna się połączenie przychodzące, połączenie się kończy, uruchomienie oceny zostaje ukończone, zostaje wyzwolony alert itd. Dostępne są **dwa modele dostarczania**:

<CardGroup cols={2}>
  <Card title="Endpointy webhooków (zalecane)" icon="bolt" href="/pl/webhooks/endpoints">
    Wiele adresów URL, sekrety dla poszczególnych endpointów, filtry zdarzeń dla poszczególnych endpointów
    oraz automatyczne ponawianie prób.
    Zarządzaj za pomocą `GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints`.
  </Card>
  <Card title="Starszy webhook z jednym adresem URL" icon="link" href="/api-reference/organizations#legacy-single-url-webhook">
    Jeden adres URL na organizację. Obejmuje zdarzenia cyklu życia połączenia, w tym
    **blokujące** wymiany konfiguracji. Zarządzany przez `GET/PUT /v1/webhook`.
  </Card>
</CardGroup>

Wszystkie wymienione typy zdarzeń w [katalogu zdarzeń](/pl/webhooks/events) są
dostarczane przez endpointy webhooków. Sześć zdarzeń cyklu życia połączenia
(`telephony.incoming`, `telephony.complete`, `telephony.tool`,
`web.incoming`, `web.complete`, `web.tool`) jest **również** wysyłanych do
starszego webhooka z jednym adresem URL — jeśli masz zarówno starszy adres URL, jak i
pasujący endpoint, otrzymasz zdarzenie na **obu** ścieżkach. Zachowanie blokujące
([wymiana konfiguracji `telephony.incoming` / `web.incoming`](/pl/webhooks/call-incoming) oraz
[wywoływanie narzędzi](/pl/tools/overview) w trybie webhooka)
jest dostępne wyłącznie na starszej ścieżce; każde dostarczenie do endpointu jest
powiadomieniem typu fire-and-forget.

## Format ładunku

Dostarczenia do endpointów mają postać obiektu JSON z polami `data`, `event_id` i
`type`:

```json
{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}
```

`event_id` jest unikalne dla każdego wyemitowanego zdarzenia. Jest identyczne przy ponownych próbach
**oraz** we wszystkich endpointach, które otrzymują zdarzenie — usuwaj duplikaty na jego podstawie.

Starszy webhook z jednym adresem URL wysyła te same pola `type` i `data`, ale
**bez** `event_id`:

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

W transmisji każde body jest serializowane kanonicznie — klucze są sortowane
alfabetycznie, bez białych znaków, w UTF-8. Przykłady sformatowane dla
czytelności w tej dokumentacji służą wyłącznie ułatwieniu lektury.

Zobacz [Katalog zdarzeń](/pl/webhooks/events), aby uzyskać pełną listę typów
zdarzeń i pól ładunku.

## Weryfikacja podpisu

Każde żądanie zawiera dwa podpisy, oba HMAC-SHA256 z kluczem `secret`
punktu końcowego (lub `secret` webhooka na poziomie organizacji w przypadku starszych
dostaw):

- `X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>` podpisuje
  znacznik czasu, metodę, ścieżkę i zapytanie oraz surową treść. Zweryfikuj
  ten podpis i odrzucaj żądania, których `t` różni się od czasu na Twoim zegarze o więcej niż **5 minut**,
  aby przechwycone żądanie nie mogło zostać później ponownie odtworzone. Ponowienia są
  podpisywane ponownie w momencie wysłania.
- `X-ThunderPhone-Signature` podpisuje tylko surową treść. Nadal jest wysyłany
  bez zmian, aby istniejące mechanizmy weryfikujące nadal działały.

### Kroki

1. Odczytaj nagłówek, metodę, surową ścieżkę i zapytanie oraz surowe
   ciało **przed** jakimkolwiek parsowaniem.
2. Oblicz szesnastkowy HMAC-SHA256 ciągu
   `<t>\n<METHOD>\n<path and query>\n<body>` przy użyciu swojego sekretu.
3. Odrzuć żądanie, jeśli `t` różni się o więcej niż 300 sekund lub jeśli
   wynik nie odpowiada `v1` w porównaniu ze stałym czasem wykonania.

Ciała mają kanoniczną serializację JSON (posortowane klucze, zwięzłe
separatory) i podpisujemy dokładnie te bajty, które przesyłamy.
[Przewodnik po weryfikacji](/pl/guides/verify-webhook-signatures) zawiera dokładny
podpisywany ciąg, przykład z objaśnieniem, kod bez SDK oraz starszy nagłówek.

<CodeGroup>
```python Python (Flask)
from flask import Flask, abort, request
from thunderphone import verify_signature

app = Flask(__name__)

@app.post("/thunderphone-webhook")
def handle():
    query = request.query_string.decode()
    if not verify_signature(
        request.headers.get("X-ThunderPhone-Signature-V2"),
        secret=WEBHOOK_SECRET,
        method=request.method,
        path=request.path + (f"?{query}" if query else ""),
        body=request.get_data(),  # raw bytes
    ):
        abort(401)
    event = request.get_json()
    # dispatch on event["type"] …
    return "", 204
```

```javascript Node.js (Express)
import express from "express";
import { verifySignature } from "@thunderphone/sdk";

const app = express();
app.post(
  "/thunderphone-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const ok = verifySignature({
      header: req.header("X-ThunderPhone-Signature-V2"),
      secret: process.env.WEBHOOK_SECRET,
      method: req.method,
      path: req.originalUrl,
      body: req.body,
    });
    if (!ok) return res.sendStatus(401);
    const event = JSON.parse(req.body.toString("utf8"));
    // dispatch on event.type …
    res.sendStatus(204);
  },
);
```
</CodeGroup>

## Semantyka dostarczania

Te zasady dotyczą dostarczania do **endpointów**. Starszy webhook z jednym adresem URL wykonuje pojedynczą synchroniczną próbę bez ponowień, z wyjątkiem wymiany konfiguracji połączenia telefonicznego [`telephony.incoming`](/pl/webhooks/call-incoming), która jest ponawiana jednokrotnie.

<AccordionGroup>
  <Accordion title="Ponowienia">
    Każde zdarzenie jest natychmiast podejmowane raz. Każda odpowiedź `2xx`
    potwierdza dostarczenie. Przy każdym innym wyniku (innym niż 2xx,
    błędzie połączenia, przekroczeniu limitu czasu) ponawiamy próbę **po 1 min, 5 min, 30 min, 2 godz., 6 godz.,
    12 godz. i 24 godz. od pierwszej próby** — łącznie 8 prób w ciągu
    24 godzin. Jeśli wszystkie próby zakończą się niepowodzeniem, dostarczanie zostanie zatrzymane, a endpoint
    otrzyma wartość `status="failing"` w sekcji
    [endpointy webhooków](/pl/webhooks/endpoints); wyślemy wiadomość e-mail do
    właścicieli i administratorów Twojej organizacji oraz wyświetlimy to w panelu. Zwróć `2xx`, gdy tylko
    ładunek zostanie trwale przyjęty; przetwarzaj go asynchronicznie.
    Wysyłki testowe z interfejsu API testowania endpointów otrzymują jedno ponowienie około minuty po
    pierwszej próbie i nigdy nie zmieniają statusu endpointu.
  </Accordion>

  <Accordion title="Kolejność">
    Kolejność dostarczania jest realizowana według najlepszych starań. W praktyce dostarczamy zdarzenia w
    kolejności ich emisji, ale ponowienia mogą zmienić kolejność po niepowodzeniu.
    Zawsze deduplikuj i uzgadniaj według `call_id` / identyfikatora obiektu.
  </Accordion>

  <Accordion title="Duplikaty">
    Dostarczanie odbywa się **co najmniej raz**: ponowienie po odpowiedzi, której nie
    otrzymaliśmy, może zduplikować zdarzenie. Każde ponowienie zawiera ten sam
    `event_id`, dlatego przechowuj przetworzone identyfikatory i pomijaj powtórzenia. `event_id` jest
    także współdzielony między punktami końcowymi — dwa punkty końcowe subskrybujące to
    samo zdarzenie otrzymują ten sam `event_id`.
  </Accordion>

  <Accordion title="Limity czasu">
    Dostarczanie do endpointów ma limit czasu **30 s** na próbę. W starszej
    ścieżce blokujące żądania sterujące zachowaniem aktywnego połączenia — wymiana
    konfiguracji [`telephony.incoming` / `web.incoming`](/pl/webhooks/call-incoming)
    — są ograniczone do **10 s** dla pierwszej próby połączenia
    telefonicznego i **13 s** dla całej wymiany, łącznie z jednym
    ponowieniem, oraz do **10 s** dla sesji widżetu. Powolna odpowiedź opóźnia
    odebranie połączenia, dlatego staraj się odpowiadać w ciągu kilku sekund. [Wysyłanie narzędzi](/pl/tools/overview) w trybie webhooka domyślnie umożliwia 20 s,
    a deklaracje narzędzi mogą ustawiać `timeout` na najwyższym poziomie.
  </Accordion>

  <Accordion title="Źródłowe adresy IP">
    Wychodzące webhooki pochodzą z zakresu adresów IP chmury ThunderPhone.
    Jeśli zapora wymaga listy dozwolonych adresów, skontaktuj się z pomocą techniczną, a
    udostępnimy aktualne zakresy.
  </Accordion>
</AccordionGroup>

## Wybór między starszymi webhookami a webhookami opartymi na punktach końcowych

| Funkcja | Starsze (`/v1/webhook`) | Punkty końcowe (`/v1/developer/webhook-endpoints`) |
|---------|------------------------|----------------------------------------------|
| Liczba adresów URL | 1 na organizację | Wiele na organizację |
| Obsługiwane zdarzenia | Tylko `telephony.*` / `web.*` | Wszystkie 10 typów zdarzeń |
| Filtr zdarzeń | — | Dla każdego punktu końcowego |
| Ponowne próby | Brak, z wyjątkiem jednej dla wymiany konfiguracji połączenia telefonicznego | 8 prób w ciągu 24 h |
| Koperta | `type` + `data` | `type` + `data` + `event_id` |
| Rotacja sekretu | Zastępuje pojedynczy sekret | Sekret dla każdego punktu końcowego |
| Wyłączenie bez usuwania | `PUT /v1/webhook` z `{"url": ""}` | `status=disabled` |
| Widoczność statusu | — | `active` / `disabled` / `failing` |
| Blokująca wymiana konfiguracji | Tak ([`telephony.incoming` / `web.incoming`](/pl/webhooks/call-incoming)) | Nigdy — tylko powiadomienia |
| Najlepsze zastosowanie | Dynamiczna konfiguracja połączeń | Obsługa zdarzeń w środowisku produkcyjnym |

Nowe integracje powinny odbierać zdarzenia przez webhooki oparte na punktach
końcowych. Zachowaj (lub dodaj) starszy adres URL tylko wtedy, gdy konfigurujesz połączenia
dynamicznie w momencie odebrania lub używasz wywoływania narzędzi w trybie webhooków — te
wymiany żądanie/odpowiedź działają tylko w starszej ścieżce.

---

## Powiązane

<CardGroup cols={2}>
  <Card title="Katalog zdarzeń" icon="list" href="/pl/webhooks/events">
    Wszystkie typy zdarzeń i ich ładunki.
  </Card>
  <Card title="Punkty końcowe webhooków" icon="bolt" href="/pl/webhooks/endpoints">
    Zarządzaj wieloma punktami końcowymi, filtrami zdarzeń i sekretami.
  </Card>
  <Card title="telephony.incoming / web.incoming" icon="phone" href="/pl/webhooks/call-incoming">
    Blokujące żądanie, na które serwer musi odpowiedzieć, aby skonfigurować połączenia.
  </Card>
  <Card title="telephony.complete / web.complete" icon="phone" href="/pl/webhooks/call-complete">
    Ładunek po połączeniu z transkrypcją, nagraniem i metrykami.
  </Card>
</CardGroup>
