## Webhooki

Webhook wysyła dane zgłoszenia jako żądanie HTTP POST z treścią JSON pod wskazany adres. Możesz w ten sposób:

- powiadamiać kanały firmowe — **Slack**, **Google Chat**, **Microsoft Teams**,
- przekazywać zdarzenia do własnego systemu (ERP, CRM, sklep, automatyzacje).

Webhooki konfigurujesz pod **System → Webhooki**.

{% callout title="Wymagania" %}
Webhooki są dostępne w planie **Business**. Do zarządzania nimi potrzebne są uprawnienia grupy *Webhooki* (przeglądanie, podgląd, dodawanie, edycja, usuwanie) — nadaje je administrator konta.
{% /callout %}

## Jak to działa

Wysyłka składa się z trzech elementów:

1. **Webhook** — dokąd wysłać: adres, rodzaj i uwierzytelnienie. Jeden webhook (np. kanał na Slacku) może być używany przez wiele reguł.
2. **Szablon webhooka** — co wysłać: treść JSON z danymi zgłoszenia, tworzona w [Szablonach](/config/templates#szablon-webhooka).
3. **Reguła biznesowa** — kiedy wysłać: akcja **Wysyłanie webhooka** łączy webhook z szablonem i uruchamia się na wybranym zdarzeniu ([Reguły biznesowe](/config/business-rules#wysylanie-webhooka)).

Dzięki temu ten sam kanał może dostawać różne wiadomości — np. „nowe zgłoszenie” z jednej reguły i „zmiana etapu” z drugiej.

## Dodawanie webhooka

1. Przejdź do **System → Webhooki** i kliknij **Nowy webhook**.
2. Wpisz **Nazwę** i wybierz **Rodzaj**.
3. Wklej **Adres URL** podany przez odbiorcę (wymagany `https`).
4. Dla rodzaju *Ogólny* wybierz opcjonalnie **Uwierzytelnienie**.
5. Zapisz. Dla webhooka ogólnego zobaczysz **sekret podpisu** — skopiuj go od razu, jest pokazywany tylko raz.

### Rodzaje webhooków

| Rodzaj | Do czego | Adres |
|---|---|---|
| **Ogólny (JSON + podpis)** | Własny system lub dowolna usługa przyjmująca JSON | Dowolny publiczny adres `https` |
| **Slack** | Kanał na Slacku (Incoming Webhook) | `https://hooks.slack.com/...` |
| **Google Chat** | Pokój w Google Chat (webhook przychodzący) | `https://chat.googleapis.com/...` |
| **Microsoft Teams** | Kanał w Teams (przepływ *Workflows* przyjmujący żądanie webhooka) | Adres wygenerowany przez Teams |

Adres webhooka Slacka, Google Chat i Teams zawiera tajny token. Dlatego po zapisaniu Reklamator nie pokazuje pełnego adresu — tylko jego początek (np. `https://hooks.slack.com/…`). Przy edycji zostaw pole adresu puste, żeby go nie zmieniać.

Adresy wewnętrzne (np. `localhost`, adresy sieci prywatnych) są odrzucane — webhook musi być dostępny z internetu.

### Uwierzytelnienie (webhook ogólny)

| Uwierzytelnienie | Co wysyła Reklamator |
|---|---|
| **Brak** | Bez nagłówka uwierzytelnienia |
| **Basic** | `Authorization: Basic …` z podanym użytkownikiem i hasłem |
| **Bearer** | `Authorization: Bearer <token>` |
| **Własny nagłówek** | Nagłówek o podanej nazwie i wartości, np. `X-Api-Key` |

Własny nagłówek nie może nadpisywać nagłówków technicznych (`Host`, `Content-Type`, `Content-Length`, `Connection`, `User-Agent`, `Transfer-Encoding` ani nagłówków `X-Reklamator-*`). Hasła i tokeny są przechowywane w postaci zaszyfrowanej i nie są nigdy wyświetlane po zapisaniu.

Slack, Google Chat i Teams nie używają uwierzytelnienia ani podpisu — token jest częścią adresu.

## Szablon wiadomości

Treść wysyłana webhookiem to szablon typu **Webhook**. Przy tworzeniu szablonu wybierz **Szablony startowe** — są gotowe wzorce dla każdego rodzaju (ogólny JSON, Slack, Google Chat, Teams).

Przykład dla Google Chat lub Slacka:

```json
{"text": {{ ("Nowe zgłoszenie " ~ issue_internal_number ~ " (" ~ issue_type_name ~ ")")|json }}}
```

Zasady pisania szablonu webhooka opisuje rozdział [Szablony → Szablon webhooka](/config/templates#szablon-webhooka).

## Test webhooka

Z menu wiersza na liście wybierz **Wyślij test**. Możesz wysłać:

- **przykładowe dane** — bez wybierania szablonu, żeby sprawdzić sam adres i uwierzytelnienie,
- **szablon na wybranym zgłoszeniu** — wybierz szablon webhooka i wpisz numer zgłoszenia; zobaczysz dokładnie to, co wyśle reguła.

Wynik pokazuje się od razu: status, kod odpowiedzi odbiorcy, czas i treść odpowiedzi. Jeśli szablon nie daje poprawnego JSON-a, test od razu to zgłosi. Testy nie wpływają na licznik błędów webhooka.

## Dostawy i ponowienia

Każde wywołanie reguły to **dostawa**. Lista dostaw webhooka jest dostępna z menu wiersza (**Dostawy**) — widać tam status, zdarzenie, liczbę prób, ostatni kod odpowiedzi i wysłane dane.

| Status | Znaczenie |
|---|---|
| Oczekuje | Dostawa w kolejce lub czeka na ponowienie |
| Dostarczono | Odbiorca odpowiedział kodem 2xx |
| Błąd | Wszystkie próby nieudane albo odbiorca odrzucił żądanie |
| Anulowano | Webhook został wyłączony przed wysyłką |

**Ponowienia.** Jeśli odbiorca jest chwilowo niedostępny (brak połączenia, przekroczony czas 10 s, kod 408, 425, 429 lub 5xx), Reklamator ponawia wysyłkę z rosnącym odstępem: po ok. 5 s, 25 s, 2 min i 10 min — łącznie do 5 prób. Inne kody 4xx oraz przekierowania (3xx) kończą dostawę bez ponawiania, bo zwykle oznaczają błąd konfiguracji.

**Wyślij ponownie** na liście dostaw wysyła te same dane jeszcze raz jako nową dostawę — np. po naprawie po stronie odbiorcy. Nie działa dla wyłączonego webhooka.

Dostawy są przechowywane przez 30 dni.

### Automatyczne wyłączenie

Po **20 kolejnych** dostawach zakończonych błędem webhook wyłącza się automatycznie i dostaje oznaczenie **Wyłączony automatycznie**. W logu systemowym pojawia się wtedy wpis `WEBHOOK_AUTO_DISABLED`. Po naprawie po stronie odbiorcy włącz webhook w edycji — licznik błędów zeruje się.

## Log systemowy

Każda próba wysyłki trafia do [logu systemowego](/logs/system) w module **WEBHOOK**: udana jako **INFO**, nieudana jako **ERROR**. Wpis zawiera nazwę webhooka, zdarzenie, numer próby, kod i czas odpowiedzi oraz fragment odpowiedzi odbiorcy.

Do logu trafiają też błędy wykryte przed wysyłką, np. `WEBHOOK_INVALID_PAYLOAD` — szablon nie wygenerował poprawnego JSON-a dla danego zgłoszenia.

## Dla integratorów (webhook ogólny)

Żądanie wysyłane przez Reklamator:

| Element | Wartość |
|---|---|
| Metoda | `POST` |
| `Content-Type` | `application/json; charset=utf-8` |
| `User-Agent` | `Reklamator-Webhook/1.0` |
| `X-Reklamator-Event` | Zdarzenie reguły, np. `ISSUE_CREATE`, `ISSUE_CHANGE_STEP` (`TEST` dla testu) |
| `X-Reklamator-Delivery` | Identyfikator dostawy — ten sam przy każdym ponowieniu; użyj go do odrzucania duplikatów |
| `X-Reklamator-Timestamp` | Czas wysłania próby (sekundy od 1970-01-01 UTC) |
| `X-Reklamator-Signature` | `v1=<HMAC-SHA256>` — tylko gdy webhook ma sekret podpisu |
| Treść | Wyrenderowany szablon webhooka (maks. 256 KB) |

Podpis to HMAC-SHA256 z sekretu webhooka liczony z tekstu `<timestamp>.<treść>`, zapisany szesnastkowo. Weryfikacja po stronie odbiorcy (Python):

```python
import hashlib, hmac, time

def is_valid(secret: str, timestamp: str, body: bytes, signature: str) -> bool:
    if abs(time.time() - int(timestamp)) > 300:
        return False
    expected = 'v1=' + hmac.new(secret.encode(), f'{timestamp}.'.encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
```

Licz podpis z **surowej** treści żądania, przed parsowaniem JSON. Odpowiedz kodem 2xx możliwie szybko — długie przetwarzanie przenieś do własnej kolejki.

Sekret można wymienić z menu wiersza (**Wygeneruj nowy sekret**). Stary sekret przestaje działać natychmiast, więc zaktualizuj go u odbiorcy.

---

## FAQ

### Czy mogę wysyłać do kilku kanałów jednocześnie?
Tak. Dodaj osobny webhook dla każdego kanału i dodaj w regule kilka akcji **Wysyłanie webhooka**.

### Czy jeden szablon może służyć wielu webhookom?
Tak. Szablon i webhook są niezależne — wybierasz je osobno w akcji reguły.

### Dlaczego nie widzę pełnego adresu webhooka?
Adresy Slacka, Google Chat i Teams zawierają tajny token, dlatego są przechowywane w postaci zaszyfrowanej i nie są wyświetlane. Aby zmienić adres, wpisz nowy w edycji webhooka.

### Webhook nie dochodzi — gdzie szukać przyczyny?
Sprawdź listę **Dostawy** webhooka i [log systemowy](/logs/system) (moduł WEBHOOK). Brak dostawy przy błędzie `WEBHOOK_INVALID_PAYLOAD` oznacza błąd w szablonie — sprawdź go przyciskiem **Wyślij test** na tym samym zgłoszeniu.

### Czy mogę usunąć webhook używany w regule?
Nie. Najpierw usuń go z akcji reguły biznesowej. Webhook można też wyłączyć bez usuwania.

### Czy odbiorca może dostać tę samą wiadomość dwa razy?
Rzadko — np. gdy odbiorca przyjął żądanie, ale odpowiedź nie dotarła do Reklamatora. Każde ponowienie ma ten sam nagłówek `X-Reklamator-Delivery`, po którym odbiorca może odrzucić duplikat.
