Preview specification. This is the proposed design of the Hospitally Connect API. Endpoints, fields and event names may change before general availability. The guest-chat connector is a concept design and is not affiliated with or endorsed by Marriott International or any chat provider.
Overview
Base URL https://api.hospitally.app/v1. Requests and responses are JSON and timestamps are ISO-8601 in UTC. Every resource belongs to a property_id, which is set by your token's scope. Every write returns the resulting event ID so you can reconcile against the webhook stream.
| Resource | What it covers |
|---|---|
reservations | Bookings, stays, check-in and out, extensions, late check-out |
rooms | Room status, assignment, moves, out-of-order |
housekeeping | Tasks, boards, inspections |
inventory | Items, par levels, purchase orders |
groups | Blocks, pickup, rooming lists, releases |
loyalty | Member arrivals and recognition |
chat | Threads and messages mirrored from connected chat platforms |
Authentication
Hospitally uses OAuth 2.0 client credentials. Tokens are scoped per property and per capability (for example reservations:write or chat:read) and last one hour.
curl -X POST https://auth.hospitally.app/oauth/token \
-d grant_type=client_credentials \
-d client_id=$CLIENT_ID -d client_secret=$CLIENT_SECRET \
-d scope="reservations:write rooms:write chat:write"
Send the token as Authorization: Bearer <token>. Writes accept an Idempotency-Key header, and a retried key within 24 hours returns the original result.
Webhooks & signatures
Subscribe an HTTPS endpoint to any event type. Each delivery carries a Hospitally-Signature header, t=<unix>,v1=<hex>, where v1 is HMAC-SHA256 of t + "." + body keyed by your endpoint secret. Reject anything older than five minutes. Deliveries retry with exponential backoff for 24 hours.
import crypto from "node:crypto";
export function verify(req, secret) {
const [t, v1] = req.headers["hospitally-signature"].split(",").map((p) => p.split("=")[1]);
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.${req.rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
Guest-chat connector
The connector links a brand's guest-chat app to live bookings. Inbound messages go to Hospitally. Hospitally matches each one to a reservation, classifies the intent and proposes an action. When staff approve, the action executes and the reply posts back to the thread.
Sent by the chat platform (or its adapter) to Hospitally for every guest message.
{
"type": "chat.message.created",
"id": "evt_01J9W3K6QX",
"created_at": "2026-09-29T11:03:12Z",
"data": {
"thread_id": "thr_8841",
"channel": "brand_app",
"guest": { "loyalty_number": "XXXX4471", "confirmation": "H48221" },
"text": "Our meetings ran over, can we extend by one more night?"
}
}Emitted by Hospitally after matching and classifying a message. It includes a feasibility check and the proposed call.
{
"type": "chat.intent.detected",
"data": {
"thread_id": "thr_8841",
"reservation_id": "H48221",
"intent": "extend_stay",
"confidence": 0.97,
"feasible": true,
"proposal": {
"method": "POST",
"path": "/v1/reservations/H48221/extend",
"body": { "nights": 1, "keep_room": true, "rate_plan": "BAR" }
},
"draft_reply": "You're all set for one more night in room 318."
}
}Posts a staff reply back to the guest thread through the connected platform.
{ "text": "You're all set for one more night in room 318.", "author": "front_desk" } Supported intents: late_checkout, extend_stay, early_checkin, room_move, amenity_request, billing_question and other. Policy rules can auto-approve by intent, tier and forecast occupancy.
Reservations
Lists reservations filtered by status (arriving, in_house, due_out, checked_out), date, group or loyalty tier. Cursor-paginated.
Returns one reservation with guest, room, rate, folio summary and preferences.
{
"id": "H48221",
"status": "in_house",
"guest": { "name": "Marcus Chen", "tier": "gold", "preferences": ["high_floor"] },
"room": { "number": "318", "type": "K" },
"arrival": "2026-09-27", "departure": "2026-09-30",
"rate_plan": "BAR", "group_code": null
}Updates mutable fields such as departure_time (late check-out), preferences or notes.
{ "departure_time": "14:00", "reason": "guest_chat" }Adds nights and keeps the same room when it is available. Returns 409 room_unavailable with alternatives when it is not.
// request
{ "nights": 1, "keep_room": true, "rate_plan": "BAR" }
// 200 response
{ "id": "H48221", "departure": "2026-10-01", "room": "318", "rate_total": 309.00, "event_id": "evt_01J9W3P2" }Checks the guest in. If room is omitted, Hospitally assigns the best ready room for the guest's type and preferences, then triggers mobile-key issuance.
Closes the stay, settles or routes the folio, and marks the room dirty for housekeeping.
Rooms
Lists rooms with housekeeping status (dirty, in_progress, clean, inspected, out_of_order) and occupancy.
Assigns or moves a reservation to a room. When rush is true, Hospitally picks the next room to turn and moves it to the top of the attendant's board.
// request
{ "reservation_id": "H48213", "room": "1412", "rush": false, "reason": "early_checkin" }
// 200 response
{ "reservation_id": "H48213", "room": "1412", "key_status": "issued", "event_id": "evt_01J9W41B" }Sets housekeeping status or out-of-order windows.
{ "status": "inspected", "inspected_by": "usr_22" }
Housekeeping
Creates a task such as an amenity delivery, a turndown or an extra clean, with an SLA. The task is routed to the attendant on that floor.
{ "room": "1107", "type": "amenity", "note": "2 towels, 1 crib", "sla_minutes": 15 }Returns attendant boards with assigned rooms, credits and progress.
Inventory
Returns items with on-hand quantity, par, per-occupied-room usage and tonight's forecast need.
Raises a purchase order to a supplier. Deliveries emit inventory.delivered.
{ "item_id": "btw", "quantity": 820, "supplier_id": "sup_linen_01" }
Groups
Returns block, pickup by night, cutoff, rate and master account.
Imports a rooming list (JSON or CSV). Hospitally fuzzy-matches names to existing reservations and creates the rest.
Releases unsold rooms from the block back to general inventory.
{ "rooms": 10, "nights": ["2026-10-01", "2026-10-02"] }
Loyalty
Returns elite arrivals with preferences and recognition state (note, amenity, upgrade).
Records a recognition action for reporting and credit sync.
{ "reservation_id": "H48213", "type": "upgrade", "to_room": "2304" }
Event types
| Event | When |
|---|---|
reservation.created / .updated / .cancelled | Booking lifecycle |
reservation.checked_in / .checked_out | Arrival and departure |
room.status_changed | Any housekeeping status change |
room.assigned | Assignment or move |
housekeeping.task.completed | Task done, with duration versus SLA |
inventory.below_need / inventory.delivered | Stock against forecast |
group.pickup_changed / group.cutoff_approaching | Blocks |
forecast.house_full | A night crosses 100% forecast |
chat.message.created / chat.intent.detected | Guest chat |
Errors & limits
Errors use standard HTTP codes with a JSON body: {"error": {"code": "room_unavailable", "message": "…", "alternatives": [...]}}. The rate limit is 600 requests per minute per property. 429 responses include Retry-After.
| Code | Meaning |
|---|---|
400 invalid_request | Malformed body or parameters |
401 unauthorized / 403 insufficient_scope | Token missing, expired or under-scoped |
404 not_found | Unknown reservation, room or thread |
409 room_unavailable / 409 house_full | Inventory conflict; alternatives included |
422 policy_blocked | The property's rules block the action, for example no late check-out on house-full days |