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
}
]
}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.
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.