Przejdź do głównej zawartości

Webhooki

Subskrypcje webhooków działają w stylu RestHooks. Zapier tworzy i usuwa subskrypcje automatycznie, gdy użytkownik włącza albo wyłącza wyzwalacz.

Subskrypcja

POST /api/v1/webhooks/subscribe
Authorization: Bearer lzy_at_your_access_token
Content-Type: application/json
{
"target_url": "https://hooks.zapier.com/hooks/catch/123/abc/",
"event_types": ["lead.created"],
"filters": {
"chatbot_id": "optional-chatbot-id"
}
}

Odpowiedź zawiera subskrypcję i sekret do podpisywania. Sekret pokazywany jest tylko raz.

Lista i usuwanie

EndpointMetoda
/api/v1/webhooksGET
/api/v1/webhooks/:idGET
/api/v1/webhooks/:idDELETE

Wszystkie endpointy webhooków wymagają zakresu webhooks:manage.

Typy zdarzeń

ZdarzenieOpis
lead.createdPozyskano nowego leada.
lead.qualifiedLead osiągnął próg kwalifikacji.
conversation.message_receivedW rozmowie pojawiła się nowa wiadomość.
ticket.createdUtworzono zgłoszenie serwisowe.
meeting.scheduledZarezerwowano spotkanie.
meeting.cancelledOdwołano spotkanie.

Bezpieczeństwo dostarczania

Leezy wysyła każdy webhook z następującymi nagłówkami:

NagłówekZastosowanie
X-Leezy-SignaturePodpis HMAC SHA-256 z <timestamp>.<raw_body>, poprzedzony sha256=.
X-Leezy-TimestampZnacznik czasu unix (w sekundach), wchodzi w skład podpisywanych danych.
X-Leezy-EventTyp zdarzenia.
X-Leezy-DeliveryIdentyfikator wpisu w logu dostarczeń.

Aby zweryfikować dostarczenie, przelicz HMAC z ${timestamp}.${raw_body} przy użyciu sekretu subskrypcji i porównaj z X-Leezy-Signature. Znacznik czasu jest częścią podpisywanych danych — odbiorca MUSI odrzucać dostarczenia, w których X-Leezy-Timestamp różni się o więcej niż pięć minut od czasu bieżącego. Bez tego okna przechwycony ładunek można byłoby odtwarzać w nieskończoność, bo ta sama treść zawsze daje ten sam podpis.

Przykład weryfikacji (Node.js):

import crypto from "node:crypto";

function verifyLeezySignature(rawBody, headers, secret) {
const timestamp = headers["x-leezy-timestamp"];
const signature = headers["x-leezy-signature"];
const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
if (!timestamp || ageSeconds > 300) return false;

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

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}