# Webhooks Il-webhooks jibagħtu l-events lis-sistema tiegħek hekk kif iseħħu, għalhekk m'għandekx bżonn tagħmel polling tal-API. ## Events | Event | Meta | |---|---| | `booking.created` | Inħoloq booking (dashboard, importazzjoni minn kanal jew API) | | `booking.updated` | Inbidlu d-dati, il-mistednin, il-ħinijiet tal-check-in/out jew id-dettalji ta' kuntatt | | `booking.cancelled` | Booking ġie kkanċellat | | `checkin.completed` | Il-mistieden temm (jew aġġorna) il-check-in online | | `payment.completed` | It-taxxa tat-turisti tħallset jew id-depożitu nżamm/tħallas (anke meta l-istaff jimmarkah bħala mħallas) | | `booking.unlocked` | Il-passi kollha lesti — il-gwida tas-soġġorn hija miftuħa | | `extras.ordered` | Il-mistieden ħallas għal extras — anke early check-in jew late check-out | | `message.sent` | Intbagħat messaġġ lill-mistieden permezz tal-kanal tal-booking (Airbnb, Booking.com … permezz ta' Hostaway jew Channex) | | `feedback.received` | Il-mistieden ta rating lis-soġġorn (1–5) fil-paġna tal-feedback wara talba għal reviżjoni | | `ping` | Event tat-test mill-buttuna **Test** | ### X'fih `data` | Event | Oqsma ta' `data` | |---|---| | `booking.created`, `booking.updated`, `booking.cancelled` | `bookingId`, `ref`, `source` (importazzjonijiet mill-kanali); `reason: "stay-times"` meta early check-in / late check-out mixtri ċaqlaq il-ħinijiet | | `checkin.completed` | `bookingId`, `ref` | | `payment.completed` | `bookingId`, `leg` (`eco` jew `deposit`), `status` (`paid` jew `held`), `manual: true` meta l-istaff immarkah bħala mħallas | | `booking.unlocked` | `bookingId` | | `extras.ordered` | `bookingId`, `leg: "extras"`, `status: "paid"` | | `message.sent` | `bookingId`, `ref`, `via` (eż. `Hostaway`) | | `feedback.received` | `bookingId`, `ref`, `rating` (1–5) | Il-verżjoni li tinqara mill-magni ta' kull event — headers, body u `data` — tinsab fit-taqsima `webhooks` tad-[dokument OpenAPI](/api/v1/openapi.json) u fir-[referenza tal-API](/api/docs#webhooks). ## Żid webhook **Settings → Webhooks**: daħħal URL `https://`, immarka l-events li trid (xejn = kollha) u kklikkja **Add webhook**. Is-**signing secret** jintwera darba biss — aħżnu mar-receiver tiegħek. ![Settings → Webhooks](/site/img/docs/d-settings-webhooks.webp "Settings → Webhooks") ## It-talba `POST` b'body JSON: ``` { "id": "evt_…", "event": "payment.completed", "createdAt": "2026-11-18T14:03:11.000Z", "tenant": "t_…", "data": { "bookingId": "b_…", "leg": "eco", "status": "paid" } } ``` Headers: | Header | Kontenut | |---|---| | `X-GP-Event` | l-isem tal-event | | `X-GP-Delivery` | ID uniku tal-konsenja | | `X-GP-Timestamp` | ħin Unix f'sekondi | | `X-GP-Signature` | `v1=` + HMAC-SHA256 f'hex ta' `.` bis-signing secret tiegħek | ## Ivverifika l-firma (Node.js) ``` const crypto = require('crypto'); function verify(rawBody, headers, secret) { const ts = headers['x-gp-timestamp']; const expected = 'v1=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex'); const given = String(headers['x-gp-signature'] || ''); const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300; return fresh && given.length === expected.length && crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected)); } ``` Dejjem ivverifika kontra l-body **mhux ipproċessat** (raw) tat-talba, u irrifjuta timestamps qodma biex timblokka replays. ## Ivverifika l-firma (C# / .NET) ``` using System.Security.Cryptography; using System.Text; static bool Verify(string rawBody, string ts, string signature, string secret) { if (!long.TryParse(ts, out var t) || Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - t) > 300) return false; using var h = new HMACSHA256(Encoding.UTF8.GetBytes(secret)); var hex = Convert.ToHexString(h.ComputeHash(Encoding.UTF8.GetBytes(ts + "." + rawBody))).ToLowerInvariant(); return CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes("v1=" + hex), Encoding.ASCII.GetBytes(signature ?? "")); } ``` Fuq .NET Framework uża `BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant()` minflok `Convert.ToHexString`, u qabbel f'ħin kostanti b'loop sempliċi. ## Ivverifika l-firma (PHP) ``` $expected = 'v1=' . hash_hmac('sha256', $_SERVER['HTTP_X_GP_TIMESTAMP'] . '.' . file_get_contents('php://input'), $secret); $ok = abs(time() - (int)$_SERVER['HTTP_X_GP_TIMESTAMP']) < 300 && hash_equals($expected, $_SERVER['HTTP_X_GP_SIGNATURE'] ?? ''); ``` ## Konsenja u tentattivi mill-ġdid Wieġeb bi kwalunkwe status 2xx fi żmien 10 sekondi. Il-konsenji li jfallu jerġgħu jiġu ppruvati wara 30 sekonda u wara 5 minuti (tliet tentattivi b'kollox). **Recent deliveries** juri l-aħħar 200 tentattiv bir-riżultat tagħhom. - `id` fil-body u l-header `X-GP-Delivery` jibqgħu l-istess f'kull tentattiv mill-ġdid — aħżnu u injora d-duplikati. - L-events jistgħu jaslu f'ordni differenti; uża `createdAt`, u ġib il-booking għall-istat attwali. - Ir-redirects ma jiġux segwiti, u jiġu kkuntattjati biss indirizzi pubbliċi `https://` (l-ebda netwerk privat jew lokali). - It-talbiet jaslu b'`Content-Type: application/json` u `User-Agent: GuestPortal-Webhooks/1`. ## Mistoqsijiet frekwenti ### Nirċievi l-booking sħiħ fl-event? L-event iġorr l-IDs u l-bidla. Ġib il-booking sħiħ b'`GET /api/v1/bookings/{id}` b'API key — b'hekk l-ebda data personali ma tivvjaġġa fil-bodies tal-webhooks. ### Il-kanali jistgħu jibagħtu webhooks lil Guestbud? Iva — dik hija d-direzzjoni l-oħra. Hostaway u Channex jistgħu jgħarrfu lil Guestbud minnufih dwar riżervazzjonijiet ġodda u mibdula; ara [Hostaway](/docs/connect-hostaway) u [Channex](/docs/connect-channex). Dawk l-indirizzi li jirċievu huma sigrieti għal kull kumpanija u jqanqlu biss importazzjoni ġdida ta' dik ir-riżervazzjoni. ### Jintbagħtu webhooks mill-kont demo? Le.