GET /reservations now returns a payment object for each reservation, exposing the same Received / Unreceived collection status shown in the Hostex web app: total_amount (expected amount), received_amount (already received), balance_amount (still outstanding, never negative) and status (unreceived / partial / received / over_received). Settlement is computed at the order level, so stays sharing the same reservation_code carry identical payment values. Most meaningful for Hostex Direct (manually created) reservations whose income is recorded via POST /transactions.
[3.8.0] - 2026-06-17
Added
GET /listings/airbnb/price_and_rules and POST /listings/airbnb/price_and_rules now support high_rated_guest_discount and mobile_only_discount boolean fields to read and toggle Airbnb's highly-rated guest discount and mobile-only discount promotions.
[3.7.0] - 2026-06-12
Added
New Messages endpoints to manage special offers and pre-approvals in a conversation (previously only available in the Hostex Inbox UI):
GET /conversations/{conversation_id}/special_offers lists the special offers and pre-approvals sent in a conversation, with their current status (active / accepted / declined / expired / withdrawn). The returned id is used to withdraw an offer. Exposed as MCP tool search_special_offers.
POST /conversations/{conversation_id}/special_offers sends a special offer to the guest, inviting them to book the given listing (listing_id) for the given dates at a custom total price, with a guest breakdown (number_of_adults / number_of_children / number_of_infants / number_of_pets). Supported on Airbnb and booking-site (direct booking) conversations; booking-site conversations also require rate_plan_id and currency. Offers typically expire 24 hours after being sent. Exposed as MCP tool send_special_offer.
POST /conversations/{conversation_id}/preapprovals pre-approves the guest's inquiry (Airbnb conversations only), inviting them to book the listing and dates they asked about at the standard price. Exposed as MCP tool send_preapproval.
DELETE /conversations/{conversation_id}/special_offers/{special_offer_id} withdraws a previously sent offer that is still active. Exposed as MCP tool withdraw_special_offer.
New read endpoints for listing-level pricing and rules, complementing the existing write endpoints:
GET /listings/airbnb/price_and_rules returns an Airbnb listing's current prices, fees, discounts, booking settings and availability rules, read in real time from Airbnb. The response mirrors the settings object accepted by POST /listings/airbnb/price_and_rules (values can be written back as-is), plus eligible_cancellation_policies listing the valid cancellation_policy values for the listing. Rate limited to 120 requests per minute, same as write operations.
GET /listings/vrbo/price_and_rules returns a Vrbo listing's prices, fees and booking rules as currently recorded by Hostex (the synced snapshot, not a real-time read from Vrbo). The response mirrors the settings object accepted by POST /listings/vrbo/price_and_rules.
[3.6.0] - 2026-06-01
Added
POST /reviews/{reservation_code} now accepts an optional category_ratings object to submit per-category sub-ratings (overall_rating, cleanliness, communication, respect_of_house_rules, recommend) together with the host review. Only effective on channels that support category ratings (currently Airbnb and Zhenguo). When host_review_score is omitted, the overall_rating value is used as the review score.
New write endpoints to update listing-level pricing, fees and booking rules (the listing's default settings, not a specific date range; only the fields you provide are updated):
POST /listings/vrbo/price_and_rules updates a Vrbo listing's prices, fees and booking rules (base_price or per-weekday nightly_rate, cleaning_fee, security_deposit, extra_guest_fee, weekly_discount / monthly_discount, check_in_start_time / check_out_before, instant_booking, minimum_stay, advance_notice, availability_window). Processed synchronously against Vrbo.
[3.5.0] - 2026-05-25
Added
New Messages write endpoint to manage the host-side note attached to a conversation thread (the same note already exposed read-only on GET /conversations/{conversation_id}):
PATCH /conversations/{conversation_id}/note sets or clears the note. Notes are stored only in Hostex (visible in the Hostex Inbox), are never sent to the guest or pushed to any channel, and are shared across operators inside the same account so the team can leave context for each other. Pass an empty string or null in note to clear the existing note (max 5000 chars). Exposed as MCP tool update_conversation_note.
New write operations on the Property group dictionary, complementing the existing GET /groups:
POST /groups creates a new property group (name required; optional property_ids to pre-attach properties). Group names must be unique within the operator's account. Exposed as MCP tool create_property_group.
PATCH /groups/{id} updates a group. name renames it; property_idsreplaces the full property assignment (empty array detaches all). Exposed as MCP tool update_property_group.
DELETE /groups/{id} deletes a group and its pivot rows; the underlying properties are unaffected. Exposed as MCP tool delete_property_group.
New write operations on the Property tag dictionary, complementing the existing GET /tags:
POST /tags creates a new property tag (name required; optional color from the Hostex palette, property_ids, room_type_ids). Operators are capped at 500 property tags; soft-deleted same-name tags are transparently restored. Exposed as MCP tool create_property_tag.
PATCH /tags/{id} updates a tag. name / color change the tag itself; property_ids / room_type_ids each replace the full attached list (empty arrays detach all). Exposed as MCP tool update_property_tag.
DELETE /tags/{id} deletes a tag and its property / room-type pivot rows. Exposed as MCP tool delete_property_tag.
New Reservation Tags section with read/write coverage of the operator's reservation tag dictionary (the tags that POST /reservations/{stay_code}/tags can attach to a reservation):
GET /reservation_tags lists the operator's reservation tag dictionary, including both system default tags (is_default = true, shared across operators) and the operator's own custom tags. Supports offset / limit pagination, id lookup and keyword substring search. Exposed as MCP tool search_reservation_tags.
POST /reservation_tags creates a new custom tag (tag_name only, max 15 chars). Color is auto-assigned from the Hostex palette. Name collisions against the system defaults or the operator's existing tags return 409; a soft-deleted tag with the same name is transparently restored. Operators are capped at 500 custom tags. Exposed as MCP tool create_reservation_tag.
DELETE /reservation_tags/{id} deletes one of the operator's custom tags. System default tags cannot be deleted via this API. Deletion also detaches the tag from every reservation it had been applied to. Exposed as MCP tool delete_reservation_tag.
New Calendar Share Links section with read/write coverage of public, read-only calendar share links (the same artefacts the Hostex Host Portal exposes under "Share calendar"):
GET /calendar_share_links lists the operator's share links. Each entry returns id, scope (entire / partial), the share url and the property_ids the link exposes (empty when scope = entire). Exposed as MCP tool search_calendar_share_links.
POST /calendar_share_links creates a new share link. scope = entire covers every property (idempotent: returns the existing link if any). scope = partial requires a non-empty property_ids list; each id must belong to the operator. Exposed as MCP tool create_calendar_share_link.
DELETE /calendar_share_links/{id} invalidates a share link; anyone holding the previous URL will get a share link invalid error. Exposed as MCP tool delete_calendar_share_link.
Changed
GET /tags x-mcp metadata: description and intent_examples clarified — this endpoint returns property tags (the tags attached to properties / room types), not reservation tags. The new MCP tool search_reservation_tags covers the reservation tag dictionary. The response shape itself is unchanged.
GET /reservations: each reservation now includes checkin_guide_images, an array of ID document images uploaded by guests through the online check-in guide. The list covers every image submitted under the reservation — including images not yet linked to a guest record (client_id is null for those). Each entry has id, client_id and url (extra-large CDN variant). Existing per-guest guests[].id_images is unchanged.
GET /reservations: each reservation now exposes rates.tax, the reservation TAXES amount as a standalone { currency, amount } object (null when the reservation has no taxes). The aggregated rates.rate and rates.details are unchanged.
[3.4.1] - 2026-05-21
Changed
BREAKINGGET /knowledge_bases: property_ids query parameter is now a comma-separated integer string (e.g. 1,2,3) instead of a repeated array, matching GET /automation/actions and the rest of the v3 list endpoints.
BREAKINGPOST /knowledge_bases and PATCH /knowledge_bases/{id}: scope_property.scope_ids renamed to scope_property.ids so the field name matches the value returned by GET /knowledge_bases and GET /knowledge_bases/{id}.
Added
GET /knowledge_bases/{id}: response now includes process_status (string enum waiting/processing/done/failed), matching the list endpoint.
GET /automation/actions: each item in actions[] now includes type (message/review) and stay_code (linked reservation code, may be null).
POST /automation/actions/{plan_id}/execute: documented 400 response for unsupported plan types or review plans whose reservation has not checked out yet.
Fixed
GET /knowledge_bases: filtering by channel_types no longer crashes with a TypeError; scope_property in each row now correctly reflects the entry's actual property scope (all / by_property / by_group / by_room_type) instead of always falling back to an empty by_property set.
GET /knowledge_bases/{id}: same scope_property correctness fix as above.
POST /knowledge_bases and PATCH /knowledge_bases/{id}: when scope_channel.type is all, the upstream channel list is no longer populated with an unknown sentinel; permission failures on PATCH /knowledge_bases/{id} and DELETE /knowledge_bases/{id} now consistently return 404.
GET /knowledge_bases: pagination now respects arbitrary offset values instead of always advancing by a full page (previous ceil(offset / limit) + 1 made offset=5, limit=10 return rows 11–20 instead of 6–15).
GET /automation/actions: results are now correctly scoped to the operator's master account, so sub-account access tokens no longer return an empty list. The total count also matches the number of returned actions[] rows (plans missing their rule or detail row are filtered in SQL instead of skipped in PHP).
POST /automation/actions/{plan_id}/execute: same-day reviews are no longer rejected as "not yet checked out" — the check-out date comparison now uses the date portion of the reservation's check-out timestamp instead of a lexicographic string compare.
[3.4.0] - 2026-05-20
Added
New Knowledge Base section with full read/write coverage of the HostGPT knowledge base entries used by the automation assistant. Each entry carries a content body and a scope (properties / channels) where it applies:
GET /knowledge_bases to list entries, with pagination and optional filtering by property or channel.
GET /knowledge_bases/{id} to fetch the full detail of a single entry.
POST /knowledge_bases to create a new entry.
PATCH /knowledge_bases/{id} to update an existing entry.
DELETE /knowledge_bases/{id} to delete an entry.
New Channels section with read-only access to the operator's connected channel accounts and the listings synced from them:
GET /channel_accounts returns the third-party platform accounts the operator has connected (Airbnb, Booking.com, etc.) with channel_type, username, origin_account_id and a readable auth_status enum (active / connecting / disconnected / exception). Supports filtering by id and channel_type. Accounts with channel_type=booking_site are excluded. Exposed as MCP tool search_channel_accounts.
GET /listings returns the listings (channel-side properties) synced under those accounts with listing_id, channel_type, channel_account_id, title, cover, url, inventory, a readable shelf_status enum and a metadata passthrough object exposing the normalized channel-side data Hostex caches internally (geo, pictures, price list, etc.; shape varies by channel). Supports filtering by channel_account_id, listing_id and channel_type. Exposed as MCP tool search_listings.
GET /tasks: new optional id query parameter for fetching a single task by its internal id (still scoped to the current operator). Other filters remain unchanged.
GET /transactions: new optional id query parameter for fetching a single transaction entry by its internal id. When id is supplied, start_date and end_date may be omitted; otherwise the existing date-range requirement (and 366-day cap) still applies.
GET /reservations: each entry in guests now includes an id_images array exposing the ID document images uploaded for that guest. Each item carries the image id and a url pointing to the extra-large variant served by the image CDN. Returns an empty array when no image has been uploaded.
GET /conversations/{id}: each entry in messages now includes:
sender_name: display name of the sender when known (operator account name for host-side messages, HostGPT for HostGPT-generated messages, localized HostGPT label for shadow preview messages). null for guest messages and other cases where the sender cannot be resolved.
sources: knowledge sources cited by HostGPT to generate the message, grouped by type (e.g. checkin_guide, automation_reply, host_knowledge, thread, host_assistant). Each group exposes docs[].title / docs[].fragment / docs[].source_type / docs[].link_id. Empty array for human-sent messages and HostGPT messages without resolved citations.
PATCH /reservations/{stay_code}/check_in_details: new optional id_required field controls whether the guest must register / upload ID documents before check-in. String enum: not_required (no ID needed), required (collect ID, no manual review), required_with_review (collect ID and the host must manually review and approve). Internally maps to the need_credential field of the per-stay check-in guide and triggers the same downstream check-in unlocking logic as the Hostex Host Portal.
GET /reservations: each entry in check_in_details now exposes the matching id_required string enum (defaults to not_required when no setting has been applied to the stay).
GET /reservations: order_by now accepts created_at (sort by the row creation timestamp, i.e. when the reservation was first synced into Hostex). Existing values (booked_at, check_in_date, check_out_date, cancelled_at) are unchanged; default remains booked_at.
POST /tasks: new optional stay_code field links the task to a specific reservation by writing into the schedule_task__reservation pivot. When stay_code is supplied without property_id, the property is inherited from the stay; when both are supplied they must point to the same property. Used by the LLM workflow for "create a cleaning / maintenance task on this reservation".
GET /tasks: each task entry now includes a stay_code field (string, nullable) — the reservation the task is linked to, or null for unlinked tasks.
New Property write endpoint:
POST /properties creates a new property (room) under the current operator. Only title is required; everything else (address, channels, pictures, prices, default check-in/out times) is configured afterwards via the Hostex Host Portal. Subject to the property quantity limit of the operator's subscription.
New Room Type write endpoint:
POST /room_types creates a new room type under the current operator. Optionally accepts property_ids to link existing properties at creation time (each property must not already belong to another room type). Subject to the room type quantity limit (capped by the property quantity limit of the subscription) and not available on Basic editions.
New GET /pricing_ratios endpoint (under Listing Calendar) returns the per-channel pricing ratio of each OTA listing linked to a property (property_id) or room type (room_type_id). Each entry exposes channel_type, listing_id, listing_title, ratio (percent) and readonly. This enables a "change price by property / room type" workflow at the skill / client layer without a dedicated server endpoint: read the ratios, compute target_price = round(base_price * ratio / 100) for every non-readonly listing, then call POST /listings/prices once per listing (readonly: true listings — e.g. Airbnb child rate plans — must be skipped).
[3.3.1] - 2026-05-11
Fixed
GET /transactions: start_date and end_date are now consistently interpreted in the operator's configured timezone, matching how entries are stored and how action_at is returned. Previously the boundaries could be evaluated in the database session's default timezone, causing up to a one-day shift for operators not in UTC+8.
POST /transactions and PATCH /transactions/{id}: action_at values supplied as UTC ISO 8601 are now correctly converted to the operator's timezone before being persisted, so the round-trip with GET /transactions returns the same instant.
[3.3.0] - 2026-05-08
Added
GET /reservations: new optional channel_id query parameter to filter reservations by the channel-side reservation ID (the same value returned as channel_id in the response).
[3.2.0] - 2026-04-29
Added
New Incomes & Expenses section, with full read/write coverage of income and expense entries (transactions):
GET /transactions for querying entries. Supports filtering by date range (start_date / end_date), property_id, stay_code, direction, item_id, payment_method_id, currency and keyword. Each entry exposes direction (income / expense), link_type (property / reservation / operator) and status (paid / outstanding) as readable string enums, and resolves item_name / payment_method_name from the dictionaries below.
POST /transactions to record a new entry. The link target is inferred from the request: provide stay_code to record against a specific stay, property_id to record against a property, or neither for an operator-level entry (master operator only). amount is always positive — sign is derived from direction. currency is required unless stay_code is provided, in which case it is inherited from the reservation order.
PATCH /transactions/{id} to update an entry's amount, item_id, payment_method_id, action_at or note. Direction, link target and currency are immutable.
DELETE /transactions/{id} to permanently delete an entry.
New dictionary endpoints GET /income_items, GET /expense_items, GET /income_methods and GET /expense_methods decode the item_id / payment_method_id returned by GET /transactions.
New Task write endpoints:
POST /tasks to create a schedule task. Optional property_id and staff_id link the task to a property and assign a staff; level is only meaningful for cleaning tasks. expected_date / expected_time are interpreted in the operator's configured timezone. Returns the new task_id.
PATCH /tasks/{id} to update an existing task. All fields are optional; pass property_id=0 or staff_id=0 to detach. The full status lifecycle (pending / in_progress / completed / cancelled) can be set here. expected_date / expected_time are interpreted in the operator's configured timezone.
DELETE /tasks/{id} to delete a task.
New Staff write endpoints:
POST /staffs to create a schedule staff (created as active). Use property_ids to scope the staff to specific properties. International operators must provide mobile in +<country code> <number> format.
PATCH /staffs/{id} to update an existing staff. Passing property_ids replaces the full assignment list; pass an empty array to clear. is_active toggles enable/disable.
DELETE /staffs/{id} to delete a staff (and remove their property assignments).
Changed
PATCH /reservations/{stay_code} (Update Reservation Basic Info): the path parameter is now stay_code instead of reservation_code, since the endpoint updates a specific stay's attributes rather than the order. The URL pattern itself is unchanged. DELETE /reservations/{reservation_code} (Cancel) and the channel-facing POST /reservations/{reservation_code}/approve|decline keep reservation_code since they operate at the order level.
Fixed
GET /reservations: the custom_channel.id field now returns the same id used by GET /custom_channels (previously returned an internal table primary key that could not be matched against the dictionary).
[3.1.2] - 2026-04-28
Added
New Task endpoints GET /tasks and GET /staffs for querying schedule tasks and staffs.
GET /tasks supports filtering by date range (start_date / end_date), staff_id, property_id, type and status.
Task type, status and level are returned as readable string enums (e.g. cleaning, pending, standard).
[3.1.1] - 2026-03-10
Added
New Property endpoint GET /tags returning all tags with their associated property and room type ids.
GET /properties supports tag_id filter and now returns a tags array on each property.
GET /room_types supports id and tag_id filters and now returns a tags array on each room type.
[3.1.0] - 2026-01-21
Added
New Property endpoint GET /groups returning all property groups with their associated property ids.
GET /properties supports group_id filter and now returns a groups array on each property.
[3.0.0]
Added
Initial release of the Hostex OpenAPI v3, with endpoints covering Properties, Room Types, Reservations, Availabilities, Listing Calendar, Messaging, Reviews, Automation and Webhooks.