- Áttekintés
- Discover — Szolgáltatások és munkatársak
- Szolgáltatások listázása (GET /services)
- Munkatársak listázása (GET /staff)
- Plan — Szabad időpontok keresése (POST /availability/search)
- Request body mezők
- Response mezők és időzóna semantika
- Truncation és suppression
- Hibák
- Reserve — Foglalás létrehozása (POST /bookings)
- Idempotency-Key
- Foglalás státuszok (state machine)
- Lifecycle figyelése
- Webhook-első megközelítés (ajánlott)
- Foglalások listázása (GET /bookings)
- Polling fallback
- Cancel — Foglalás lemondása (POST /bookings/{bookingId}/cancel)
- Hibák a flow során
- Retry stratégia
- Best practices
Foglalási flow
A foglalási folyamat end-to-end integrálása — service discovery, availability, foglalás létrehozása, lifecycle figyelése, lemondás.
Áttekintés#
A Bokko foglalási folyamat 5 fázisból áll:
- Discover — elérhető szolgáltatások és munkatársak lekérdezése
- Plan — szabad időpontok keresése adott dátumtartományra
- Reserve — foglalás létrehozása
- Lifecycle — foglalás státuszának figyelése (webhook vagy polling)
- Cancel — foglalás lemondása, ha szükséges
Discover — Szolgáltatások és munkatársak#
Szolgáltatások listázása (GET /services)#
curl -X GET "https://api.bokko.io/v1/services?salonSlug=pelda-uzlet&locationSlug=belvaros" \
-H "Authorization: Bearer bk_live_..."Visszaadja az összes aktív, online foglalható szolgáltatást az adott telephelyen. A serviceId értékre az availability search-ben és a foglalás létrehozásakor lesz szükséged.
Munkatársak listázása (GET /staff)#
curl -X GET "https://api.bokko.io/v1/staff?salonSlug=pelda-uzlet&locationSlug=belvaros" \
-H "Authorization: Bearer bk_live_..."Az availability search response-ban a slots[].staffId megjelöli, melyik munkatárs végzi a szolgáltatást — ezt a GET /staff válasz alapján tudod megjeleníteni.
Plan — Szabad időpontok keresése (POST /availability/search)#
Request body mezők#
| Mező | Típus | Leírás |
|---|---|---|
salonSlug | string (kötelező) | A szolgáltató üzletének azonosítója |
locationSlug | string (kötelező) | A telephely azonosítója |
serviceId | string (kötelező) | A keresett szolgáltatás azonosítója |
staffId | string (opcionális) | Ha megadod, csak az adott munkatárs slotjai jelennek meg |
dateRange.from | YYYY-MM-DD (kötelező) | Keresési időszak kezdete (üzlet helyi időzóna) |
dateRange.to | YYYY-MM-DD (kötelező) | Keresési időszak vége — inclusive, max 31 nappal a from után |
curl -X POST "https://api.bokko.io/v1/availability/search" \
-H "Authorization: Bearer bk_live_..." \
-H "Content-Type: application/json" \
-d '{
"salonSlug": "pelda-uzlet",
"locationSlug": "belvaros",
"serviceId": "svc_haircut_01",
"staffId": "staff_anna_01",
"dateRange": {
"from": "2026-05-12",
"to": "2026-05-18"
}
}'Response mezők és időzóna semantika#
Request/propose fázis — üzlet helyi időzóna:
slots[].date—YYYY-MM-DDaz üzlet helyi időzónájában (nem UTC)slots[].startTime—HH:MMüzlet-local wall-clock időslots[].endTime—HH:MMüzlet-local wall-clock időslots[].serviceId,slots[].staffId— azonosítók
UTC timestamp:
snapshotAt— UTC ISO 8601 timestamp (a snapshot kibocsátásának pillanata)
Confirmed lifecycle — UTC ISO 8601: A foglalás metaadatai (createdAt, updatedAt) UTC ISO 8601 formátumban érkeznek.
Confirmed lifecycle — Üzlet helyi időzóna: A megerősített időpont (confirmedSlot.date, startTime, endTime) szintén az üzlet helyi időzónájában érkezik, megegyezve az availability search formátumával. Így a megjelenítéshez nincs szükség bonyolult időzóna-konverzióra.
Megjegyzés a confirmedSlot-ról: A confirmedSlot mező az aktív, megerősített jellegű életciklus-állapotokban van kitöltve, például confirmed, completed és noShow esetén. cancelled vagy declined státuszú foglalásoknál a confirmedSlot az API-ban mindig null, akkor is, ha a foglalás korábban már meg volt erősítve. A status mező alapján dől el, hogy az időpont jelenleg foglalt-e.
Truncation és suppression#
Ha a keresés 500-nál több slotot adna vissza, a válasz csonkul:
meta.truncated: truejelzi a csonkítástmeta.returnedSlots— ténylegesen visszaadott slotok számameta.slotLimit— a csonkítási határ (500)
Ha az online foglalás ki van kapcsolva az üzletnél:
meta.availabilitySuppressed: truedata.slotsüres tömb
Hibák#
availability.date_range_too_wide(400) — adateRangeszélesebb 31 napnál
Reserve — Foglalás létrehozása (POST /bookings)#
Idempotency-Key#
Minden foglalás-létrehozási kéréshez RFC 4122 UUID v1–v5 formátumú Idempotency-Key header szükséges. Az idempotency ablak 24 óra.
Az UUID-t egyszer generáld shell változóba. Retry esetén pontosan ugyanezt a kulcsot küldd:
IDEMPOTENCY_KEY="$(uuidgen)"
curl -X POST "https://api.bokko.io/v1/bookings" \
-H "Authorization: Bearer bk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
-d '{
"salonSlug": "pelda-uzlet",
"locationSlug": "belvaros",
"serviceId": "svc_haircut_01",
"expectedPricingVersion": "a1b2c3d4e5f6",
"staffId": "staff_anna_01",
"slot": {
"date": "2026-05-12",
"startTime": "10:00"
},
"guest": {
"name": "Teszt Vendég",
"phone": "+36301234567"
}
}'Foglalás státuszok (state machine)#
| Státusz | Leírás |
|---|---|
requested | Létrehozva, vár a megerősítésre |
confirmed | Megerősítve a szolgáltató által |
declined | Elutasítva |
rescheduleProposed | Átütemezési javaslat érkezett |
cancelled | Lemondva |
completed | Teljesítve |
noShow | Vendég nem jelent meg |
Lifecycle figyelése#
Webhook-első megközelítés (ajánlott)#
Állíts be webhookot a PUT /webhooks/config endpointon — értesítést kapsz minden foglalásváltozásnál.
A 8 webhook event:
booking.requestedbooking.confirmedbooking.declinedbooking.cancelledbooking.reschedule_proposedbooking.reschedule_confirmedbooking.completedbooking.no_show
Minden event X-Bokko-Signature: sha256=<hex> fejléccel érkezik HMAC-SHA256 aláírással — ellenőrizd a hitelesség megállapításához. Részletes leírás: Webhooks →
Foglalások listázása (GET /bookings)#
Ha több foglalás állapotát szeretnéd egyszerre szinkronizálni:
curl -X GET "https://api.bokko.io/v1/bookings?salonSlug=pelda-uzlet&locationSlug=belvaros&status=confirmed&from=2026-05-12&to=2026-05-18" \
-H "Authorization: Bearer bk_live_..."Szűrési paraméterek:
status(opcionális): Csak az adott állapotú foglalások.locationSlug(opcionális): Szűrés telephelyre.fromésto(opcionális, párban): Időintervallum szűrés a foglalás napja alapján.
Polling fallback#
Ha webhook nem áll rendelkezésre, lekérdezheted a foglalás állapotát:
curl -X GET "https://api.bokko.io/v1/bookings/{bookingId}?salonSlug=pelda-uzlet" \
-H "Authorization: Bearer bk_live_..."Cancel — Foglalás lemondása (POST /bookings/{bookingId}/cancel)#
IDEMPOTENCY_KEY="$(uuidgen)"
curl -X POST "https://api.bokko.io/v1/bookings/{bookingId}/cancel?salonSlug=pelda-uzlet" \
-H "Authorization: Bearer bk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${IDEMPOTENCY_KEY}"A lemondás idempotens: ha a foglalás már cancelled státuszban van, a kérés 409 booking.invalid_transition hibával tér vissza — ez nem valódi hiba, a cancel sikeresen megtörtént.
Hibák a flow során#
| Kód | HTTP | Mikor fordul elő |
|---|---|---|
booking.slot_unavailable | 409 | A kért időpont már nem elérhető |
booking.service_pricing_changed | 409 | Az ár változott az availability search és a foglalás között |
idempotency.payload_mismatch | 409 | Azonos Idempotency-Key, eltérő payload |
idempotency.request_in_progress | 503 | A kérés feldolgozása még folyamatban van (retryable) |
auth.plan_insufficient | 403 | A kulcshoz tartozó szolgáltatói üzletnek nincs Pro előfizetése |
Retry stratégia#
idempotency.request_in_progress(503) — retryable: igen, ugyanolyan Idempotency-Key-jelbooking.slot_unavailable(409) — retryable: nem; keress új időpontotbooking.service_pricing_changed(409) — retryable: nem; kérd le újra a szolgáltatáslistát
Best practices#
- Idempotency-Key shell változóba generáld, ne inline — retry alatt ne változzon
- Webhook-elsőbbség: polling csak fallbackként; valós idejű értesítésekhez webhookot használj
- Időzóna: az availability slot
date/startTime/endTimeüzlet-local; aconfirmedAtés hasonló lifecycle mezők UTC — ne keverd össze - Slot freshness: az availability snapshot gyorsan elavulhat; a foglalás előtt ne tárold cache-ben 30 másodpercnél tovább