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.
- 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#
A webhook URL-t a PUT /v1/webhooks/config végponton tudod regisztrálni. Ehhez webhook.manage capability szükséges.
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ány | Példák |
|---|---|
| Loopback | localhost, 127.0.0.1, ::1, 0.0.0.0 |
| Privát hálózat | 10.x.x.x, 172.16-31.x.x, 192.168.x.x |
| Link-local | 169.254.x.x |
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ény | Leírás |
|---|---|
booking.requested | New booking received |
booking.confirmed | Booking confirmed |
booking.declined | Booking declined |
booking.cancelled | Booking cancelled |
booking.reschedule_proposed | Appointment modification proposed |
booking.reschedule_confirmed | Modified appointment confirmed |
booking.completed | Booking completed |
booking.no_show | Guest did not show up |
| Esemény | Leírás |
|---|---|
booking.requested | Új foglalás érkezett |
booking.confirmed | Foglalás megerősítve |
booking.declined | Foglalás elutasítva |
booking.cancelled | Foglalás lemondva |
booking.reschedule_proposed | Időpont-módosítás javasolva |
booking.reschedule_confirmed | Módosított időpont megerősítve |
booking.completed | Foglalás teljesítve |
booking.no_show | Vendég nem jelent meg |
Payload formátum#
Minden webhook kézbesítés egy JSON objektum a következő struktúrával:
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 -->
{
"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 enum | Webhook esemény |
|---|---|
requested | booking.requested (foglalás létrejött) |
confirmed | booking.confirmed, booking.reschedule_confirmed (ha átütemezés után erősítik meg) |
declined | booking.declined |
cancelled | booking.cancelled |
rescheduleProposed | booking.reschedule_proposed |
completed | booking.completed |
noShow | booking.no_show |
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éc | Leírás |
|---|---|
X-Bokko-Signature | sha256=<hex> — HMAC-SHA256 aláírás a body felett |
X-Bokko-Delivery-Id | UUID — deduplikációs kulcs |
X-Bokko-Event | Az esemény neve (pl. booking.confirmed) |
X-Bokko-Timestamp | ISO 8601 időbélyeg |
Aláírás ellenőrzés#
Node.js#
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#
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áma | 1 (nincs újrapróbálkozás) |
| Timeout | 8 másodperc |
| Redirect követés | Nem |
| Kézbesítési garancia | At-most-once |
Lehetséges kimenetek:
success— 2xx válaszkód érkezetttimeout— a végpont nem válaszolt 8 másodpercen belülnetwork_error— a végpont nem volt elérhetőhttp_error— nem 2xx válaszkód (pl. 500)
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éter | Leírás |
|---|---|
event | Eseménytípus szűrő (pl. booking.confirmed) |
outcome | Kimenet szűrő (success, timeout, network_error, http_error) |
from / to | Dá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:
curl -X POST https://api.bokko.io/v1/webhooks/config/rotate-secret \
-H "Authorization: Bearer {API_KEY}"Legjobb gyakorlatok#
- Deduplikálj
deliveryIdalapján — bár at-most-once a garancia, hálózati anomáliák esetén érdemes ellenőrizni - Válaszolj gyorsan 200-zal, a tényleges feldolgozást aszinkron végezd — a 8 másodperces timeout szoros lehet összetett logikánál
- Periodikusan egyeztesd a
GET /v1/bookingsvégponttal, hogy ne maradj le eseményekről - Helyi fejlesztéshez használj webhook.site-ot vagy ngrok-ot a webhook fogadásához