Documentation menu

Wychodzące webhooki

Webhooki wysyłają zdarzenia Manisma do publicznego endpointu HTTPS Twojej organizacji.

Konfiguracja endpointu

Otwórz jako Admin Zarządzanie → Połączenia, utwórz endpoint i wybierz nazwę, URL oraz zdarzenia. Secret podpisujący jest wyświetlany tylko raz. Przechowuj go bezpiecznie. Po rotacji nowy secret obowiązuje od momentu zapisu.

URL musi:

  • używać HTTPS;
  • być publicznie dostępny przez DNS;
  • używać portu 443 lub 8443;
  • nie zawierać nazwy użytkownika/hasła w URL;
  • nie wskazywać na localhost, prywatne IP, link-local ani metadane chmury.

Użyj Test, aby wysłać ping przed aktywacją rzeczywistych zdarzeń.

Zdarzenia

Zdarzenie Wyzwalacz
ping Ręczny test endpointu.
client.created Klient utworzony.
client.updated Klient zmieniony.
job.created Zlecenie utworzone.
job.planned Status zlecenia zmieniony na zaplanowane.
job.completed Status zlecenia zmieniony na zakończone.
job.cancelled Status zlecenia zmieniony na anulowane.
approval.approved Klient zaakceptował propozycję.
approval.declined Klient odrzucił propozycję.
workorder.completed Dane zlecenia pracy gotowe do fakturowania przy zakończeniu.

Zmiana innego pola już zakończonego zlecenia nie wysyła ponownie job.completed; musi zmienić się sam status.

Envelope i nagłówki

{
  "event": "job.completed",
  "version": 1,
  "tenant_id": "tenant-uuid",
  "occurred_at": "2026-07-13T09:15:00.000Z",
  "data": {}
}

Nagłówki:

  • X-Manisma-Event: nazwa zdarzenia;
  • X-Manisma-Delivery: stabilne id tej logicznej dostawy;
  • X-Manisma-Signature: sha256=<hex HMAC-SHA256> dla dokładnej surowej treści.

Zweryfikuj HMAC przed parsowaniem JSON i używaj porównania bezpiecznego czasowo:

import { createHmac, timingSafeEqual } from 'node:crypto'

export function verify(rawBody, header, secret) {
  if (!header?.startsWith('sha256=')) return false
  const expected = createHmac('sha256', secret).update(rawBody).digest('hex')
  const supplied = header.slice(7)
  const a = Buffer.from(expected, 'hex')
  const b = Buffer.from(supplied, 'hex')
  return a.length === b.length && timingSafeEqual(a, b)
}

Payloady

Zdarzenia klienta zawierają id, customer_number, name, client_type, email i phone. Wewnętrzne notatki klienta są pomijane.

Zdarzenia zlecenia zawierają id/numer zlecenia, tytuł, status, priorytet, planowanie oraz zwięzłe obiekty dla klienta, adresu serwisowego i technika głównego. Nieprzypisane zlecenie lub zlecenie bez adresu używa null.

Zdarzenia akceptacji zawierają id akceptacji, job_id, status, wybrany termin i czas odpowiedzi. chosen_slot może być stringiem JSON lub starszym dowolnym tekstem; parsuj defensywnie.

workorder.completed zawiera:

  • zwięzłe zlecenie i klienta;
  • najnowszą zakończoną wizytę, jeśli dostępna;
  • użyte materiały ze SKU, ceną sprzedaży, ilością i kwotą pozycji;
  • czas pracy;
  • suma materiałów w EUR.

Cena materiału to cena sprzedaży w momencie budowania payloadu webhooka, niekoniecznie historycznie przypięta cena.

Dostarczanie i retry

Webhooki są at least once. Uczyń swój odbiornik idempotentnym po `X-Manisma-Delivery**. Pomyślne odebranie to każda odpowiedź 2xx. Przekierowania nie są śledzone, a każda próba ma timeout 10 sekund.

Przy błędzie tymczasowym jest maksymalnie trzy próby: natychmiast, po 60 sekundach i ponownie po 300 sekundach. To samo delivery-id zostaje zachowane. Retry działają obecnie w procesie usługi i nie przeżywają redeploy; sprawdzaj również log dostarczania w Połączenia pod kątem pozostałych wpisów pending.

Najpierw zapisz delivery-id w tej samej transakcji co przetwarzanie, a następnie szybko odpowiedz 2xx. Wolne przetwarzanie przenieś do własnej kolejki.