Docs
Ctrl+K

Webhooks

Valós idejű értesítések booking eseményekről, HMAC-SHA256 aláírás ellenőrzés.

Áttekintés#

A Bokko webhook rendszer valós idejű HTTP értesítéseket küld, amikor egy foglalás állapota megváltozik. Így a te rendszered azonnal reagálhat az eseményekre anélkül, hogy folyamatosan polloznia kellene az API-t.

Tipp
A webhookok konfigurálásához és használatához Bokko Pro előfizetés szükséges.
  • Valós idejű: az értesítés a státuszváltás pillanatában kiküldésre kerül
  • HTTPS: csak biztonságos végpontra küldhető webhook
  • HMAC-SHA256 aláírás: minden payload kriptográfiailag aláírt, ellenőrizheted a hitelességét

Beállítás#

Tipp
A webhook konfigurációt a dashboardon is kezelheted (URL beállítása, secret rotálás, aktiválás/deaktiválás). Részletes UI útmutató: Help: Webhook konfiguráció.

A webhook URL-t a PUT /v1/webhooks/config végponton tudod regisztrálni. Ehhez webhook.manage capability szükséges.

bash
curl -X PUT https://api.bokko.io/v1/webhooks/config \
  -H "Authorization: Bearer {API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/webhooks/bokko" }'

URL követelmények:

  • Kötelezően HTTPS protokoll
  • Maximum 500 karakter hosszú
  • Nem tartalmazhat hitelesítő adatokat (user:pass@)

Tiltott címtartományok:

TartományPéldák
Loopbacklocalhost, 127.0.0.1, ::1, 0.0.0.0
Privát hálózat10.x.x.x, 172.16-31.x.x, 192.168.x.x
Link-local169.254.x.x
Tipp
Az első PUT híváskor a rendszer automatikusan generál egy HMAC secretet (32 byte = 64 hex karakter). Ez a secret egyszer kerül visszaadásra a válaszban — mentsd el biztonságos helyre! Későbbi PUT hívások nem adják vissza újra.

Események#

EseményLeírás
booking.requestedNew booking received
booking.confirmedBooking confirmed
booking.declinedBooking declined
booking.cancelledBooking cancelled
booking.reschedule_proposedAppointment modification proposed
booking.reschedule_confirmedModified appointment confirmed
booking.completedBooking completed
booking.no_showGuest did not show up
EseményLeírás
booking.requestedÚj foglalás érkezett
booking.confirmedFoglalás megerősítve
booking.declinedFoglalás elutasítva
booking.cancelledFoglalás lemondva
booking.reschedule_proposedIdőpont-módosítás javasolva
booking.reschedule_confirmedMódosított időpont megerősítve
booking.completedFoglalás teljesítve
booking.no_showVendég nem jelent meg

Payload formátum#

Minden webhook kézbesítés egy JSON objektum a következő struktúrával:

Info
A deliveryId formátuma eseménytípusonként eltér: booking.requested eseménynél determinisztikus 32-karakteres hex string (receiver-oldali deduplikációhoz), minden más eseménynél UUID v4. Mindkét alak biztonságosan használható map kulcsként és HTTP fejléc értékeként.

<!-- doc-example: webhook-payload -->

json
{
  "event": "booking.confirmed",
  "deliveryId": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-04-01T09:00:00.000Z",
  "salonSlug": "precision-cuts",
  "booking": {
    "bookingId": "abc123",
    "publicReference": "BK-A2B3C4D5",
    "status": "confirmed",
    "serviceId": "svc_haircut_01",
    "serviceName": "Hajvágás",
    "staffId": "staff_anna_01",
    "staffName": "Anna",
    "guestName": "Kiss Péter",
    "requestedSlot": {
      "date": "2026-04-05",
      "startTime": "10:00",
      "timezone": "Europe/Budapest"
    },
    "confirmedSlot": {
      "date": "2026-04-05",
      "startTime": "10:00",
      "endTime": "10:45",
      "timezone": "Europe/Budapest"
    },
    "note": null,
    "createdAt": "2026-04-01T09:00:00Z",
    "updatedAt": "2026-04-01T09:15:00Z"
  }
}

A confirmedSlot a véglegesített időpontot tartalmazza, ha ilyen létezik a foglaláshoz (pl. confirmed, completed vagy noShow státuszban). cancelled vagy declined státuszú foglalásoknál ez az érték mindig null az API válaszban, még akkor is, ha a foglalás korábban meg volt erősítve. Ez azt tükrözi, hogy az időpont már nem foglalt.

Status enum ↔ eseménynév leképezés#

A foglalás status mezője camelCase enum-ot használ (Bokko Public API konvenció), míg a webhook eseménynevei snake_case névteres formátumot (REST / event sourcing konvenció). A kettő szándékosan eltér egymástól — klienseknek az alábbi leképezést kell alkalmazni:

BookingStatus enumWebhook esemény
requestedbooking.requested (foglalás létrejött)
confirmedbooking.confirmed, booking.reschedule_confirmed (ha átütemezés után erősítik meg)
declinedbooking.declined
cancelledbooking.cancelled
rescheduleProposedbooking.reschedule_proposed
completedbooking.completed
noShowbooking.no_show
Info
A booking.no_show esemény neve snake_case-ben szerepel (no_show), nem camelCase-ben (noShow). A Booking schema status mezője viszont camelCase-t használ (noShow, rescheduleProposed). Ez az eltérés szándékos design döntés.

HTTP fejlécek#

Minden webhook kérés az alábbi egyedi fejléceket tartalmazza:

FejlécLeírás
X-Bokko-Signaturesha256=<hex> — HMAC-SHA256 aláírás a body felett
X-Bokko-Delivery-IdUUID — deduplikációs kulcs
X-Bokko-EventAz esemény neve (pl. booking.confirmed)
X-Bokko-TimestampISO 8601 időbélyeg

Aláírás ellenőrzés#

Figyelmeztetés
Mindig ellenőrizd az aláírást a payload feldolgozása előtt! Timing-safe összehasonlítást használj, hogy elkerüld a timing attack-eket.

Node.js#

javascript
const crypto = require('crypto');

function verifySignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('hex');

  const sig = signature.replace('sha256=', '');

  return crypto.timingSafeEqual(
    Buffer.from(sig, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

Python#

python
import hmac
import hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()

    sig = signature.replace('sha256=', '')

    return hmac.compare_digest(sig, expected)

Kézbesítési szabályok#

SzabályÉrték
Kísérletek száma1 (nincs újrapróbálkozás)
Timeout8 másodperc
Redirect követésNem
Kézbesítési garanciaAt-most-once

Lehetséges kimenetek:

  • success — 2xx válaszkód érkezett
  • timeout — a végpont nem válaszolt 8 másodpercen belül
  • network_error — a végpont nem volt elérhető
  • http_error — nem 2xx válaszkód (pl. 500)
Tipp
Mivel nincs automatikus újrapróbálkozás, érdemes a kézbesítési naplóból figyelni a sikertelen kézbesítéseket, és szükség esetén a GET /v1/bookings végponttal szinkronizálni.

Kézbesítési napló#

A GET /v1/webhooks/deliveries végponton visszanézheted az elmúlt 90 nap kézbesítéseit.

Szűrési lehetőségek:

ParaméterLeírás
eventEseménytípus szűrő (pl. booking.confirmed)
outcomeKimenet szűrő (success, timeout, network_error, http_error)
from / toDátumtartomány (ISO 8601)

A lapozás cursor-alapú: a válasz meta.cursor mezőjét add meg a következő kérés cursor paraméterében.

Secret rotálás#

Ha a secreted kompromittálódott, új secretet generálhatsz:

bash
curl -X POST https://api.bokko.io/v1/webhooks/config/rotate-secret \
  -H "Authorization: Bearer {API_KEY}"
Figyelmeztetés
A rotálás azonnal érvényteleníti a régi secretet. Az új secret egyszer kerül visszaadásra a válaszban — mentsd el azonnal. A rotálás után az összes bejövő webhook az új secrettel lesz aláírva.

Legjobb gyakorlatok#

  1. Deduplikálj deliveryId alapján — bár at-most-once a garancia, hálózati anomáliák esetén érdemes ellenőrizni
  2. Válaszolj gyorsan 200-zal, a tényleges feldolgozást aszinkron végezd — a 8 másodperces timeout szoros lehet összetett logikánál
  3. Periodikusan egyeztesd a GET /v1/bookings végponttal, hogy ne maradj le eseményekről
  4. Helyi fejlesztéshez használj webhook.site-ot vagy ngrok-ot a webhook fogadásához