Bookings (Reservas)
Retorna una lista paginada de reservas del negocio. Soporta el sistema de filtrado.
Listar reservas
Sección titulada «Listar reservas»GET /v1/bookingsRespuesta exitosa: 200 OK
{ "total": 42, "items": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "startTime": "2026-03-05 10:00:00", "endTime": "2026-03-05 11:00:00", "status": "confirmed", "internalNote": null, "clientNote": null, "paymentStatus": null, "isFromWeb": false, "isFromAgent": false, "amount": 50.0, "clientId": "660e8400-e29b-41d4-a716-446655440001", "locationId": "770e8400-e29b-41d4-a716-446655440002", "serviceId": "880e8400-e29b-41d4-a716-446655440003", "personId": "990e8400-e29b-41d4-a716-446655440004", "paymentId": null, "businessAccountId": "aa0e8400-e29b-41d4-a716-446655440005", "location": { "id": "770e8400-e29b-41d4-a716-446655440002", "name": "Sede Principal" }, "person": { "id": "990e8400-e29b-41d4-a716-446655440004", "firstname": "María", "lastname": "García", "email": "maria@example.com", "status": "active", "phone": "+593991234567" }, "service": { "id": "880e8400-e29b-41d4-a716-446655440003", "name": "Corte de cabello", "duration": 60, "domiciliary": false, "virtual": false, "status": "active", "price": 50.0, "categoryId": "bb0e8400-e29b-41d4-a716-446655440006", "description": null, "sessions": null, "simultaneous": 1 }, "client": { "id": "660e8400-e29b-41d4-a716-446655440001", "firstname": "Juan", "lastname": "Pérez", "email": "juan@example.com", "phone": "+593991234568" }, "notifyClient": true, "repeatGroupId": null, "answers": null, "questionaryId": null, "createdAt": "2026-03-01 15:30:00" } ]}Obtener reserva
Sección titulada «Obtener reserva»GET /v1/bookings/{id}| Parámetro | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID de la reserva |
Respuesta exitosa: 200 OK — Un único objeto Booking.
Respuesta error: 404 Not Found
{ "message": "Booking not found." }Crear reserva
Sección titulada «Crear reserva»POST /v1/bookings| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
startTime | string | Si | Fecha/hora inicio ISO 8601. Ej: 2026-03-05T10:00:00Z |
endTime | string | Si | Fecha/hora fin ISO 8601. Debe ser posterior a startTime |
status | string | Si | Estado: reserved, pending, confirmed, no_show, completed, cancelled |
internalNote | string | No | Nota interna |
amount | number | Si | Monto de la reserva (>= 0) |
clientId | string (UUID) | Si | UUID del cliente |
locationId | string (UUID) | Si | UUID de la ubicación |
serviceId | string (UUID) | Si | UUID del servicio |
personId | string (UUID) | No | UUID del profesional |
notifyClient | boolean | No | Notificar al cliente (default: true) |
Ejemplo:
{ "startTime": "2026-03-10T10:00:00Z", "endTime": "2026-03-10T11:00:00Z", "status": "confirmed", "amount": 50.00, "clientId": "660e8400-e29b-41d4-a716-446655440001", "locationId": "770e8400-e29b-41d4-a716-446655440002", "serviceId": "880e8400-e29b-41d4-a716-446655440003", "personId": "990e8400-e29b-41d4-a716-446655440004", "notifyClient": true}Respuesta exitosa: 201 Created — { "id": "cc0e8400-e29b-41d4-a716-446655440007" }
Actualizar reserva (parcial)
Sección titulada «Actualizar reserva (parcial)»PUT /v1/bookings/{id}| Parámetro | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID de la reserva |
Permite actualizar parcialmente una reserva existente. Solo los campos enviados serán modificados; los campos omitidos conservarán su valor actual.
Nota: Los campos de origen (
isFromWeb,isFromAgent,isFromApi) no pueden ser modificados.
Body (todos los campos son opcionales):
| Campo | Tipo | Descripción |
|---|---|---|
startTime | string (ISO 8601) | Fecha y hora de inicio |
endTime | string (ISO 8601) | Fecha y hora de fin |
status | string | Estado: reserved, pending, confirmed, no_show, completed, cancelled |
internalNote | string | Nota interna |
amount | number | Monto (≥ 0) |
clientId | string (UUID) | ID del cliente |
locationId | string (UUID) | ID de la ubicación |
serviceId | string (UUID) | ID del servicio |
personId | string (UUID) | ID del profesional |
notifyClient | boolean | Notificar al cliente (default: true) |
Ejemplo — actualizar solo el estado:
{ "status": "confirmed"}Ejemplo — actualizar horario y monto:
{ "startTime": "2026-04-01T14:00:00Z", "endTime": "2026-04-01T15:00:00Z", "amount": 75.00}Respuesta exitosa: 204 No Content
Error si la reserva no existe: 422 Unprocessable Entity
Eliminar reserva
Sección titulada «Eliminar reserva»DELETE /v1/bookings/{id}Realiza un soft-delete de la reserva.
Respuesta exitosa: 204 No Content
Consultar disponibilidad
Sección titulada «Consultar disponibilidad»GET /v1/bookings/availabilityRetorna los slots de tiempo disponibles para un servicio en una ubicación.
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
locationId | string (UUID) | Si | UUID de la ubicación |
serviceId | string (UUID) | Si | UUID del servicio |
startDate | string | No | Fecha inicio (YYYY-MM-DD). Default: hoy |
endDate | string | No | Fecha fin (YYYY-MM-DD). Default: startDate + 30 días |
professionalId | string (UUID) | No | Filtrar por profesional específico |
Respuesta exitosa: 200 OK
{ "days": ["2026-03-05", "2026-03-06", "2026-03-07"], "professionals": [ { "id": "990e8400-e29b-41d4-a716-446655440004", "name": "María García" }, { "id": "aa1e8400-e29b-41d4-a716-446655440008", "name": "Carlos López" } ], "slots": [ { "startTime": "2026-03-05 09:00:00", "endTime": "2026-03-05 10:00:00", "professionals": [{ "id": "990e8400-e29b-41d4-a716-446655440004", "name": "María García" }] }, { "startTime": "2026-03-05 10:00:00", "endTime": "2026-03-05 11:00:00", "professionals": [ { "id": "990e8400-e29b-41d4-a716-446655440004", "name": "María García" }, { "id": "aa1e8400-e29b-41d4-a716-446655440008", "name": "Carlos López" } ] } ], "limitExceeded": false}| Campo | Tipo | Descripción |
|---|---|---|
days | string[] | Fechas con disponibilidad (YYYY-MM-DD) |
professionals | Professional[] | Profesionales con al menos un slot disponible |
slots | Slot[] | Slots de tiempo disponibles |
slots[].startTime / slots[].endTime | string | Inicio/fin del slot (YYYY-MM-DD HH:mm:ss) |
limitExceeded | boolean | true si el rango excedió la ventana de agenda |