Webhooki dla nowych leadów

Webhook wysyła każdy nowy lead z Twoich kanałów czatu, takich jak czat na stronie, Messenger i Instagram, do innej aplikacji zaraz po jego zebraniu: do CRM, Zapiera, Make, n8n albo Twojego własnego kodu. KnowStack wykonuje podpisany POST HTTPS z danymi kontaktowymi leada i rozmową do tej chwili.

Webhooki leadów są dostępne w planach Business i Enterprise oraz w bezpłatnym okresie próbnym. Skonfigurujesz je, jeśli Twoja rola może zarządzać użytkownikami, na przykład Company Admin.

Dodawanie webhooka

  1. Skopiuj adres webhooka z aplikacji, która ma odbierać leady. Musi zaczynać się od https://.
  2. W KnowStack otwórz Ustawienia, wybierz „Integracje” i przejdź do sekcji „Wysyłaj leady do swojego CRM”.
  3. W części „Dodaj webhook” wpisz w polu „Nazwa” nazwę, którą łatwo rozpoznasz, wklej adres w polu „Adres webhooka” i kliknij „Dodaj webhook”.
  4. Skopiuj wyświetlony klucz podpisu. Zaczyna się od whsec_ i jest pokazywany tylko raz. Potem kliknij „Zapisałem go”.
  5. Otwórz menu webhooka i kliknij „Wyślij test”. Wynik pojawi się od razu, a także w sekcji „Dziennik wysyłek”.

Wysyłane są tylko leady zebrane po dodaniu webhooka; wcześniejsze zostają w KnowStack. Możesz dodać kilka webhooków, a każdy nowy lead trafia do wszystkich aktywnych.

Adres musi być publiczny: tylko https, na standardowym porcie, bez nazwy użytkownika i hasła. Adresy w sieci prywatnej lub lokalnej są odrzucane, także gdy publiczna nazwa zacznie później na taką wskazywać. Przekierowania nie są obsługiwane, więc wklej adres docelowy.

Kiedy wysyłane są żądania

ZdarzenieKiedyCo zawiera
lead.createdCzat zbiera nowy leadLead i rozmowa do tej chwili
lead.updatedImię, e-mail lub telefon pojawia się później w tym samym leadzieAktualne dane leada i lista changed z nowymi polami, bez rozmowy
testKlikasz „Wyślij test”Przykładowy lead z id 0 i krótka przykładowa rozmowa

Wiadomości napisane po utworzeniu leada nigdy nie są wysyłane. Żądanie lead.updated wychodzi dopiero po przyjęciu lead.created i tylko wtedy, gdy pole zmieniło się z pustego na wypełnione.

Nagłówki żądania

NagłówekWartość
Content-Typeapplication/json
User-AgentLeadWebhook/1.0
X-Webhook-Eventlead.created, lead.updated lub test
X-Webhook-DeliveryIdentyfikator wysyłki. Ponowna próba tej samej wysyłki go zachowuje, więc używaj go do pomijania duplikatów
X-Webhook-TimestampMoment podpisania w sekundach Unix
X-Webhook-Signaturev1= i szesnastkowy HMAC-SHA256 ze znacznika czasu, kropki i surowej treści, obliczony Twoim kluczem podpisu

Treść (wersja 1)

Treść to JSON w UTF-8, wysyłany bez podziałów wierszy i pokazany tu w sformatowanej postaci. Wartości w nawiasach ostrych oznaczają Twoje własne: nazwa produktu to KnowStack, a adres to ten, pod którym się logujesz. Żądanie lead.created:

{
  "version": 1,
  "event": "lead.created",
  "deliveryId": "4821",
  "occurredAt": "2026-01-15T10:03:12.000Z",
  "lead": {
    "id": 1375,
    "name": "Anna Novak",
    "email": "[email protected]",
    "phone": null,
    "channel": "web_chat",
    "channelLabel": "Website chat",
    "source": "<product name> · Website chat",
    "question": "Do you have availability next week?",
    "firstPageUrl": "https://example.com/pricing",
    "locale": "en",
    "capturedAt": "2026-01-15T10:02:40.000Z",
    "conversationUrl": "https://<your app address>/dashboard/channels/website-chat?conversation=812"
  },
  "transcript": [
    { "from": "customer", "text": "Hi, do you have availability next week?", "at": "2026-01-15T10:00:05.000Z" },
    { "from": "ai", "text": "Yes, we do. Could I take your email so the team can confirm a time?", "at": "2026-01-15T10:00:09.000Z" },
    { "from": "customer", "text": "Sure, [email protected]", "at": "2026-01-15T10:02:40.000Z" }
  ],
  "transcriptIncomplete": false
}
PoleZnaczenie
versionW tym formacie zawsze 1. Zmiana, która mogłaby zepsuć Twój kod, dostanie nowy numer
event, deliveryIdTe same wartości co w nagłówkach X-Webhook-Event i X-Webhook-Delivery
occurredAtMoment zbudowania żądania w formacie ISO 8601 (UTC)
lead.idIdentyfikator leada w KnowStack. lead.updated ma ten sam identyfikator, więc znajdziesz utworzony rekord
lead.name, lead.email, lead.phoneDane kontaktowe. Każde z nich może mieć wartość null
lead.channelGdzie odbył się czat: obecnie web_chat, messenger lub instagram. Wraz z nowymi kanałami pojawią się nowe wartości, więc akceptuj dowolny tekst
lead.channelLabel, lead.sourceWyświetlana nazwa kanału i gotowe źródło leada, na przykład "KnowStack · Instagram", w języku osoby, która dodała webhook
lead.questionPytanie zadane przez klienta przy zbieraniu leada albo null
lead.firstPageUrl, lead.localeStrona, na której zaczął się czat na stronie, i język odwiedzającego. W innych kanałach zwykle null
lead.capturedAtMoment pozostawienia danych kontaktowych
lead.conversationUrlLink do rozmowy w KnowStack dla osób, które mogą zalogować się do Twojej firmy
transcriptRozmowa do chwili utworzenia leada, od najstarszej wiadomości, maksymalnie 500 wiadomości. Każda ma from (customer, ai lub team), text i at
transcriptIncompletetrue, gdy starsze wiadomości zostały już usunięte zgodnie z ustawieniami przechowywania. Takie wiadomości mają text równe null i purged równe true

Treść lead.updated ma te same pola version, event, deliveryId, occurredAt i lead, z aktualnymi wartościami leada. Zamiast rozmowy zawiera changed, listę pól wypełnionych od ostatniego żądania, na przykład ["phone"].

Weryfikacja podpisu

  1. Odczytaj surową treść żądania, zanim przetworzysz ją jako JSON.
  2. Połącz wartość X-Webhook-Timestamp, kropkę i surową treść.
  3. Oblicz HMAC-SHA256 tego tekstu swoim kluczem podpisu, pełną wartością razem z whsec_, i zapisz go szesnastkowo.
  4. Porównaj v1= z tą wartością z nagłówkiem X-Webhook-Signature, używając porównania w stałym czasie.
  5. Odrzuć żądanie, jeśli znacznik czasu różni się od Twojego zegara o więcej niż 5 minut. Dzięki temu nikt nie odtworzy starego żądania.

Przykład dla Node.js z Express:

const crypto = require('crypto');
const express = require('express');

const SECRET = process.env.LEAD_WEBHOOK_SECRET; // whsec_...
const app = express();

// Keep the body raw: the signature covers the exact bytes that were sent.
app.post('/leads', express.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.get('X-Webhook-Timestamp') || '';
  const received = req.get('X-Webhook-Signature') || '';
  const expected = 'v1=' + crypto
    .createHmac('sha256', SECRET)
    .update(timestamp + '.' + req.body)
    .digest('hex');

  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
  const valid = received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
  if (!fresh || !valid) return res.status(401).end();

  const body = JSON.parse(req.body);
  // req.get('X-Webhook-Delivery') identifies the delivery: skip it if you
  // have already handled it.
  console.log(body.event, body.lead.id);
  res.status(204).end();
});

app.listen(3000);

Do sprawdzenia kodu: klucz whsec_test, znacznik czasu 1761559200 i treść {"a":1} dają podpis v1=ed347bcd87edf5b36afc10e41346740621d7f3c26b13ee1a4cc1eb7cddd0786f.

Odpowiedzi i ponowne próby

Twoja odpowiedźCo się dzieje
2xxDostarczono
408, 429, 5xx, przekroczony czas lub błąd sieciPonowne próby w coraz dłuższych odstępach przez około 24 godziny, potem oznaczenie jako nieudane. Retry-After przy 429 jest respektowany, maksymalnie do godziny
410Webhook od razu przechodzi w stan „Wymaga uwagi”
401, 403 lub 404 trzy razy bez udanej wysyłki pomiędzyWebhook przechodzi w stan „Wymaga uwagi”
Każdy inny kod, także przekierowanieOznaczenie jako nieudane, bez ponownych prób

Odpowiedz w ciągu 10 sekund, inaczej próba liczy się jako przekroczenie czasu. Odczytywane są tylko pierwsze 64 KB Twojej odpowiedzi. Najpierw odpowiedz, a czasochłonną pracę wykonaj potem.

Gdy webhook wymaga uwagi

Dopóki webhook ma stan „Wymaga uwagi” lub „Wstrzymany”, nowe leady czekają w kolejce zamiast przepadać. Gdy webhook przestaje działać, osoby zarządzające użytkownikami dostają jedno powiadomienie w dzwonku, a także w Telegramie, jeśli go połączyły. Napraw aplikację odbierającą albo popraw adres przez „Edytuj”, lub kliknij „Wznów”, jeśli adres był prawidłowy. Wysyłanie rusza ponownie, zaczynając od leadów, które czekały.

„Dziennik wysyłek” w menu webhooka pokazuje ostatnie 50 żądań z wynikiem i kodem odpowiedzi. Kliknij „Ponów” przy nieudanym, aby wysłać je jeszcze raz z tym samym identyfikatorem wysyłki. W zakładce „Leady” każdego kanału czatu znacznik pokazuje, czy lead dotarł do CRM; dla leada, który nie został wysłany, wybierz „Wyślij ponownie do CRM” w menu jego wiersza. Jeśli leady nadal nie docierają, a webhook pozostaje aktywny, jego wiersz pokazuje „Ostatnie wysyłki nie powiodły się”, a osoby zarządzające użytkownikami dostają powiadomienie, najwyżej raz dziennie.

Klucz podpisu

Jeśli klucz wyciekł, wybierz „Nowy klucz podpisu” w menu webhooka. Stary klucz od razu przestaje działać, więc od razu wpisz nowy w aplikacji odbierającej.

Jeśli Twoja firma przejdzie na plan bez webhooków leadów, nowe leady nie są wysyłane. Leady, które w tym czasie trafią do aktywnego webhooka, są pomijane i po zmianie planu na wyższy nie zostaną wysłane same; po zmianie planu możesz wysłać każdy z nich przez „Wyślij ponownie do CRM”. Leady czekające przy wstrzymanym webhooku lub takim, który wymaga uwagi, zostają w kolejce i zostaną wysłane, gdy zmienisz plan i wznowisz webhook. Twoje webhooki zostają na liście i nadal możesz je wstrzymać lub usunąć.