Webhooki - wysyłanie zdarzeń z Chateo do Twoich systemów
Jak dodać adres webhooka, jakie zdarzenia wysyła Chateo, jak sprawdzić podpis, co dzieje się przy błędach i jak przeglądać dostawy.
Webhook to adres w Twoim systemie, na który Chateo wysyła wiadomość (żądanie HTTP), gdy w czatach coś się wydarzy: ktoś zaczyna rozmowę, pisze wiadomość, zostawia dane w formularzu offline albo ocenia rozmowę. Dzięki temu Twój system dowiaduje się o tym od razu, bez odpytywania Chateo.
Przykłady użycia w sklepie „Sklep z kawą":
- CRM - każda wiadomość z formularza offline zakłada kontakt lub zgłoszenie sprzedażowe.
- Powiadomienia zespołu - zakończona rozmowa z oceną
badwysyła alert do kanału, który obserwuje obsługa. - Własna analiza - zdarzenia trafiają do hurtowni danych, a Ty liczysz czas pierwszej odpowiedzi i oceny po swojemu.
Webhookami zarządza właściciel konta lub administrator. Konsultanci i administratorzy ograniczeni do wybranych stron nie widzą tej sekcji.
Dostępność w pakietach
Webhooki są dostępne w pakiecie Biznes (do 10 adresów). Aktualny stan swojego konta zobaczysz w Ustawienia > Webhooki (np. „Adresy: 1 z 10"). Jeśli pakiet nie obejmuje webhooków, zobaczysz komunikat Webhooki są dostępne w pakiecie Biznes. Adresy dodane wcześniej (np. przed zmianą pakietu) nadal widać na liście: możesz obejrzeć ich szczegóły i historię dostaw, wyłączyć je albo usunąć, ale Chateo nie wysyła na nie zdarzeń. Szczegóły pakietów: Pakiety i płatności.
Dodanie adresu
- Wejdź w Ustawienia > Webhooki i kliknij Dodaj adres.
- W polu Adres URL wpisz adres swojego odbiornika. Adres musi zaczynać się od
https://, mieć standardowy port 443, być nazwą domeny (nie adresem IP) i być dostępny z internetu. Adresy wskazujące na sieć prywatną są odrzucane. - Opcjonalnie dodaj Opis (opcjonalnie), np. „CRM sprzedaży".
- W polu Zdarzenia zaznacz te, które chcesz dostawać.
- W polu Strony wybierz Wszystkie strony albo Wybrane strony.
- Jeśli masz włączoną weryfikację dwuetapową, wpisz Kod z aplikacji uwierzytelniającej.
- Kliknij Dodaj adres.
Zaraz po dodaniu zobaczysz okno Klucz podpisu. Skopiuj klucz od razu - ze względów bezpieczeństwa nie pokażemy go ponownie. Okno zamkniesz tylko przyciskiem Skopiowałem, zamknij (klawisz Esc ani kliknięcie obok go nie zamykają). Klucz zaczyna się od whsec_ i służy do sprawdzania podpisu (niżej). Przechowuj go w sekretach swojej aplikacji, nie w kodzie.
Właściciel konta i administratorzy z dostępem do wszystkich stron dostają e-mail o każdym nowym adresie i o każdej zmianie adresu (ten e-mail wysyłamy zawsze, także gdy wyłączyłeś powiadomienia o skrzynkach), żeby nikt niepostrzeżenie nie wyprowadzał rozmów z konta. Jeśli to nie Ty dodałeś adres, usuń go i zmień hasło.
Zdarzenia
Każde żądanie to JSON w tej samej kopercie:
id- unikalny identyfikator zdarzenia (taki sam przy każdym ponowieniu),type- rodzaj zdarzenia,api_version- wersja formatu (obecnie2026-11-01; adres zostaje przy wersji, z którą go dodano),created_at- czas zdarzenia (UTC),account_id- identyfikator Twojego konta w Chateo,portal- strona, której dotyczy zdarzenie (ididomain),data- szczegóły zależne od rodzaju zdarzenia.
W ścieżkach stron (page_path) usuwamy parametry zapytania i fragment po #, bo często zawierają adresy e-mail albo tokeny zamówień. Nie wysyłamy adresów IP, danych przeglądarki ani lokalizacji. Załączniki mają tylko opis (rodzaj i rozmiar), bez linku do pliku. W kolejnych wersjach do kopert mogą dochodzić nowe pola - nie traktuj nieznanych pól jako błędu.
Rozpoczęta rozmowa (conversation.started)
Kiedy odwiedzający albo konsultant rozpoczyna rozmowę. Rozmowa z reguły proaktywnej liczy się dopiero wtedy, gdy odwiedzający odpisze. customer_id to Twój identyfikator klienta i jest wypełniony tylko wtedy, gdy sklep przekazał go w zweryfikowany sposób.
{
"id": "0193f1c2-7a10-7c3e-9d11-5b2f6a4e8c01",
"type": "conversation.started",
"api_version": "2026-11-01",
"created_at": "2026-11-09T12:00:00.000Z",
"account_id": "0193e000-1111-7222-8333-944455556666",
"portal": { "id": "0193e000-aaaa-7bbb-8ccc-9dddeeeeffff", "domain": "sklep-z-kawa.example.com" },
"data": {
"conversation": { "id": "0193f1c2-7a0f-7000-8000-0123456789ab", "started_by": "visitor", "page_path": "/kawa/ziarnista" },
"visitor": { "id": "0193f1b0-0000-7000-8000-00000000abcd", "customer_id": null }
}
}Nowa wiadomość (message.created)
Wiadomość odwiedzającego lub konsultanta. Wiadomości bota i systemowe nie są wysyłane. W text jest treść wpisana przez rozmówcę. Przy bardzo długiej treści tekst jest skracany, a truncated ma wartość true. Dla wiadomości konsultanta dochodzi obiekt operator (imię wyświetlane, bez adresu e-mail).
{
"id": "0193f1c3-1b20-7a4e-8e22-6c3f7b5f9d02",
"type": "message.created",
"api_version": "2026-11-01",
"created_at": "2026-11-09T12:01:10.000Z",
"account_id": "0193e000-1111-7222-8333-944455556666",
"portal": { "id": "0193e000-aaaa-7bbb-8ccc-9dddeeeeffff", "domain": "sklep-z-kawa.example.com" },
"data": {
"conversation_id": "0193f1c2-7a0f-7000-8000-0123456789ab",
"message": {
"id": "0193f1c3-1b1f-7000-8000-0123456789cd",
"sender_type": "operator",
"text": "Dzień dobry, ta kawa jest świeżo palona w tym tygodniu.",
"truncated": false,
"attachments": [],
"created_at": "2026-11-09T12:01:10.000Z"
},
"operator": { "id": "0193e001-0000-7000-8000-000000000001", "name": "Anna" }
}
}Zakończona rozmowa (conversation.closed)
Rozmowa zamknięta przez odwiedzającego, konsultanta albo automatycznie po bezczynności (closed_by: visitor, operator, inactivity). first_reply_seconds to czas pierwszej odpowiedzi (albo null). Obiekt operator pojawia się, gdy rozmowa miała przypisanego konsultanta.
{
"id": "0193f1d0-4c30-7b5f-8f33-7d4a8c6a0e03",
"type": "conversation.closed",
"api_version": "2026-11-01",
"created_at": "2026-11-09T12:20:00.000Z",
"account_id": "0193e000-1111-7222-8333-944455556666",
"portal": { "id": "0193e000-aaaa-7bbb-8ccc-9dddeeeeffff", "domain": "sklep-z-kawa.example.com" },
"data": {
"conversation": {
"id": "0193f1c2-7a0f-7000-8000-0123456789ab",
"closed_by": "operator",
"started_at": "2026-11-09T12:00:00.000Z",
"closed_at": "2026-11-09T12:20:00.000Z",
"visitor_messages": 4,
"operator_messages": 5,
"first_reply_seconds": 38
},
"operator": { "id": "0193e001-0000-7000-8000-000000000001", "name": "Anna" }
}
}Wiadomość z formularza offline (offline_message.created)
Gdy nikogo nie ma i odwiedzający zostawia e-mail oraz wiadomość. To zdarzenie zawiera adres e-mail i dowolny tekst, więc traktuj je jak dane kontaktowe.
{
"id": "0193f2a0-5d40-7c6a-9044-8e5b9d7b1f04",
"type": "offline_message.created",
"api_version": "2026-11-01",
"created_at": "2026-11-09T22:15:00.000Z",
"account_id": "0193e000-1111-7222-8333-944455556666",
"portal": { "id": "0193e000-aaaa-7bbb-8ccc-9dddeeeeffff", "domain": "sklep-z-kawa.example.com" },
"data": {
"conversation_id": "0193f2a0-5d3f-7000-8000-0123456789ef",
"email": "[email protected]",
"text": "Czy macie kawę bezkofeinową w paczkach po kilogramie?",
"truncated": false,
"page_path": "/kawa/bezkofeinowa"
}
}Ocena rozmowy (rating.submitted)
Odwiedzający ocenił rozmowę: rating to 1, 2 lub 3, a rating_label to odpowiednio bad, ok, good. Komentarz może być pusty (null). Jeśli odwiedzający najpierw wybierze ocenę, a potem dopisze komentarz, dostaniesz dwa zdarzenia dla tej samej rozmowy.
{
"id": "0193f1d5-6e50-7d7b-8155-9f6c0e8c2a05",
"type": "rating.submitted",
"api_version": "2026-11-01",
"created_at": "2026-11-09T12:21:30.000Z",
"account_id": "0193e000-1111-7222-8333-944455556666",
"portal": { "id": "0193e000-aaaa-7bbb-8ccc-9dddeeeeffff", "domain": "sklep-z-kawa.example.com" },
"data": {
"conversation_id": "0193f1c2-7a0f-7000-8000-0123456789ab",
"rating": 3,
"rating_label": "good",
"comment": "Szybka i konkretna odpowiedź, dziękuję."
}
}Test (webhook.test)
Zdarzenie wysyłane tylko przyciskiem Wyślij test. Nie wybierasz go w liście zdarzeń. W data ma jedno pole message z tekstem „Test z Chateo". Przyda się do sprawdzenia adresu i weryfikacji podpisu.
Nagłówki żądania
| Nagłówek | Znaczenie |
|---|---|
Content-Type | zawsze application/json |
User-Agent | Chateo-Webhooks/1.0 (+https://chateo.pl/pomoc/webhooki) |
Chateo-Event-Id | identyfikator zdarzenia, taki sam przy każdym ponowieniu - użyj go do usuwania duplikatów |
Chateo-Event-Type | rodzaj zdarzenia, np. message.created |
Chateo-Delivery-Id | identyfikator tej dostawy |
Chateo-Attempt | numer próby (1, 2, 3...) |
Chateo-Signature | podpis żądania (patrz niżej) |
Sprawdzanie podpisu
Każde żądanie jest podpisane Twoim kluczem, więc możesz upewnić się, że pochodzi z Chateo i nie zostało zmienione. Nagłówek ma postać:
Chateo-Signature: t=1731153600,v1=<64 znaki szesnastkowe>
t- czas wysłania w sekundach (czas uniksowy),v1- podpis zapisany szesnastkowo małymi literami: HMAC-SHA256 z tekstut, kropki i surowej treści żądania (dokładnie tych bajtów, które dostałeś, przed parsowaniem JSON). Kluczem jest cały ciąg klucza podpisu razem zwhsec_, jako tekst UTF-8 (nie dekoduj go z base64).
Po zmianie klucza (niżej) nagłówek zawiera dwa wpisy v1= - nowy i stary. Wystarczy, że zgadza się którykolwiek.
Odrzucaj żądania, w których t różni się od Twojego czasu o więcej niż 300 sekund (ochrona przed ponownym odtworzeniem), i porównuj podpisy funkcją odporną na ataki czasowe. Zanim porównasz podpis, sprawdź, że ma dokładnie 64 znaki szesnastkowe (małe litery) - inaczej uznaj go za błędny. Bez tego sprawdzenia zniekształcony nagłówek może wywołać wyjątek w funkcji porównującej (np. timingSafeEqual w Node.js) i błąd 500 zamiast odrzucenia żądania.
Wektor testowy do sprawdzenia własnej implementacji: klucz whsec_exampleExampleExampleExampleExampleExample1, t = 1731153600, treść {"type":"webhook.test"} daje podpis f59c85f79a52044aeeea07a9b984a3fd429313675bca8fad225bddf60f59029d.
Node.js
Użyj surowej treści, np. w Express: app.post('/chateo', express.raw({ type: 'application/json' }), handler).
const crypto = require('node:crypto');
function verifyChateo(rawBody, header, secret, toleranceSec = 300) {
const parts = header.split(',').map((p) => p.trim().split('='));
const t = Number(parts.find(([k]) => k === 't')?.[1]);
const sigs = parts.filter(([k]) => k === 'v1').map(([, v]) => v);
if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
return sigs.some((s) => {
// Dokładnie 64 znaki szesnastkowe (małe litery) - inaczej podpis jest błędny, bez wyjątku.
if (typeof s !== 'string' || !/^[0-9a-f]{64}$/.test(s)) return false;
const given = Buffer.from(s, 'hex');
return given.length === 32 && expected.length === 32 && crypto.timingSafeEqual(given, expected);
});
}
// w obsłudze żądania:
// verifyChateo(req.body.toString('utf8'), req.get('Chateo-Signature') ?? '', process.env.CHATEO_WEBHOOK_SECRET)PHP
<?php // PHP 7.4+
function chateo_verify(string $payload, string $header, string $secret, int $tolerance = 300): bool {
$t = null; $sigs = [];
foreach (explode(',', $header) as $part) {
[$k, $v] = array_pad(explode('=', trim($part), 2), 2, '');
if ($k === 't' && ctype_digit($v)) { $t = (int) $v; } elseif ($k === 'v1') { $sigs[] = $v; }
}
if ($t === null || abs(time() - $t) > $tolerance) { return false; }
$expected = hash_hmac('sha256', $t . '.' . $payload, $secret, true); // 32 bajty
foreach ($sigs as $s) {
// Dokładnie 64 znaki szesnastkowe (małe litery) - inaczej podpis jest błędny.
if (preg_match('/^[0-9a-f]{64}$/', $s) !== 1) { continue; }
$given = hex2bin($s);
if ($given !== false && strlen($given) === 32 && hash_equals($expected, $given)) { return true; }
}
return false;
}
$payload = file_get_contents('php://input');
if (!chateo_verify($payload, $_SERVER['HTTP_CHATEO_SIGNATURE'] ?? '', getenv('CHATEO_WEBHOOK_SECRET'))) {
http_response_code(400);
exit;
}
http_response_code(200); // odpowiedz szybko, resztę przetwarzaj osobnoOdpowiedź, ponowienia i duplikaty
- Za sukces uznajemy każdą odpowiedź
2xxw ciągu 10 sekund. Odpowiadaj szybko, a zdarzenie przetwarzaj osobno. - Przekierowania (
3xx) traktujemy jako błąd i nie podążamy za nimi - podaj docelowy adres bezpośrednio. - Przy błędzie ponawiamy wysyłkę: po 1 minucie, 5 minutach, 30 minutach, 2, 6, 12 i 24 godzinach (z niewielkim losowym rozrzutem). To łącznie 8 prób w ciągu około 45 godzin. Potem dostawa dostaje status Nieudane.
- Dostawa może trafić do Ciebie więcej niż raz. Zapisuj
Chateo-Event-Idi ignoruj zdarzenia, które już przetworzyłeś. - Kolejność zdarzeń nie jest gwarantowana. Jeśli jej potrzebujesz, sortuj po
created_at.
Automatyczne wyłączenie
Jeśli Twój serwer przez ponad dobę nie przyjmuje zdarzeń i było już wiele nieudanych prób z rzędu, Chateo wyłącza adres (status Wyłączony automatycznie), a zaległe dostawy kończą się jako Nieudane. Właściciel i administratorzy z dostępem do wszystkich stron dostają o tym e-mail (zawsze, także przy wyłączonych powiadomieniach o skrzynkach), raz na jedno wyłączenie. Gdy naprawisz serwer, kliknij Włącz ponownie. Zdarzeń z czasu przerwy nie odtwarzamy automatycznie - możesz je wysłać ponownie z listy dostaw, dopóki są dostępne (niżej).
Adres możesz też wyłączyć sam przyciskiem Wyłącz (na przykład na czas prac na serwerze) i potem włączyć przyciskiem Włącz.
Wyślij test i lista dostaw
Przy każdym adresie jest przycisk Wyślij test. Wynik zobaczysz od razu, np. „Test dostarczony - HTTP 200, 120 ms", albo przyczynę błędu, np. „brak odpowiedzi w 10 s", „nie znaleziono adresu", „błąd certyfikatu HTTPS", „nie udało się połączyć", „serwer odpowiedział kodem 500".
Po kliknięciu Szczegóły zobaczysz sekcję Ostatnie dostawy z kolumnami Czas, Zdarzenie, Status, Kod HTTP, Próby i Czas odpowiedzi. Statusy to Dostarczone, Ponawiane, Oczekuje, Wysyłane i Nieudane; listę możesz przefiltrować. Po rozwinięciu wiersza (Pokaż) widać odpowiedź Twojego serwera (pierwsze 256 znaków), błąd i czas następnej próby. Przycisk Wyślij ponownie wysyła dane zdarzenie jeszcze raz.
Historię dostaw przechowujemy ograniczony czas, a treść zdarzenia krócej niż wpis w historii. Starszych zdarzeń nie da się wysłać ponownie: Zdarzenie jest starsze niż 7 dni - nie można go wysłać ponownie.
Zmiana klucza podpisu
Jeśli klucz mógł wyciec, kliknij Wygeneruj nowy klucz przy adresie (z kodem z aplikacji uwierzytelniającej, jeśli ją masz). Nowy klucz działa od razu, a stary podpisuje żądania jeszcze przez 24 godziny, żebyś zdążył podmienić go u siebie bez przerwy w dostawach. Datę końca zobaczysz przy adresie. Nowy klucz pokazujemy tylko raz.
Zapier, Make, n8n
W Zapier, Make i n8n użyj wyzwalacza typu „Catch Hook" (odbiornik webhooków) i wklej jego adres https:// do pola Adres URL. Kliknij Wyślij test, żeby narzędzie zobaczyło przykładowe dane. Weryfikacja podpisu w tych narzędziach jest opcjonalna i wymaga własnego kroku z kodem - przy niewrażliwych danych często można ją pominąć, ale wtedy każdy, kto pozna adres, może do niego pisać.
Prywatność
Do Twojego systemu trafiają dane osobowe Twoich rozmówców: treść wiadomości, a w formularzu offline także adres e-mail. Od momentu wysłania Ty jesteś administratorem tych danych w swoim systemie - uwzględnij odbiorcę webhooków w rejestrze czynności przetwarzania i w informacji o prywatności. Więcej: Prywatność i RODO.
- Nie wysyłamy adresów IP, danych przeglądarki ani lokalizacji, a adresy stron są bez parametrów zapytania.
- Gdy usuwasz dane odwiedzającego, usuwamy też jego zdarzenia z historii dostaw Chateo (to, co już trafiło do Twojego systemu, usuwasz u siebie).
- Usunięcie adresu zatrzymuje wysyłkę od razu i kasuje jego historię dostaw.
Rozwiązywanie problemów
| Komunikat | Co zrobić |
|---|---|
| Ten adres wskazuje na sieć prywatną | Użyj publicznej nazwy domeny. Adresy lokalne i wewnętrzne są blokowane ze względów bezpieczeństwa. |
| Adres musi zaczynać się od https:// | Skonfiguruj certyfikat HTTPS na odbiorniku. |
| Użyj standardowego portu HTTPS (443). | Wystaw odbiornik na porcie 443 (np. przez serwer pośredniczący). |
| brak odpowiedzi w 10 s | Odpowiadaj 200 od razu, a zdarzenie przetwarzaj w tle. |
| błąd certyfikatu HTTPS | Sprawdź, czy certyfikat jest ważny, wystawiony na tę domenę i ma pełny łańcuch. |
| nie znaleziono adresu | Sprawdź nazwę domeny w adresie URL i rekordy DNS. |
| nie udało się połączyć | Sprawdź, czy serwer działa i przepuszcza ruch z internetu na port 443. |
| serwer odpowiedział kodem 4xx lub 5xx | Obejrzyj odpowiedź w Ostatnie dostawy i logi własnego serwera. Sprawdź też podpis - zła weryfikacja zwykle kończy się kodem 400 lub 401. |
| Ten adres jest już dodany. | Każdy adres można dodać do konta tylko raz. |
| Osiągnięto limit adresów w Twoim pakiecie | Usuń nieużywany adres albo zmień pakiet: Pakiety i płatności. |
Jeśli te kroki nie pomagają, napisz do nas przez czat na chateo.pl i podaj czas oraz rodzaj zdarzenia z listy dostaw.