Skip to main content

Events & Filtering

Every message carries the same envelope shape; the event field (and, for updates, reason) tells you what happened, and the same value is also set as the SNS message attribute eventType so you can filter at the subscription level.

Event types

booking.created

A new booking has been persisted. Emitted from the booking-creation flow after the row is committed, on both the online/Staah path and the Livbnb path. reason is null.

booking.updated

An existing booking changed. Always carries a reason:

reasonMeaning
payment_collectedAn online balance collection was applied — paidAmount / outstandingAmount / paymentStatus moved.
settledA finance-approved offline payment settled the booking (paid/outstanding/status recomputed).
modified(reserved) a future booking edit (VAS/meal/date changes). Not emitted yet.

Only emitted when the booking row actually changed (e.g. a duplicate/no-op collection does not emit).

booking.cancelled

The booking was cancelled (bookingStatus → CANCELLED, loyalty reversed, cart released). reason is null. The snapshot reflects the cancelled state.

Envelope

Every event body is:

{
"id": "9f1c8e2a-6b3d-4e7a-9c10-2f5b8a1d4e33",
"event": "booking.updated",
"occurredAt": "2026-07-23T09:14:05.482Z",
"bookingId": "GWVFXCDFFO",
"reason": "payment_collected",
"data": { /* full booking snapshot — see Payloads */ }
}
FieldTypeNotes
idstring (UUID)Unique per emitted event. Use as your idempotency key.
eventstringbooking.created | booking.updated | booking.cancelled
occurredAtstring (ISO-8601, UTC)When the event was published (post-commit).
bookingIdstringThe booking id (equals the booking code).
reasonstring | nullSet only on booking.updated.
dataobject | nullThe rich snapshot. null only if the booking couldn't be read at publish time.

Message attribute & filter policies

Each SNS message sets a single String message attribute:

eventType = "booking.created" | "booking.updated" | "booking.cancelled"

Subscribe with an SNS filter policy (scope MessageAttributes) to receive only the types you care about. The subscription API builds this for you when you pass eventTypes; the resulting policy is:

{ "eventType": ["booking.created", "booking.cancelled"] }

A subscription with no filter policy receives all booking events.

note

The reason on booking.updated is not a message attribute — it lives in the body. If you need to filter updates by reason, subscribe to booking.updated and branch on reason in your consumer.