Gdy ktoś składa wniosek o urlop, osoby, które powinny o tym wiedzieć, powinny się o tym dowiedzieć tam, gdzie już pracują — na Slacku. Ten przewodnik krok po kroku łączy webhooki Collabin z kanałem Slack: zasubskrybujesz zdarzenia urlopowe, zweryfikujesz kryptograficznie każdą dostawę i wyślesz sformatowaną wiadomość. Ten sam wzorzec działa z Microsoft Teams, Discordem, n8n, Make lub każdym innym wewnętrznym systemem.
Jak działają webhooki Collabin
Webhook to endpoint HTTPS, który hostujesz samodzielnie; Collabin wywołuje go żądaniem POST zawsze, gdy wystąpi zasubskrybowane zdarzenie. Dostępne są dwa zdarzenia:
| Zdarzenie | Wywoływane, gdy |
|---|---|
leave.created | zostanie złożony nowy wniosek o urlop |
leave.status_changed | wniosek zostanie zatwierdzony lub odrzucony |
Każda dostawa to koperta JSON:
{
"event": "leave.created",
"timestamp": "2026-06-13T09:30:00Z",
"delivery_id": "f3a91c0d2b8e4a17",
"organization_id": 42,
"data": {
"id": 1337,
"user_id": 7,
"user": { "id": 7, "name": "Jan Kowalski" },
"leave_type_id": 1,
"leave_type": { "id": 1, "name": "Urlop wypoczynkowy" },
"start_date": "2026-07-01T00:00:00Z",
"end_date": "2026-07-05T00:00:00Z",
"is_half_day": false,
"status": "PENDING"
}
}
Każdemu żądaniu towarzyszą trzy nagłówki:
X-Collabin-Event— nazwa zdarzenia, dzięki czemu można kierować ruch bez parsowania treści.X-Collabin-Delivery— unikalny identyfikator dostawy, przydatny do deduplikacji i korelacji logów.X-Collabin-Signature—sha256=<hex>, podpis HMAC-SHA256 surowej treści żądania, obliczony z użyciem tajnego klucza Twojego webhooka. Zawsze zweryfikuj ten podpis, zanim zaufasz danym.
Collabin czeka maksymalnie 10 sekund i traktuje każdą odpowiedź 2xx jako sukces — odpowiadaj szybko, a właściwą pracę wykonuj asynchronicznie.
Czego będziesz potrzebować
- Konta Collabin w planie Pro (zarządzanie webhookami jest dostępne tylko w tym planie).
- Przestrzeni roboczej Slack, w której możesz utworzyć incoming webhook.
- Miejsca, w którym uruchomisz ~40 linii kodu Node.js: mały VPS, Cloud Run, funkcja serverless — cokolwiek z publicznym adresem URL HTTPS.
Krok 1: Utwórz incoming webhook w Slacku
W Slacku utwórz aplikację (lub użyj istniejącej), włącz Incoming Webhooks i dodaj webhook dla kanału, na który mają trafiać powiadomienia. Slack wygeneruje adres URL w formacie https://hooks.slack.com/services/T000/B000/XXXX. Traktuj go jako tajny.
Krok 2: Wdróż mostek (bridge)
Ten mały serwer Express weryfikuje podpis Collabin i przekazuje czytelną wiadomość do Slacka:
const crypto = require('crypto');
const express = require('express');
const COLLABIN_SECRET = process.env.COLLABIN_WEBHOOK_SECRET;
const SLACK_URL = process.env.SLACK_WEBHOOK_URL;
const app = express();
// Zachowujemy surową treść — podpis jest liczony dla dokładnych bajtów.
app.use(express.raw({ type: 'application/json' }));
app.post('/collabin-webhook', async (req, res) => {
const expected = 'sha256=' + crypto
.createHmac('sha256', COLLABIN_SECRET)
.update(req.body)
.digest('hex');
const received = req.get('X-Collabin-Signature') || '';
const valid = received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!valid) {
return res.status(401).send('invalid signature');
}
// Potwierdzamy natychmiast; Collabin potrzebuje tylko odpowiedzi 2xx.
res.status(200).send('ok');
const payload = JSON.parse(req.body.toString('utf8'));
const leave = payload.data;
const who = leave.user ? leave.user.name : `użytkownik #${leave.user_id}`;
const type = leave.leave_type ? leave.leave_type.name : 'Urlop';
const from = leave.start_date.slice(0, 10);
const to = leave.end_date.slice(0, 10);
const text = payload.event === 'leave.created'
? `:palm_tree: *${who}* złożył wniosek o *${type}* od *${from}* do *${to}*`
: `:bell: wniosek *${who}* (${type}, ${from} – ${to}) ma teraz status *${leave.status}*`;
await fetch(SLACK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
});
app.listen(process.env.PORT || 3000);
Dwa szczegóły są ważniejsze, niż się wydaje:
- Weryfikuj na podstawie surowej treści. Jeśli Twój framework najpierw parsuje JSON, a Ty go ponownie serializujesz, zmiana kolejności kluczy lub białych znaków zepsuje HMAC. Odczytuj dokładne bajty.
- Używaj porównania w czasie stałym (
crypto.timingSafeEqual), aby sprawdzenie nie ujawniało informacji o czasie wykonania.
Krok 3: Zarejestruj webhook w Collabin
- W panelu Collabin otwórz Webhooki.
- Dodaj nowy webhook: wklej adres URL swojego endpointu i wybierz zdarzenia (
leave.created,leave.status_changedlub oba). - Collabin przypisze webhookowi tajny klucz — skopiuj go do zmiennej środowiskowej
COLLABIN_WEBHOOK_SECRETswojego mostka.
Złóż testowy wniosek o urlop — wiadomość powinna pojawić się w Slacku w ciągu jednej lub dwóch sekund.
Uwagi operacyjne
- Brak automatycznych ponownych prób. Dostawa działa na zasadzie „wyślij i zapomnij": jeśli Twój endpoint jest nieosiągalny lub zwróci status inny niż 2xx, zdarzenie nie zostanie wysłane ponownie — natomiast nieudana próba zostaje zapisana w dzienniku błędów systemowych Collabin, dzięki czemu wiesz dokładnie, co i kiedy poszło nie tak.
- Dezaktywuj, nie usuwaj podczas debugowania: webhook można przełączyć na nieaktywny i później ponownie włączyć bez konieczności wprowadzania konfiguracji od nowa.
- Jeden webhook na odbiorcę. Każdy webhook ma własny tajny klucz; każdemu systemowi docelowemu przypisz własną rejestrację, a nie jeden wspólny endpoint.
Poza Slackiem
Powyższy mostek jest celowo minimalny. Korzystając z tych samych zweryfikowanych danych, możesz automatycznie oznaczać osoby jako nieobecne, synchronizować z wewnętrznym systemem HR lub zasilać narzędzie no-code — wskaż trigger webhooka w n8n lub Make na Collabin, a weryfikację podpisu umieść w kroku typu function.