Event Types

Webhook Event Types

Reference for the payload shape of every event Hostex emits. Read the
Usage Guide first for headers, delivery semantics,
and security.

Every payload is a single flat JSON object: event, a string event_id, the
event-specific fields listed below, and a timestamp (ISO 8601 UTC,
e.g. 2026-05-22T02:51:12Z) stamped when the event was queued:

Every v3 event, including authorization_revoked, includes a 26-character ULID event_id. All webhook URLs receiving the same emitted event and all delivery attempts share this ID. Distinct emitted events have different IDs. Deduplicate on event_id; it identifies a notification, not the business resource or the API request that caused it. It does not guarantee delivery or ordering.

{
  "event": "<event_name>",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW0",
  "...event-specific fields...": "...",
  "timestamp": "2026-05-22T02:51:12Z"
}

Webhook payloads are deliberately thin: they identify what changed
and carry no further detail. Fetch the current state from the
corresponding GET endpoint — the webhook is a "something changed,
go look" signal, not a change feed.


reservation_created

Fired when a new reservation lands in Hostex — from any channel
(Airbnb, Booking.com, custom-channel via POST /reservations, etc.).

{
  "event": "reservation_created",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW1",
  "reservation_code": "ABC123",
  "stay_code": "ABC123",
  "property_id": 12345,
  "timestamp": "2026-05-22T02:51:12Z"
}

A multi-room booking fires one event per stay: same
reservation_code, a distinct stay_code for each room.

Use it to: index a new booking, trigger an onboarding email, create a
cleaning task — after fetching the details via
GET /reservations?reservation_code=<...>.


reservation_updated

Fired when an existing reservation changes in any of these ways:

  • Status transition (e.g. accepted → cancelled).
  • Date / guest-count change, or room reassignment (allocate).
  • Arrival / departure time set (sub_event: arrival_and_departure_time_updated).
  • Nightly rates changed (sub_event: rates_updated).
  • Door-lock code set or removed (sub_event: lock_code_updated / lock_code_deleted).
  • Check-in details updated (sub_event: check_in_details_updated).
  • note (host-side reservation remarks) edited (sub_event: remarks_updated).
  • Custom fields saved via the OpenAPI custom-fields endpoint (no sub_event).

The optional sub_event field, when present, tells you which of the
above happened; when absent, treat it as a generic change.

{
  "event": "reservation_updated",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW2",
  "sub_event": "rates_updated",
  "reservation_code": "ABC123",
  "stay_code": "ABC123",
  "property_id": 12345,
  "timestamp": "2026-05-22T02:51:12Z"
}

Tip: the payload only confirms that the reservation changed; if you need
the post-change snapshot, call GET /reservations?id=<...> and read the
fresh state. Avoid trying to diff payloads — the same reservation can
emit several reservation_updated events in quick succession.


property_availability_updated

Fired whenever a property's nightly availability changes in Hostex,
whatever the cause: your POST /availabilities calls, portal
edits, reservations being accepted or cancelled (dates auto-close /
re-open), iCal imports, listing deactivation, and so on.

{
  "event": "property_availability_updated",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW3",
  "property_id": 12345,
  "availabilities": [
    { "date": "2026-06-01", "available": false },
    { "date": "2026-06-02", "available": false }
  ],
  "timestamp": "2026-05-22T02:51:12Z"
}

The payload lists each affected date individually — it is not a
date-range summary.


listing_calendar_updated

Fired after Hostex successfully pushes calendar changes (prices,
inventory) to a channel-side listing — whether the change originated
from your POST /listings/prices / POST /listings/inventories calls
or from Hostex's own sync. Not fired for edits made directly on the
channel (OTA) itself.

Not fired in these cases:

  • POST /listings/restrictions, POST /listings/airbnb/price_and_rules and POST /listings/vrbo/price_and_rules write to the channel directly and never send this event.
  • The push fails, or finishes with a warning instead of a clean success.
{
  "event": "listing_calendar_updated",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW4",
  "channel_type": "airbnb",
  "listing_id": "12345678",
  "start_date": "2026-06-01",
  "end_date": "2026-06-30",
  "timestamp": "2026-05-22T02:51:12Z"
}

listing_id is the channel-side listing identifier (always a string).

What the event does and does not tell you:

  • It normally means the channel accepted the push. Hostex does not read the calendar back from the channel to verify it.
  • It carries no identifier linking it to the API request that caused it; match it on channel_type + listing_id + dates. timestamp is when the event was queued, not when the channel applied the change.
  • For the same channel, listing and date range, only the first event in a 5-second window is sent. Identical events raised during the rest of that window are dropped — they are not folded into the delivery you received, and no later event reports them. If you need the final values, wait a few seconds before reading, and rely on periodic reconciliation.

Use it to: keep your own price intelligence / channel-manager bridge
in sync with less polling of the listing calendar endpoints. Because
failed deliveries are not sent again (see the Usage Guide),
still reconcile periodically with POST /listings/calendar.


message_created

Fired when a new message lands in a conversation thread — inbound from
the guest, outbound sent by you (POST /conversations/{id}), by the
host from the Host Portal or the channel's own app, or by automation.
For OTA channels the event can arrive with a delay of some seconds
(channel sync round-trip).

{
  "event": "message_created",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW5",
  "conversation_id": "0-2588930000",
  "message_id": "0-31777061577-667553000",
  "timestamp": "2026-05-22T02:51:12Z"
}

Both ids are opaque strings whose format varies by channel — store and
compare them as-is.

⚠️

The payload does not tell you who sent the message. Call

GET /conversations/{id} and check the message's sender_role
before acting — an auto-replier that treats every message_created
as a guest message will answer its own outbound messages and loop.


review_created

Fired the first time Hostex sees a review record for a reservation on
the channel. On some channels this record is created around checkout
before any content is written, so review_created does not
guarantee that review content exists yet.

{
  "event": "review_created",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW6",
  "reservation_code": "ABC123",
  "stay_code": "ABC123",
  "property_id": 12345,
  "timestamp": "2026-05-22T02:51:12Z"
}

review_updated

Fired on any subsequent change to that review record — the guest
submits their review, the host replies, scores or content change.

{
  "event": "review_updated",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW7",
  "reservation_code": "ABC123",
  "stay_code": "ABC123",
  "property_id": 12345,
  "timestamp": "2026-05-22T02:51:12Z"
}

Recommended: handle review_created and review_updated identically —
fetch the fresh state via GET /reviews and act on what is actually
there.


transaction_created

Fired when an income/expense entry is created — via POST /v3/transactions,
the Hostex portal, or system-generated charges (e.g. refunds).

{
  "event": "transaction_created",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW8",
  "transaction_id": 123456,
  "timestamp": "2026-05-22T02:51:12Z"
}

transaction_updated

Fired when an existing entry is edited — amount, item, payment method,
action_at, or note. Note that editing does not change the entry's
action_at, so polling GET /v3/transactions by date window alone will
miss edits to older entries; this event is the reliable signal.

{
  "event": "transaction_updated",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRW9",
  "transaction_id": 123456,
  "timestamp": "2026-05-22T02:51:12Z"
}

transaction_deleted

Fired when an entry is deleted. Deletion is permanent — the entry will
no longer appear in GET /v3/transactions responses.

{
  "event": "transaction_deleted",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRWA",
  "transaction_id": 123456,
  "timestamp": "2026-05-22T02:51:12Z"
}

Recommended: on transaction_created / transaction_updated, fetch the
current state via GET /v3/transactions?id=<transaction_id>; on
transaction_deleted, remove the entry from your mirror. Together these
three events let you keep an up-to-date transaction mirror without
scanning a wide action-date window.


Forward compatibility

Hostex may add new events or new fields to existing events at any time
without bumping the v3 API version. Your handler must:

  1. Ignore unknown event types (drop or log; do not crash).
  2. Ignore unknown fields within known events.
  3. Re-derive state from the API when the payload is not enough —
    the webhook is a "something changed, go look" signal, not a full
    change feed.

authorization_revoked

Final lifecycle notification when the OAuth application is disconnected. Sent to the application's API-created webhook endpoints for the account, irrespective of their business-event filters, using each webhook's original secret. The webhook registrations and tokens are already removed when delivery begins. No personal information is included. See the Usage Guide for multi-device behavior and delivery limitations.

{
  "event": "authorization_revoked",
  "event_id": "01K71WRG00R6PR4FPYRXBNNRWB",
  "account_id": "12345",
  "client_id": "your_application_id",
  "timestamp": "2026-10-09T02:00:00Z"
}