Skip to Content
Hotel front desk

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.

EndpointScope
GET /v1/hotel/room-typeshotel:rooms:read
POST /v1/hotel/room-typeshotel:rooms:write
GET /v1/hotel/roomshotel:rooms:read
POST /v1/hotel/roomshotel:rooms:write
GET /v1/hotel/availabilityhotel:reservations:read
GET /v1/hotel/reservationshotel:reservations:read
GET /v1/hotel/reservations/:idhotel:reservations:read
POST /v1/hotel/reservationshotel:reservations:write
POST /v1/hotel/reservations/:id/check-inhotel:reservations:write
POST /v1/hotel/reservations/:id/check-outhotel:reservations:write
POST /v1/hotel/reservations/:id/cancelhotel:reservations:write

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-types

Optional 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-types
FieldTypeRequiredDescription
store_iduuidYesProperty the room type belongs to
namestringYesRoom type name
nightly_ratenumberYesPrice per night
max_guestsnumberNoCapacity (defaults to 1)
amenitiesstring[]NoWhat’s included
currencystringNoISO code (defaults to NGN)
descriptionstringNoFree-text description

Rooms

GET /v1/hotel/rooms

Optional query: store_id. Each room: { id, storeId, roomTypeId, number, status, createdAt }. status is one of available, occupied, out_of_service.

POST /v1/hotel/rooms
FieldTypeRequiredDescription
store_iduuidYesProperty
room_type_iduuidYesThe room type this room backs
numberstringYesRoom number or name
statusstringNoDefaults to available

Availability

GET /v1/hotel/availability

Returns the room types with at least one room free for the given dates and party size.

ParameterTypeRequiredDescription
store_iduuidYesProperty
check_in_dateISO dateYesYYYY-MM-DD
check_out_dateISO dateYesYYYY-MM-DD
adultsnumberYesNumber of adults
childrennumberNoNumber of children
{ "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/reservations

Filters: store_id, status, from, to (ISO dates). Returns an array of reservation objects.

GET /v1/hotel/reservations/:id

Returns a single reservation, or 404 not_found if the ID doesn’t belong to your business.

Create a reservation

POST /v1/hotel/reservations

Creates 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.

FieldTypeRequiredDescription
store_iduuidYesProperty
customer_iduuidYesGuest (a contact)
room_type_iduuidYesRoom type to book
check_in_dateISO dateYesYYYY-MM-DD (not in the past)
check_out_dateISO dateYesMust be after check-in
adultsnumberYesNumber of adults
childrennumberNoNumber of children
room_iduuidNoPre-assign a specific room
notesstringNoFree-text note
{ "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/cancel

Move 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.

Last updated on