Hotel front desk
Read and manage your hotel inventory and bookings - useful for migrating from another system, syncing a channel manager, or building a custom booking flow on top of Cloove’s AI Front Desk.
All endpoints share the prefix /v1/hotel and authenticate with an
API key. Request bodies and query parameters are snake_case;
responses are camelCase.
The hotel:read scope is a shorthand that grants every hotel :read scope.
Room types
A room type is a sellable category (e.g. “Deluxe”) with a nightly rate and capacity. Physical rooms belong to a room type.
GET /v1/hotel/room-typesOptional query: store_id to scope to one property.
{
"message": "Room types retrieved",
"data": [
{
"id": "rt1a2b3c-...",
"storeId": "st1a2b3c-...",
"name": "Deluxe Room",
"description": null,
"maxGuests": 2,
"amenities": ["Wi-Fi", "Breakfast"],
"nightlyRate": 45000,
"currency": "NGN",
"isActive": true,
"createdAt": "2026-06-09T10:00:00.000Z"
}
]
}POST /v1/hotel/room-typesRooms
GET /v1/hotel/roomsOptional query: store_id. Each room: { id, storeId, roomTypeId, number, status, createdAt }.
status is one of available, occupied, out_of_service.
POST /v1/hotel/roomsAvailability
GET /v1/hotel/availabilityReturns the room types with at least one room free for the given dates and party size.
{
"message": "Availability retrieved",
"data": [
{
"roomType": { "id": "rt1a2b3c-...", "name": "Deluxe Room", "nightlyRate": 45000, "currency": "NGN", "...": "..." },
"availableUnits": 3,
"nights": 3,
"total": 135000,
"taxAmount": 0
}
]
}total is what the guest pays for the stay. When the business charges VAT on hotel
bookings, total includes it and taxAmount shows the VAT inside total; otherwise
taxAmount is 0.
Reservations
GET /v1/hotel/reservationsFilters: store_id, status, from, to (ISO dates). Returns an array of
reservation objects.
GET /v1/hotel/reservations/:idReturns a single reservation, or 404 not_found if the ID doesn’t belong to
your business.
Create a reservation
POST /v1/hotel/reservationsCreates a confirmed (unpaid) reservation. The guest must already exist - create
or look one up via the Contacts API and pass its customer_id.
Always send an Idempotency-Key header.
{
"store_id": "st1a2b3c-...",
"customer_id": "ct1a2b3c-...",
"room_type_id": "rt1a2b3c-...",
"check_in_date": "2026-07-01",
"check_out_date": "2026-07-04",
"adults": 2
}Response 201 Created - the reservation. Because creation runs a live
availability check, it returns 422 when no room of that type is free for the
dates.
Manage a reservation
POST /v1/hotel/reservations/:id/check-in
POST /v1/hotel/reservations/:id/check-out
POST /v1/hotel/reservations/:id/cancelMove a reservation through its lifecycle. These return 422 when the transition
isn’t allowed (e.g. checking in before a room is assigned, or cancelling a stay
that is already checked in).
The reservation object
{
"id": "rv1a2b3c-...",
"storeId": "st1a2b3c-...",
"confirmationCode": "CLV-1A2B3C4D",
"status": "confirmed",
"guest": { "id": "ct1a2b3c-...", "name": "Ada Lovelace" },
"roomType": { "id": "rt1a2b3c-...", "name": "Deluxe Room" },
"roomId": null,
"roomNumber": null,
"checkInDate": "2026-07-01",
"checkOutDate": "2026-07-04",
"adults": 2,
"children": 0,
"nightlyRate": 45000,
"totalAmount": 135000,
"currency": "NGN",
"source": "dashboard",
"createdAt": "2026-06-09T10:00:00.000Z"
}status is one of confirmed, checked_in, checked_out, cancelled,
no_show.
totalAmount is what the guest pays for the stay, including VAT when the business
charges VAT on hotel bookings. It is fixed when the reservation is created, so later
VAT setting changes do not alter existing reservations.
Reservation changes emit webhooks (hotel.reservation.created,
hotel.reservation.checked_in, and so on), so downstream systems stay in sync
whether a booking comes from the API, the dashboard, or the AI front desk.