Referencia de API
- Base URL
- Autenticación
- Formatos de Datos
- Estructura de Endpoints
- Endpoints por Rol
- Account (Usuario Autenticado)
- Reservas (Account)
- GET /reservations
- GET /reservations/:id
- POST /reservations
- PUT /reservations/:id
- DELETE /reservations/:id
- GET /account/bookings
- POST /account/bookings
- GET /account/bookings/calculate-price
- GET /account/bookings/{bookingId}
- GET /account/courts
- GET /account/reservation-types
- GET /account/payment-types
- GET /account/stats
- Perfil (Account)
- GET /account/profile
- PUT /account/profile
- Cliente (Account)
- GET /account/client
- PATCH /account/client
- POST /account/client
- Clases (Account)
- GET /account/classes
- GET /account/classes/my-enrollments
- GET /account/classes/{id}
- POST /account/classes/{id}/enroll
- Admin (Administradores y Operadores)
- Reservas (Admin)
- GET /admin/booking
- GET /admin/bookings
- GET /admin/booking/full
- POST /admin/booking
- POST /admin/bookings
- GET /admin/booking/{id}
- GET /admin/bookings/{id}
- PATCH /admin/booking/{id}
- PATCH /admin/bookings/{id}
- DELETE /admin/booking/{id}
- DELETE /admin/bookings/{id}
- DELETE /admin/booking
- DELETE /admin/bookings
- GET /admin/booking/calculate-price
- GET /admin/bookings/calculate-price
- GET /admin/booking/{id}/price
- POST /admin/booking/validate
- Pagos de Reservas (Admin)
- GET /admin/payments
- GET /admin/payments/stats
- GET /admin/payments/:id
- GET /admin/payments/transaction/:transaction_id
- GET /admin/booking/{bookingId}/payment
- POST /admin/booking/{bookingId}/payment
- GET /admin/booking/{bookingId}/payment/{paymentId}
- PATCH /admin/booking/{bookingId}/payment/{paymentId}
- DELETE /admin/booking/{bookingId}/payment
- POST /admin/payments
- PATCH /admin/payments/:id
- DELETE /admin/payments/:id
- Clases (Admin)
- GET /admin/classes
- POST /admin/classes
- GET /admin/classes/{id}
- PUT /admin/classes/{id}
- DELETE /admin/classes/{id}
- PATCH /admin/classes/{id}/cancel
- PATCH /admin/classes/{id}/complete
- Inscripciones (Admin)
- GET /admin/enrollments
- POST /admin/enrollments
- GET /admin/enrollments/{id}
- DELETE /admin/enrollments/{id}
- PATCH /admin/enrollments/{id}/accept
- PATCH /admin/enrollments/{id}/reject
- PATCH /admin/enrollments/{id}/attendance
- Notificaciones (Admin)
- POST /admin/notifications/token
- DELETE /admin/notifications/token
- POST /admin/notifications/send
- Trainer (Entrenadores)
- Clases (Trainer)
- GET /trainer/classes
- POST /trainer/classes
- GET /trainer/classes/{id}
- PUT /trainer/classes/{id}
- DELETE /trainer/classes/{id}
- PATCH /trainer/classes/{id}/cancel
- PATCH /trainer/classes/{id}/complete
- Reservas (Trainer)
- GET /trainer/bookings
- POST /trainer/bookings
- GET /trainer/bookings/calculate-price
- Inscripciones (Trainer)
- GET /trainer/enrollments
- POST /trainer/enrollments
- GET /trainer/enrollments/{id}
- DELETE /trainer/enrollments/{id}
- PATCH /trainer/enrollments/{id}/accept
- PATCH /trainer/enrollments/{id}/reject
- PATCH /trainer/enrollments/{id}/attendance
- Alumnos (Trainer)
- GET /trainer/students
- GET /trainer/students/{id}
- POST /trainer/students/{id}/assign
- Clientes (Trainer)
- GET /trainer/clients
- POST /trainer/clients
- GET /trainer/clients/{id}
- Canchas (Trainer)
- GET /trainer/courts
- Dashboard (Trainer)
- GET /trainer/dashboard/stats
- Tipos de Documento (Trainer)
- GET /trainer/document-types
- Tipos de Pago (Trainer)
- GET /trainer/payment-types
- Tipos de Reserva (Trainer)
- GET /trainer/reservation-types
- Tarifas de Clase (Trainer)
- GET /trainer/tariff-classes
- GET /trainer/tariff-classes/{id}
- Public (Público)
- Sudo (Super Administradores)
- Pagos (Cuenta de Usuario)
- GET /account/payments
- GET /account/payments/:id
- POST /account/payments
- Clientes (Admin)
- GET /admin/clients
- POST /admin/clients
- GET /admin/clients/{id}
- PATCH /admin/clients/{id}
- DELETE /admin/clients/{id}
- Canchas (Admin)
- GET /admin/courts
- POST /admin/courts
- GET /admin/courts/{id}
- PATCH /admin/courts/{id}
- DELETE /admin/courts/{id}
- Tipos de Cancha (Admin)
- GET /admin/court-types
- POST /admin/court-types
- GET /admin/court-types/{id}
- PATCH /admin/court-types/{id}
- DELETE /admin/court-types/{id}
- Tipos de Documento (Admin)
- GET /admin/document-types
- POST /admin/document-types
- GET /admin/document-types/{id}
- PATCH /admin/document-types/{id}
- DELETE /admin/document-types/{id}
- Tipos de Pago (Admin)
- GET /admin/payment-types
- POST /admin/payment-types
- GET /admin/payment-types/{id}
- PATCH /admin/payment-types/{id}
- DELETE /admin/payment-types/{id}
- Estados de Reserva (Admin)
- GET /admin/reservation-statuses
- POST /admin/reservation-statuses
- GET /admin/reservation-statuses/{id}
- PATCH /admin/reservation-statuses/{id}
- DELETE /admin/reservation-statuses/{id}
- Tipos de Reserva (Admin)
- GET /admin/reservation-types
- POST /admin/reservation-types
- GET /admin/reservation-types/{id}
- PATCH /admin/reservation-types/{id}
- DELETE /admin/reservation-types/{id}
- Tarifas (Admin)
- GET /admin/tariffs
- POST /admin/tariffs
- GET /admin/tariffs/{id}
- PATCH /admin/tariffs/{id}
- DELETE /admin/tariffs/{id}
- Tarifas de Clase (Admin)
- GET /admin/tariff-classes
- POST /admin/tariff-classes
- GET /admin/tariff-classes/{id}
- PATCH /admin/tariff-classes/{id}
- DELETE /admin/tariff-classes/{id}
- Dashboard (Admin)
- GET /admin/dashboard/stats
- Usuarios (Admin)
- GET /admin/users
- GET /admin/users/{uid}
- Account (Usuario Autenticado)
- Interfaces TypeScript
- Códigos de Estado HTTP
- Manejo de Errores
- Webhooks
Este documento describe la API REST de UnoSportClub implementada en functions/server.js con Express.js.
Base URL
Producción (API Público)
La API está disponible en producción en los siguientes subdominios:
-
Portal Principal:
-
Portal para usuarios finales
-
Panel de Administración:
-
Panel operativo para administradores y operadores
-
Super Administrador:
-
Consola de control para super usuarios (sudo)
Desarrollo Local
Para desarrollo local, la API está disponible en:
-
http://localhost:6100/api- Desarrollo local -
http://localhost:5005/api- Emulador de desarrollo alternativo -
http://localhost:5006/api- Emulador de desarrollo alternativo
O usando el proxy de Angular (configurado en proxy.conf.json):
/api
Nota:
* El servidor backend en producción se ejecuta con PM2 y está balanceado por Caddy.
* La documentación interactiva de la API (Swagger UI) está disponible en:
- Producción: https://app.unosportclub.com.co/api/api-docs
- QA: https://panel.qa.unosportclub.com.co/api/api-docs
- Desarrollo: http://localhost:6100/api/api-docs
* El esquema OpenAPI (JSON) está disponible en:
- Producción: https://app.unosportclub.com.co/api/api-docs.json
- QA: https://panel.qa.unosportclub.com.co/api/api-docs.json
- Desarrollo: http://localhost:6100/api/api-docs.json
* Los endpoints con localhost son exclusivamente para desarrollo local.
* Los endpoints con subdominios de unosportclub.com.co son el API público en producción.
* Esta documentación está basada en el esquema OpenAPI oficial (versión 3.0.0) y las interfaces TypeScript definidas en @cortex-ia-com-co/common.
* Recomendación: Para la documentación más actualizada y completa, consulta el esquema OpenAPI JSON directamente o usa Swagger UI para explorar la API de forma interactiva.
Autenticación
La API soporta dos métodos de autenticación:
Autenticación con Firebase Auth (Usuarios)
Para usuarios autenticados mediante Firebase Auth, el token debe enviarse en el header:
Authorization: Bearer [firebase-id-token]
Este método se usa para usuarios humanos que se autentican mediante Firebase Authentication.
Autenticación con API Key (Bots)
Para bots y sistemas automatizados, se puede usar autenticación mediante API Key enviando el valor de BOT_API_KEYS en el header:
X-Auth: [BOT_API_KEYS]
Características de la autenticación con API Key:
* El header debe ser X-Auth (no Authorization)
* El valor debe coincidir exactamente con la variable de entorno BOT_API_KEYS configurada en el servidor
* Otorga permisos completos: operator, admin, sudo, trainer, y bot
* Disponible en las rutas: /account/, /admin/, /trainer/, y /sudo/
* El usuario autenticado tendrá uid: "bot-api-key" y bot: true
Ejemplo de uso:
curl -H "X-Auth: tu-api-key-aqui" https://app.unosportclub.com.co/api/admin/clients
Nota: Algunos endpoints públicos (/public/*) no requieren autenticación.
Formatos de Datos
Fechas y Horas
La API utiliza diferentes formatos según el contexto:
-
Fechas: Formato ISO 8601
YYYY-MM-DD(ej:2024-01-15) -
Horas: Formato
HH:MMoHH:MM:SS(ej:18:00o18:00:00) -
Fecha y Hora: Formato ISO 8601 completo
YYYY-MM-DDTHH:MM:SSZ(ej:2024-01-15T18:00:00Z)
Campos de fecha/hora en reservas:
* checking: Fecha y hora de inicio en formato ISO 8601 completo
* checkout: Fecha y hora de fin en formato ISO 8601 completo
* checking_date: Fecha de inicio en formato YYYY-MM-DD (cuando se separa)
* checking_time: Hora de inicio en formato HH:MM:SS (cuando se separa)
* checkout_date: Fecha de fin en formato YYYY-MM-DD (cuando se separa)
* checkout_time: Hora de fin en formato HH:MM:SS (cuando se separa)
Nota: Algunos endpoints pueden devolver campos separados (checking_date, checking_time) mientras que otros usan campos combinados (checking). Consulta la respuesta específica de cada endpoint para más detalles.
Estructura de Endpoints
La API está organizada por roles y funcionalidades:
-
/account/*: Endpoints para usuarios autenticados (clientes) -
/admin/*: Endpoints para administradores y operadores -
/trainer/*: Endpoints para entrenadores -
/public/*: Endpoints públicos (sin autenticación) -
/sudo/*: Endpoints para super administradores
Endpoints por Rol
Account (Usuario Autenticado)
Los endpoints bajo /account/* permiten a los usuarios autenticados gestionar sus propios recursos.
GET /reservations
Obtiene la lista de reservas.
Query Parameters:
* client_id (opcional): Filtrar por cliente
* operator_id (opcional): Filtrar por operador
* court_id (opcional): Filtrar por cancha
* status (opcional): Filtrar por estado
* from (opcional): Fecha desde (ISO 8601)
* to (opcional): Fecha hasta (ISO 8601)
Response 200:
{
"data": [
{
"id": 1,
"operator_id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T08:00:00Z"
}
],
"total": 1
}
GET /reservations/:id
Obtiene una reserva específica.
Response 200:
{
"data": {
"id": 1,
"operator_id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T08:00:00Z"
}
}
POST /reservations
Crea una nueva reserva.
Request Body:
{
"operator_id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1"
}
Response 201:
{
"data": {
"id": 1,
"operator_id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T08:00:00Z"
}
}
PUT /reservations/:id
Actualiza una reserva existente.
Request Body:
{
"checking": "2024-01-15T10:30:00Z",
"checkout": "2024-01-15T12:30:00Z",
"notes": "Cancha 1 - Actualizado"
}
Response 200:
{
"data": {
"id": 1,
"operator_id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:30:00Z",
"checkout": "2024-01-15T12:30:00Z",
"notes": "Cancha 1 - Actualizado",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T09:00:00Z"
}
}
DELETE /reservations/:id
Elimina una reserva.
Response 204: No Content
Nota importante:
* Estos endpoints solo devuelven reservas del usuario autenticado
* Las reservas incluyen información agregada de pagos (total_paid, total_amount, is_payment_complete, can_add_payment)
* Los pagos dentro de las reservas incluyen tanto status (string) como statusBoolean (boolean) para compatibilidad
* Las reservas incluyen campos checking y checkout para mostrar fecha y hora de inicio y fin
* Los horarios están disponibles en slots de 30 minutos
* Las interfaces TypeScript correspondientes están en AccountBookingInterface y AccountBookingPaymentInterface del paquete @cortex-ia-com-co/common
GET /account/bookings
Obtiene las reservas del usuario autenticado con información detallada de pagos y paginación.
Query Parameters:
* page (opcional, default: 1): Número de página
* limit (opcional, default: 10): Cantidad de resultados por página
Response 200:
{
"bookings": [
{
"id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T08:00:00Z",
"court_name": "Cancha 1",
"reservation_type_name": "Libre",
"total_paid": 50000.00,
"total_amount": 50000.00,
"is_payment_complete": true,
"can_add_payment": false,
"payments": [
{
"id": 1,
"reservation_id": 1,
"payment_type_id": 1,
"payment_type_name": "Efectivo",
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": null,
"status": "completed",
"statusBoolean": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva"
}
]
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 15,
"totalPages": 2
}
}
Campos de información de pagos:
* total_paid: Suma total de pagos completados asociados a la reserva
* total_amount: Monto total requerido para la reserva
* is_payment_complete: Indica si el pago está completo (total_paid >= total_amount)
* can_add_payment: Indica si se pueden agregar más pagos a la reserva
* payments: Array de pagos asociados con información detallada
Formato dual de status en pagos:
* status: String con valores "pending" o "completed" (para compatibilidad con frontend)
* statusBoolean: Boolean equivalente (false = pending, true = completed)
Response 401:
{
"error": "No autenticado"
}
POST /account/bookings
Crea una nueva reserva para el cliente autenticado.
Request Body:
{
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1"
}
Campos requeridos:
* court_id: ID de la cancha (integer)
* reservation_type_id: ID del tipo de reserva (integer)
* checking: Fecha y hora de inicio (ISO 8601)
* checkout: Fecha y hora de fin (ISO 8601)
Campos opcionales:
* notes: Notas adicionales (string, nullable)
Response 201:
{
"id": 1,
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z",
"notes": "Cancha 1",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T08:00:00Z"
}
Response 400: Datos incompletos, fecha inválida o referencia inválida Response 401: No autenticado Response 404: Cliente no encontrado Response 409: Conflicto de reserva (cancha ocupada)
GET /account/bookings/calculate-price
Calcula el precio de una reserva con ajustes de tarifas usando función PostgreSQL.
Query Parameters:
* date (requerido): Fecha de la reserva (YYYY-MM-DD)
* checking (requerido): Hora de inicio (HH:MM)
* checkout (requerido): Hora de fin (HH:MM)
* court_id (requerido): ID de la cancha
* reservation_type_id (opcional): ID del tipo de reserva
* reservation_id (opcional): ID de la reserva (para edición)
Response 200:
{
"court": {
"id": 1,
"name": "Cancha 1",
"base_price": 50000.00
},
"date": "2024-01-15",
"checking": "10:00",
"checkout": "12:00",
"available": true,
"hours": 2.0,
"final_price": 50000.00,
"price_per_hour": 25000.00,
"applied_adjustments": [
{
"tariff_id": 1,
"description": "Descuento nocturno",
"adjustment": "-10%",
"adjusted_price": 45000.00
}
]
}
Campos de respuesta:
* court: Información de la cancha (id, name, base_price)
* date: Fecha de la reserva (YYYY-MM-DD)
* checking: Hora de inicio (HH:MM)
* checkout: Hora de fin (HH:MM)
* available: Indica si la cancha está disponible en ese horario
* hours: Número de horas de la reserva (decimal)
* final_price: Precio final calculado después de aplicar tarifas
* price_per_hour: Precio por hora calculado
* applied_adjustments: Array de ajustes de tarifa aplicados con información detallada
Nota: La función calcula el precio por periodos de 30 minutos aplicando tarifas según rangos de fechas y horas. La interfaz TypeScript correspondiente es CalculatePriceResponseInterface del paquete @cortex-ia-com-co/common.
GET /account/bookings/{bookingId}
Obtiene una reserva específica del usuario autenticado.
Response 200: Similar a GET /account/bookings pero con un solo objeto en lugar de array.
Response 400: ID de reserva inválido Response 401: No autenticado Response 404: Reserva no encontrada o no pertenece al usuario
GET /account/courts
Obtiene canchas disponibles con verificación de disponibilidad.
Query Parameters:
* checking (opcional): Fecha y hora de inicio para verificar disponibilidad (ISO 8601)
* checkout (opcional): Fecha y hora de fin para verificar disponibilidad (ISO 8601)
Response 200: Array de canchas con información de disponibilidad.
GET /account/reservation-types
Obtiene todos los tipos de reserva disponibles.
Response 200: Array de tipos de reserva (ReservationTypeInterface).
GET /account/payment-types
Obtiene todos los tipos de pago disponibles para el cliente.
Response 200: Array de tipos de pago (PaymentTypeInterface).
GET /account/stats
Obtiene estadísticas del usuario autenticado.
Response 200: Objeto con estadísticas del usuario (reservas, pagos, etc.). Response 401: No autenticado Response 403: Acceso denegado
GET /account/profile
Obtiene el perfil del usuario autenticado.
Response 200: Perfil del usuario obtenido exitosamente (FirebaseUserInterface).
Response 401: No autenticado
Response 403: Acceso denegado
PUT /account/profile
Actualiza el perfil del usuario autenticado.
Request Body:
{
"displayName": "Juan Pérez",
"phone": "+573001234567"
}
Campos opcionales:
* displayName: Nombre de visualización (string)
* phone: Teléfono de contacto (string)
Response 200: Perfil actualizado exitosamente. Response 401: No autenticado Response 403: Acceso denegado
GET /account/client
Obtiene los datos del cliente del usuario autenticado.
Response 200: Objeto ClientInterface del cliente autenticado.
Response 401: No autenticado Response 404: Cliente no encontrado
PATCH /account/client
Actualiza los datos del cliente del usuario autenticado.
Request Body:
{
"firstName": "Juan",
"lastName": "Pérez",
"document": "1234567890",
"documentTypeId": 1,
"address": "Calle 123",
"phone": "+573001234567"
}
Response 200: Cliente actualizado exitosamente.
POST /account/client
Crea un nuevo cliente para el usuario autenticado.
Request Body:
{
"email": "cliente@example.com",
"first_name": "Juan",
"last_name": "Pérez",
"document": "1234567890",
"document_type_id": 1,
"phone": "+573001234567",
"address": "Calle 123"
}
Campos requeridos:
* email: Email del cliente
* first_name: Nombre del cliente
* last_name: Apellido del cliente
* document: Número de documento
* document_type_id: ID del tipo de documento
Response 201: Cliente creado exitosamente. Response 400: Datos incompletos o usuario no encontrado Response 409: Cliente ya existe para este usuario
GET /account/classes
Obtiene lista de clases disponibles para inscripción.
Query Parameters:
* reservation_type_id (opcional): Filtrar por tipo de reserva. Siempre filtra por gestion=2.
Response 200: Lista de clases disponibles (filtradas por gestion=2).
Nota: Las clases disponibles son aquellas con reservation_type.gestion = 2 (clases de entrenamiento).
GET /account/classes/my-enrollments
Obtiene las inscripciones del cliente actual.
Response 200: Lista de inscripciones del cliente (EnrollmentInterface[]).
GET /account/classes/{id}
Obtiene detalles de una clase específica.
Response 200: Detalles de la clase (TrainingClassInterface).
Response 404: Clase no encontrada
POST /account/classes/{id}/enroll
Inscribirse en una clase.
Request Body:
{
"payments": [
{
"paymentTypeId": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456"
}
]
}
Response 201: Inscripción exitosa. Response 400: Error de validación Response 404: Clase no encontrada Response 409: Ya está inscrito en esta clase
Admin (Administradores y Operadores)
Los endpoints bajo /admin/* permiten la gestión completa del sistema para administradores y operadores.
Reservas (Admin)
Los endpoints de reservas permiten la gestión completa (CRUD) de reservas desde el panel de administración.
Nota importante:
* Las reservas pueden tener un client_id opcional (null para reservas de mantenimiento)
* Las reservas incluyen información de estado (reservation_status_id) y tipo (reservation_type_id)
* Los campos checking y checkout son fechas y horas en formato ISO 8601
* La interfaz TypeScript correspondiente es BookingInterface y BookingDetailInterface del paquete @cortex-ia-com-co/common
GET /admin/booking
Obtiene todas las reservas con filtros opcionales.
Query Parameters:
* client_id (opcional): Filtrar por ID de cliente
* court_id (opcional): Filtrar por ID de cancha
* limit (opcional, default: 100): Límite de resultados
* offset (opcional, default: 0): Offset para paginación
Response 200: Array de reservas (BookingInterface[]).
Nota: Este endpoint es un alias de /admin/bookings.
GET /admin/bookings
Obtiene todas las reservas con filtros opcionales.
Query Parameters:
* client_id (opcional): Filtrar por ID de cliente
* court_id (opcional): Filtrar por ID de cancha
* limit (opcional, default: 100): Límite de resultados
* offset (opcional, default: 0): Offset para paginación
Response 200: Array de reservas (BookingInterface[]).
GET /admin/booking/full
Obtiene reservas con información completa de pagos y precios.
Query Parameters:
* client_id (opcional): Filtrar por ID de cliente
* court_id (opcional): Filtrar por ID de cancha
* start_date (opcional): Filtrar por fecha de inicio (YYYY-MM-DD)
* end_date (opcional): Filtrar por fecha de fin (YYYY-MM-DD)
* active (opcional): Filtrar solo reservas activas (checkout > ahora)
* confirmed (opcional): Filtrar por estado confirmado (true = confirmadas, false = pendientes)
* limit (opcional, default: 1000): Límite de resultados
* offset (opcional, default: 0): Offset para paginación
Response 200: Array de reservas con información completa incluyendo total_amount, total_paid, total_debt.
POST /admin/booking
Crea una nueva reserva.
Request Body:
{
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"reservation_status_id": 1,
"checking": "2024-01-15T18:00:00Z",
"checkout": "2024-01-15T19:00:00Z",
"notes": "Notas adicionales"
}
Campos requeridos:
* court_id: ID de la cancha (integer)
* reservation_type_id: ID del tipo de reserva (integer)
* checking: Fecha y hora de inicio (ISO 8601)
* checkout: Fecha y hora de fin (ISO 8601)
Campos opcionales:
* client_id: ID del cliente (integer, nullable, opcional para reservas de mantenimiento)
* reservation_status_id: ID del estado de reserva (integer, nullable)
* notes: Notas adicionales (string, nullable)
Response 201: Reserva creada exitosamente (BookingInterface).
Response 400: Datos inválidos, incompletos o referencia inválida
Response 401: No autenticado
Response 409: Conflicto de reserva (cancha ocupada)
Nota: Este endpoint es un alias de /admin/bookings.
POST /admin/bookings
Crea una nueva reserva.
Request Body: Similar a POST /admin/booking.
Response 201: Reserva creada exitosamente (BookingInterface).
GET /admin/booking/{id}
Obtiene una reserva por ID con detalles completos.
Response 200: Reserva obtenida exitosamente con detalles completos (BookingDetailInterface).
Response 404: Reserva no encontrada
Nota: BookingDetailInterface incluye información adicional del cliente (client_first_name, client_last_name, client_email, client_phone, client_document, client_address) y de la cancha (court_base_price, court_type_name).
GET /admin/bookings/{id}
Obtiene una reserva por ID con detalles completos.
Response 200: Reserva obtenida exitosamente con detalles completos (BookingDetailInterface).
Response 404: Reserva no encontrada
PATCH /admin/booking/{id}
Edita una reserva por ID.
Request Body:
{
"client_id": 1,
"court_id": 1,
"reservation_type_id": 1,
"reservation_status_id": 1,
"checking": "2024-01-15T18:00:00Z",
"checkout": "2024-01-15T19:00:00Z",
"notes": "Notas actualizadas"
}
Response 200: Reserva actualizada exitosamente (BookingInterface).
Response 400: Datos inválidos
Response 401: No autenticado
Response 404: Reserva no encontrada
PATCH /admin/bookings/{id}
Edita una reserva por ID.
Request Body: Similar a PATCH /admin/booking/{id}.
Response 200: Reserva actualizada exitosamente (BookingInterface).
DELETE /admin/booking/{id}
Elimina una reserva por ID.
Response 204: Reserva eliminada exitosamente. Response 400: ID de reserva inválido Response 401: No autenticado Response 404: Reserva no encontrada
DELETE /admin/bookings/{id}
Elimina una reserva por ID.
Response 204: Reserva eliminada exitosamente.
DELETE /admin/booking
Elimina varias reservas.
Request Body:
{
"ids": ["1", "2", "3"]
}
Response 200: Reservas eliminadas exitosamente.
Nota: Este endpoint es un alias de /admin/bookings DELETE.
DELETE /admin/bookings
Elimina varias reservas.
Request Body: Similar a DELETE /admin/booking.
Response 200: Reservas eliminadas exitosamente.
GET /admin/booking/calculate-price
Calcula el precio de una reserva con ajustes de tarifas.
Query Parameters:
* date (requerido): Fecha de la reserva (YYYY-MM-DD)
* checking (requerido): Hora de inicio (HH:MM)
* checkout (requerido): Hora de fin (HH:MM)
* court_id (requerido): ID de la cancha
* reservation_type_id (opcional): ID del tipo de reserva
Response 200:
{
"court": {
"id": 1,
"name": "Cancha 1",
"base_price": 50000.00
},
"checking_date": "2024-01-15",
"checking_time": "18:00:00",
"checkout_date": "2024-01-15",
"checkout_time": "19:00:00",
"available": true,
"hours": 1.0,
"final_price": 50000.00,
"price_per_hour": 50000.00,
"applied_adjustments": []
}
Campos de respuesta:
* court: Información de la cancha (id, name, base_price)
* checking_date: Fecha de inicio (YYYY-MM-DD)
* checking_time: Hora de inicio (HH:MM:SS)
* checkout_date: Fecha de fin (YYYY-MM-DD)
* checkout_time: Hora de fin (HH:MM:SS)
* available: Indica si la cancha está disponible
* hours: Número de horas de la reserva (decimal)
* final_price: Precio final calculado después de aplicar tarifas
* price_per_hour: Precio por hora calculado
* applied_adjustments: Array de ajustes de tarifa aplicados
Response 400: Parámetros inválidos Response 404: Cancha no encontrada Response 500: Error interno del servidor
Nota: Este endpoint es un alias de /admin/bookings/calculate-price.
GET /admin/bookings/calculate-price
Calcula el precio de una reserva con ajustes de tarifas.
Query Parameters: Similar a GET /admin/booking/calculate-price.
Response 200: Ficha detallada con precio calculado. Estructura similar a GET /admin/booking/calculate-price pero con campos date, checking, checkout en lugar de checking_date, checking_time, checkout_date, checkout_time.
Nota: Este endpoint puede tener una estructura de respuesta ligeramente diferente para compatibilidad con versiones anteriores.
GET /admin/booking/{id}/price
Calcula el precio de una reserva existente por su ID.
Response 200: Ficha detallada con precio calculado. Estructura similar a GET /admin/booking/calculate-price con campos checking_date, checking_time, checkout_date, checkout_time.
Response 404: Reserva no encontrada
Response 500: Error interno del servidor
POST /admin/booking/validate
Valida fecha y disponibilidad de una reserva.
Request Body:
{
"court_id": 1,
"checking": "2024-01-15T18:00:00Z",
"checkout": "2024-01-15T19:00:00Z",
"reservation_id": null
}
Campos requeridos:
* court_id: ID de la cancha (integer)
* checking: Fecha y hora de inicio (ISO 8601)
* checkout: Fecha y hora de fin (ISO 8601)
Campos opcionales:
* reservation_id: ID de reserva existente (integer, nullable, excluir en validación)
Response 204: Validación exitosa (sin contenido). Response 400: Datos inválidos Response 409: Conflicto - fecha inválida o cancha no disponible
Pagos de Reservas (Admin)
Los endpoints de pagos permiten la gestión completa (CRUD) de pagos desde el panel de administración.
Nota importante:
* El campo status es un boolean: false = pendiente, true = completado
* Los pagos pueden estar asociados a reservas (reservation_id) o inscripciones (enrollment_id), pero no a ambas
* Los pagos pueden ser "huérfanos" (sin reservation_id ni enrollment_id) cuando se reciben desde webhooks antes de que se cree el recurso asociado
* El campo payment_type_id es opcional y puede ser null
* La interfaz TypeScript correspondiente es PaymentInterface del paquete @cortex-ia-com-co/common
GET /admin/payments
Obtiene la lista de pagos con filtros y paginación.
Query Parameters:
* search (opcional): Búsqueda por transaction_id o description (búsqueda ILIKE)
* status (opcional): Filtrar por estado del pago (boolean: false = pendiente, true = completado)
* reservation_id (opcional): Filtrar por ID de reservación
* limit (opcional, default: 100): Límite de resultados
* offset (opcional, default: 0): Offset para paginación
Nota: Los pagos pueden estar asociados a reservas (reservation_id) o inscripciones (enrollment_id).
Ordenamiento: Los resultados se ordenan primero por estado (pendientes primero) y luego por fecha descendente.
Response 200:
[
{
"id": 1,
"reservation_id": 1,
"enrollment_id": null,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva"
},
{
"id": 2,
"reservation_id": null,
"enrollment_id": null,
"payment_type_id": null,
"amount": 30000.00,
"transaction_id": "TXN-789012",
"gateway_response": null,
"status": false,
"date": "2024-01-11T10:00:00Z",
"description": "Pago huérfano"
}
]
GET /admin/payments/stats
Obtiene estadísticas agregadas de pagos.
Response 200:
{
"total": 150,
"pending": 10,
"completed": 130,
"orphan_payments": 8,
"total_amount": 7500000.00,
"completed_amount": 6500000.00,
"by_status": {
"completed": 130,
"pending": 10,
"failed": 0,
"refunded": 0
}
}
Campos de respuesta:
* total: Total de pagos en el sistema
* pending: Cantidad de pagos pendientes (status = false)
* completed: Cantidad de pagos completados (status = true)
* orphan_payments: Cantidad de pagos sin reservation_id ni enrollment_id asociado
* total_amount: Suma total de todos los pagos
* completed_amount: Suma total de pagos completados
* by_status: Desglose por estado (nota: failed y refunded no están implementados actualmente)
GET /admin/payments/:id
Obtiene un pago específico por ID.
Response 200:
{
"id": 1,
"reservation_id": 1,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva"
}
Response 404:
{
"error": "Pago no encontrado"
}
GET /admin/payments/transaction/:transaction_id
Obtiene un pago por transaction_id del gateway de pago.
Response 200:
{
"id": 1,
"reservation_id": 1,
"enrollment_id": null,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva"
}
Response 404:
{
"error": "Pago no encontrado"
}
GET /admin/booking/{bookingId}/payment
Lista todos los pagos de una reserva.
Response 200: Array de pagos de la reserva (PaymentInterface[]).
Response 404: Reserva no encontrada
Response 500: Error interno del servidor
POST /admin/booking/{bookingId}/payment
Crea un nuevo pago para una reserva.
Request Body:
{
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"status": false,
"description": "Pago de reserva",
"gateway_response": null
}
Campos requeridos:
* amount: Monto del pago (number, decimal)
* transaction_id: ID de transacción del gateway de pago (string)
Campos opcionales:
* payment_type_id: ID del tipo de pago (integer, nullable)
* status: Estado del pago (boolean, default: false)
* description: Descripción del pago (string, nullable)
* gateway_response: Respuesta completa del gateway de pago (string, nullable)
Response 201: Pago creado exitosamente (PaymentInterface).
Response 400: Datos inválidos
Response 404: Reserva no encontrada
Response 500: Error interno del servidor
Nota: El reservation_id se toma automáticamente del parámetro de ruta bookingId.
GET /admin/booking/{bookingId}/payment/{paymentId}
Obtiene un pago específico de una reserva.
Response 200: Pago obtenido exitosamente (PaymentInterface).
Response 404: Reserva o pago no encontrado
Response 500: Error interno del servidor
PATCH /admin/booking/{bookingId}/payment/{paymentId}
Actualiza un pago de una reserva.
Request Body:
{
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"status": true,
"description": "Pago actualizado",
"gateway_response": "{\"status\":\"completed\"}"
}
Response 200: Pago actualizado exitosamente (PaymentInterface).
Response 400: Datos inválidos
Response 404: Reserva o pago no encontrado
Response 500: Error interno del servidor
DELETE /admin/booking/{bookingId}/payment
Elimina un pago de una reserva.
Query Parameters:
* paymentId (requerido): ID del pago a eliminar
Response 200: Pago eliminado exitosamente. Response 404: Reserva o pago no encontrado Response 500: Error interno del servidor
POST /admin/payments
Crea un nuevo pago. Útil para registrar pagos manuales o sincronizar pagos desde sistemas externos.
Request Body:
{
"reservation_id": 1,
"enrollment_id": null,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"status": true,
"description": "Pago de reserva",
"gateway_response": "{\"status\":\"completed\"}"
}
Campos requeridos:
* amount: Monto del pago (number)
* transaction_id: ID de transacción del gateway (string)
* status: Estado del pago (boolean)
Campos opcionales:
* reservation_id: ID de la reservación asociada (integer, nullable, mutuamente exclusivo con enrollment_id)
* enrollment_id: ID de la inscripción asociada (integer, nullable, mutuamente exclusivo con reservation_id)
* payment_type_id: ID del tipo de pago (integer, nullable)
* description: Descripción del pago (string, nullable)
* gateway_response: Respuesta completa del gateway (string, nullable)
Validaciones:
* Debe proporcionarse reservation_id O enrollment_id, pero no ambos
* Si se proporciona reservation_id, debe existir en la tabla reservation
* Si se proporciona enrollment_id, debe existir en la tabla enrollment
* El transaction_id debe ser una cadena no vacía
Response 201:
{
"id": 1,
"reservation_id": 1,
"enrollment_id": null,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva"
}
Response 400:
{
"error": "Datos incompletos",
"message": "amount y transaction_id son requeridos"
}
PATCH /admin/payments/:id
Actualiza un pago existente. Permite actualizar campos específicos sin requerir todos los campos.
Request Body:
{
"reservation_id": 2,
"enrollment_id": null,
"status": true,
"description": "Pago actualizado"
}
Campos actualizables:
* reservation_id: Asignar o cambiar la reservación asociada (integer, nullable, mutuamente exclusivo con enrollment_id)
* enrollment_id: Asignar o cambiar la inscripción asociada (integer, nullable, mutuamente exclusivo con reservation_id)
* payment_type_id: Cambiar el tipo de pago (integer, nullable)
* status: Actualizar el estado del pago (boolean)
* description: Actualizar la descripción (string, nullable)
Validaciones:
* Si se proporciona reservation_id, debe existir en la tabla reservation y no puede tener enrollment_id simultáneamente
* Si se proporciona enrollment_id, debe existir en la tabla enrollment y no puede tener reservation_id simultáneamente
* Al menos un campo debe ser proporcionado para actualizar
Response 200:
{
"id": 1,
"reservation_id": 2,
"enrollment_id": null,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago actualizado"
}
Response 400:
{
"error": "Datos incompletos",
"message": "Debe proporcionar al menos un campo para actualizar"
}
Response 404:
{
"error": "Pago no encontrado"
}
DELETE /admin/payments/:id
Elimina un pago del sistema. Use con precaución, ya que esto elimina permanentemente el registro del pago.
Response 204: No Content (éxito)
Response 404:
{
"error": "Pago no encontrado"
}
GET /admin/classes
Obtiene lista de clases (admin).
Response 200: Lista de clases (TrainingClassInterface[]).
POST /admin/classes
Crea una nueva clase (admin).
Request Body:
{
"user_id": 1,
"title": "Clase de Fútbol",
"description": "Clase de entrenamiento",
"start_time": "2024-01-15T10:00:00Z",
"end_time": "2024-01-15T12:00:00Z",
"start_date": "2024-01-15",
"end_date": "2024-03-15",
"class_start_time": "10:00:00",
"recurrence_days": ["MO", "WE", "FR"]
}
Campos requeridos:
* title: Título de la clase
* start_time: Fecha y hora de inicio
* end_time: Fecha y hora de fin
* start_date: Fecha de inicio del período
* end_date: Fecha de fin del período
* class_start_time: Hora de inicio de cada clase
* recurrence_days: Array de días de recurrencia (MO, TU, WE, TH, FR, SA, SU)
Campos opcionales:
* user_id: ID del entrenador (opcional, usa admin actual)
* description: Descripción de la clase
Response 201: Clase creada exitosamente.
GET /admin/classes/{id}
Obtiene una clase específica (admin).
Response 200: Datos de la clase (TrainingClassInterface).
Response 404: Clase no encontrada
PATCH /admin/classes/{id}/cancel
Cancela una clase (admin).
Response 200: Clase cancelada exitosamente.
PATCH /admin/classes/{id}/complete
Marca una clase como completada (admin).
Response 200: Clase marcada como completada exitosamente.
GET /admin/enrollments
Obtiene lista de inscripciones (admin).
Query Parameters:
* class_id (opcional): Filtrar inscripciones por clase
* status (opcional): Filtrar inscripciones por estado (boolean: true = activo, false = inactivo)
Response 200: Lista de inscripciones (EnrollmentInterface[]).
POST /admin/enrollments
Crea una nueva inscripción (admin).
Request Body:
{
"class_id": 1,
"client_id": 1,
"payment_type_id": 1,
"payment_amount": 50000.00,
"payment_reference": "TXN-123456"
}
Campos requeridos:
* class_id: ID de la clase
* client_id: ID del cliente
Campos opcionales:
* payment_type_id: ID del tipo de pago
* payment_amount: Monto del pago
* payment_reference: Referencia de la transacción
Response 201: Inscripción creada exitosamente. Response 400: Datos inválidos Response 404: Clase no encontrada
GET /admin/enrollments/{id}
Obtiene una inscripción específica (admin).
Response 200: Datos de la inscripción (EnrollmentInterface).
Response 404: Inscripción no encontrada
DELETE /admin/enrollments/{id}
Elimina una inscripción (admin).
Response 200: Inscripción eliminada exitosamente.
PATCH /admin/enrollments/{id}/accept
Acepta una inscripción (admin).
Response 200: Inscripción aceptada exitosamente. Response 400: La inscripción no está en estado pendiente
PATCH /admin/enrollments/{id}/reject
Rechaza una inscripción (admin).
Request Body:
{
"reason": "Cupo lleno"
}
Response 200: Inscripción rechazada exitosamente.
PATCH /admin/enrollments/{id}/attendance
Registra asistencia de un alumno (admin).
Request Body:
{
"attendance_status": "present"
}
Valores permitidos: "present" o "absent"
Response 200: Asistencia registrada exitosamente. Response 400: La inscripción no está aceptada
POST /admin/notifications/token
Registra o actualiza token FCM para usuario (admin).
Request Body:
{
"userId": "firebase-uid-123",
"token": "fcm-token-abc123"
}
Campos requeridos:
* userId: Firebase Auth UID del usuario
* token: Token FCM del dispositivo
Response 200: Token FCM registrado exitosamente. Response 400: Datos incompletos
DELETE /admin/notifications/token
Elimina token FCM del usuario autenticado (admin).
Response 200: Token FCM eliminado exitosamente. Response 404: Token no encontrado
POST /admin/notifications/send
Envia notificación push a un cliente específico.
Request Body:
{
"clientId": 1,
"title": "Título de la notificación",
"body": "Cuerpo de la notificación",
"url": "/reservations/1"
}
Campos requeridos:
* clientId: ID del cliente al que se enviará la notificación
Campos opcionales:
* title: Título de la notificación
* body: Cuerpo de la notificación
* url: URL a la que navegar al hacer clic
Response 200: Notificación enviada exitosamente. Response 400: Datos incompletos Response 404: Cliente o usuario no encontrado
Nota: La interfaz TypeScript correspondiente es PushNotificationPayload del paquete @cortex-ia-com-co/common.
Trainer (Entrenadores)
Los endpoints bajo /trainer/* permiten a los entrenadores gestionar sus clases y alumnos.
GET /trainer/classes
Obtiene lista de clases del entrenador.
Response 200: Lista de clases (TrainingClassInterface[]).
POST /trainer/classes
Crea una nueva clase.
Request Body: Similar a POST /admin/classes pero sin user_id (usa el entrenador autenticado).
Response 201: Clase creada exitosamente.
GET /trainer/classes/{id}
Obtiene una clase específica.
Response 200: Datos de la clase (TrainingClassInterface).
Response 404: Clase no encontrada
PATCH /trainer/classes/{id}/complete
Marca una clase como completada.
Response 200: Clase marcada como completada exitosamente.
GET /trainer/bookings
Obtiene lista de reservas del entrenador.
Query Parameters:
* court_id (opcional): Filtrar por cancha específica
* from (opcional): Fecha de inicio para filtrar reservas (ISO 8601)
* to (opcional): Fecha de fin para filtrar reservas (ISO 8601)
Response 200: Lista de reservas (excluye canceladas).
POST /trainer/bookings
Crea una reserva para el entrenador.
Request Body: Similar a POST /account/bookings.
Response 201: Reserva creada exitosamente.
GET /trainer/bookings/calculate-price
Calcula el precio de una reserva con ajustes de tarifas.
Query Parameters:
* date (requerido): Fecha de la reserva (YYYY-MM-DD)
* checking (requerido): Hora de inicio (HH:MM)
* checkout (requerido): Hora de fin (HH:MM)
* court_id (requerido): ID de la cancha
* reservation_type_id (opcional): ID del tipo de reserva
Response 200: Ficha detallada con precio calculado (CalculatePriceResponseInterface).
Response 400: Parámetros inválidos
Response 404: Cancha no encontrada
Response 500: Error interno del servidor
GET /trainer/enrollments
Obtiene lista de inscripciones del entrenador.
Query Parameters:
* class_id (opcional): Filtrar inscripciones por clase
* status (opcional): Filtrar inscripciones por estado (boolean)
Response 200: Lista de inscripciones (EnrollmentInterface[]).
POST /trainer/enrollments
Crea una nueva inscripción.
Request Body:
{
"class_id": 1,
"client_id": 1
}
Response 201: Inscripción creada exitosamente. Response 400: Datos inválidos Response 404: Clase no encontrada
GET /trainer/enrollments/{id}
Obtiene una inscripción específica.
Response 200: Datos de la inscripción (EnrollmentInterface).
Response 404: Inscripción no encontrada
DELETE /trainer/enrollments/{id}
Elimina una inscripción.
Response 200: Inscripción eliminada exitosamente. Response 400: No se puede eliminar (fecha pasada o no creada por el trainer)
PATCH /trainer/enrollments/{id}/accept
Acepta una inscripción.
Response 200: Inscripción aceptada exitosamente.
PATCH /trainer/enrollments/{id}/reject
Rechaza una inscripción.
Request Body:
{
"reason": "Cupo lleno"
}
Response 200: Inscripción rechazada exitosamente.
PATCH /trainer/enrollments/{id}/attendance
Registra asistencia de un alumno.
Request Body:
{
"attendance_status": "present"
}
Response 200: Asistencia registrada exitosamente.
GET /trainer/students
Obtiene lista de alumnos del entrenador.
Query Parameters:
* class_id (opcional): Filtrar alumnos por clase específica
Response 200: Lista de alumnos (StudentInterface[]).
GET /trainer/students/{id}
Obtiene un alumno específico.
Response 200: Datos del alumno (StudentInterface).
Response 404: Alumno no encontrado
POST /trainer/students/{id}/assign
Asigna un alumno a una clase.
Request Body:
{
"class_id": 1
}
Response 201: Alumno asignado exitosamente. Response 400: Datos inválidos Response 404: Clase o alumno no encontrado
GET /trainer/clients
Obtiene lista de clientes con búsqueda.
Query Parameters:
* search (opcional): Búsqueda por email, display_name, first_name, last_name, document o phone
* limit (opcional, default: 20): Límite de resultados
* offset (opcional, default: 0): Offset para paginación
Response 200: Lista de clientes (ClientInterface[]).
POST /trainer/clients
Crea un nuevo cliente.
Request Body: Similar a POST /admin/clients.
Response 201: Cliente creado exitosamente.
GET /trainer/clients/{id}
Obtiene un cliente específico.
Response 200: Datos del cliente (ClientInterface).
Response 404: Cliente no encontrado
GET /trainer/courts
Obtiene lista de canchas disponibles.
Response 200: Lista de canchas (CourtInterface[]).
GET /trainer/dashboard/stats
Obtiene estadísticas del dashboard del entrenador.
Response 200: Estadísticas del dashboard.
GET /trainer/document-types
Obtiene todos los tipos de documento disponibles.
Response 200: Lista de tipos de documento (DocumentTypeInterface[]).
GET /trainer/payment-types
Obtiene todos los tipos de pago disponibles.
Response 200: Lista de tipos de pago (PaymentTypeInterface[]).
GET /trainer/reservation-types
Obtiene todos los tipos de reserva disponibles.
Response 200: Lista de tipos de reserva (ReservationTypeInterface[]).
Sudo (Super Administradores)
Los endpoints bajo /sudo/* son exclusivos para super administradores con permisos completos.
GET /sudo/users
Obtiene todos los usuarios de Firebase Auth (solo para administradores).
Query Parameters:
* maxResults (opcional, default: 1000): Número máximo de resultados (máximo 1000)
* pageToken (opcional): Token para paginación
Response 200: Lista de usuarios con paginación (UsersListResponseInterface).
Response 403: No tienes permisos de administrador
POST /sudo/users
Crea un nuevo usuario en Firebase Auth.
Request Body:
{
"email": "usuario@example.com",
"password": "password123",
"displayName": "Usuario",
"disabled": false,
"emailVerified": false,
"role": "admin",
"trainer": false
}
Campos requeridos:
* email: Email del usuario
* password: Contraseña del usuario
Campos opcionales:
* displayName: Nombre para mostrar
* disabled: Si el usuario está deshabilitado
* emailVerified: Si el email está verificado
* role: Rol principal ("admin", "operator", "sudo", "trainer")
* trainer: Indica si el usuario tendrá rol de entrenador (boolean)
Response 201: Usuario creado exitosamente (FirebaseUserInterface).
Response 400: Datos inválidos (email duplicado, formato inválido, etc.)
GET /sudo/users/{uid}
Obtiene un usuario específico de Firebase Auth.
Response 200: Usuario obtenido exitosamente (FirebaseUserInterface).
Response 404: Usuario no encontrado
PUT /sudo/users/{uid}
Actualiza un usuario de Firebase Auth.
Request Body: Similar a POST pero con campos opcionales.
Response 200: Usuario actualizado exitosamente.
DELETE /sudo/users/{uid}
Elimina un usuario de Firebase Auth.
Response 204: Usuario eliminado exitosamente. Response 404: Usuario no encontrado
Pagos (Cuenta de Usuario)
Los endpoints de pagos de cuenta permiten a los usuarios autenticados gestionar sus propios pagos asociados a sus reservas.
Nota importante:
* Estos endpoints solo devuelven pagos asociados a reservas del usuario autenticado
* El campo status es un boolean: false = pendiente, true = completado
* Los pagos incluyen información adicional de la reserva asociada (court_name, checking, checkout)
* Validación de pagos para confirmar reserva: Para confirmar una reserva, todos los pagos asociados deben tener status: true (completados) y el monto total pagado debe cubrir el precio total de la reserva
GET /account/payments
Obtiene el historial de pagos del usuario autenticado con paginación.
Query Parameters:
* page (opcional, default: 1): Número de página
* limit (opcional, default: 10): Cantidad de resultados por página
Response 200:
{
"payments": [
{
"id": 1,
"reservation_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva",
"court_name": "Cancha 1",
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3
}
}
Campos adicionales en respuesta:
* court_name: Nombre de la cancha de la reserva asociada
* checking: Fecha y hora de inicio de la reserva
* checkout: Fecha y hora de fin de la reserva
GET /account/payments/:id
Obtiene un pago específico del usuario autenticado.
Response 200:
{
"id": 1,
"reservation_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": "{\"status\":\"completed\"}",
"status": true,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva",
"court_name": "Cancha 1",
"checking": "2024-01-15T10:00:00Z",
"checkout": "2024-01-15T12:00:00Z"
}
Response 403:
{
"error": "Acceso denegado",
"message": "Este pago no pertenece al usuario autenticado"
}
Response 404:
{
"error": "Pago no encontrado"
}
POST /account/payments
Crea un nuevo pago asociado a una reserva del cliente autenticado. El frontend debe asegurarse de que la reserva ya exista y pertenezca al cliente actual.
Request Body:
{
"reservation_id": 1,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"description": "Pago de reserva"
}
Campos requeridos:
* reservation_id: ID de la reserva asociada (integer)
* payment_type_id: ID del tipo de pago (integer)
* amount: Monto del pago (number, debe ser mayor a 0)
* transaction_id: ID de transacción del gateway (string, no vacío)
Campos opcionales:
* description: Descripción del pago (string, nullable)
Validaciones:
* La reserva debe existir y pertenecer al cliente del usuario autenticado
* El transaction_id debe ser una cadena no vacía
* El amount debe ser un número mayor a 0
* Los IDs deben ser numéricos válidos
Response 201:
{
"id": 1,
"reservation_id": 1,
"payment_type_id": 1,
"amount": 50000.00,
"transaction_id": "TXN-123456",
"gateway_response": null,
"status": false,
"date": "2024-01-10T08:00:00Z",
"description": "Pago de reserva"
}
Response 400:
{
"error": "Datos incompletos",
"message": "reservation_id, payment_type_id, amount y transaction_id son requeridos"
}
Response 403:
{
"error": "Acceso denegado",
"message": "La reserva no pertenece al usuario autenticado"
}
GET /admin/clients
Obtiene todos los clientes.
Query Parameters:
* search (opcional): Búsqueda por email o display_name
* limit (opcional, default: 100): Límite de resultados
* offset (opcional, default: 0): Offset para paginación
Response 200: Lista de clientes (ClientInterface[]).
POST /admin/clients
Crea un nuevo cliente.
Request Body:
{
"user_id": 1,
"email": "cliente@example.com",
"display_name": "Juan Pérez",
"first_name": "Juan",
"last_name": "Pérez",
"phone": "+573001234567",
"document": "1234567890",
"document_type_id": 1,
"address": "Calle 123"
}
Campos requeridos:
* first_name: Nombre del cliente
* last_name: Apellido del cliente
* document: Número de documento
* document_type_id: ID del tipo de documento
Campos opcionales:
* user_id: ID del usuario existente en la base de datos (user.id). Opcional si se proporciona email
* email: Email del nuevo usuario (opcional si se proporciona user_id). Se creará el usuario en Firebase Auth con contraseña aleatoria y se enviará un email con link para establecer contraseña
* display_name: Nombre para mostrar del usuario (solo si se proporciona email)
* phone: Teléfono del cliente (opcional). Se vinculará al usuario en Firebase Auth
* address: Dirección del cliente
Response 201: Cliente creado exitosamente (ClientInterface).
Response 400: Datos inválidos
GET /admin/clients/{id}
Obtiene un cliente por ID.
Response 200: Cliente encontrado (ClientInterface).
Response 404: Cliente no encontrado
PATCH /admin/clients/{id}
Edita un cliente por ID.
Request Body:
{
"first_name": "Juan",
"last_name": "Pérez",
"document": "1234567890",
"document_type_id": 1,
"address": "Calle 123"
}
Response 200: Cliente actualizado exitosamente.
GET /admin/courts
Obtiene todas las canchas.
Query Parameters:
* search (opcional): Búsqueda por nombre
Response 200: Lista de canchas (CourtInterface[]).
POST /admin/courts
Crea una nueva cancha.
Request Body:
{
"name": "Cancha 1",
"court_type_id": 1,
"cost": 10000.00,
"price": 50000.00
}
Campos requeridos:
* name: Nombre de la cancha
* court_type_id: ID del tipo de cancha
Response 201: Cancha creada exitosamente (CourtInterface).
Response 400: Datos inválidos
GET /admin/courts/{id}
Obtiene una cancha por ID.
Response 200: Cancha encontrada (CourtInterface).
Response 404: Cancha no encontrada
GET /admin/court-types
Obtiene todos los tipos de cancha.
Query Parameters:
* search (opcional): Búsqueda por nombre o descripción
Response 200: Lista de tipos de cancha (CourtTypeInterface[]).
POST /admin/court-types
Crea un nuevo tipo de cancha.
Request Body:
{
"name": "Fútbol",
"description": "Cancha de fútbol"
}
Campos requeridos:
* name: Nombre del tipo de cancha
Response 201: Tipo de cancha creado exitosamente (CourtTypeInterface).
Response 400: Datos inválidos
GET /admin/court-types/{id}
Obtiene un tipo de cancha por ID.
Response 200: Tipo de cancha encontrado (CourtTypeInterface).
Response 404: Tipo de cancha no encontrado
PATCH /admin/court-types/{id}
Actualiza un tipo de cancha.
Response 200: Tipo de cancha actualizado exitosamente.
DELETE /admin/court-types/{id}
Elimina un tipo de cancha.
Response 204: Tipo de cancha eliminado exitosamente.
GET /admin/document-types
Obtiene todos los tipos de documento.
Query Parameters:
* search (opcional): Búsqueda por nombre o descripción
Response 200: Lista de tipos de documento (DocumentTypeInterface[]).
POST /admin/document-types
Crea un nuevo tipo de documento.
Request Body:
{
"name": "Cédula de Ciudadanía",
"description": "Documento de identidad colombiano"
}
Campos requeridos:
* name: Nombre del tipo de documento
Response 201: Tipo de documento creado exitosamente (DocumentTypeInterface).
Response 400: Datos inválidos
GET /admin/document-types/{id}
Obtiene un tipo de documento por ID.
Response 200: Tipo de documento encontrado (DocumentTypeInterface).
Response 404: Tipo de documento no encontrado
PATCH /admin/document-types/{id}
Actualiza un tipo de documento.
Response 200: Tipo de documento actualizado exitosamente.
DELETE /admin/document-types/{id}
Elimina un tipo de documento.
Response 204: Tipo de documento eliminado exitosamente.
GET /admin/payment-types
Obtiene todos los tipos de pago.
Query Parameters:
* search (opcional): Búsqueda por nombre o descripción
Response 200: Lista de tipos de pago (PaymentTypeInterface[]).
POST /admin/payment-types
Crea un nuevo tipo de pago.
Request Body:
{
"name": "Efectivo",
"description": "Pago en efectivo"
}
Campos requeridos:
* name: Nombre del tipo de pago
Response 201: Tipo de pago creado exitosamente (PaymentTypeInterface).
Response 400: Datos inválidos
GET /admin/payment-types/{id}
Obtiene un tipo de pago por ID.
Response 200: Tipo de pago encontrado (PaymentTypeInterface).
Response 404: Tipo de pago no encontrado
PATCH /admin/payment-types/{id}
Actualiza un tipo de pago.
Response 200: Tipo de pago actualizado exitosamente.
DELETE /admin/payment-types/{id}
Elimina un tipo de pago.
Response 204: Tipo de pago eliminado exitosamente.
GET /admin/reservation-statuses
Obtiene todos los estados de reserva.
Query Parameters:
* search (opcional): Búsqueda por nombre o descripción
Response 200: Lista de estados de reserva (ReservationStatusInterface[]).
POST /admin/reservation-statuses
Crea un nuevo estado de reserva.
Request Body:
{
"name": "Confirmada",
"description": "Reserva confirmada",
"color": "#10b981"
}
Campos requeridos:
* name: Nombre del estado
* color: Color hexadecimal para representación visual
Response 201: Estado de reserva creado exitosamente (ReservationStatusInterface).
Response 400: Datos inválidos
GET /admin/reservation-statuses/{id}
Obtiene un estado de reserva por ID.
Response 200: Estado de reserva encontrado (ReservationStatusInterface).
Response 404: Estado de reserva no encontrado
PATCH /admin/reservation-statuses/{id}
Actualiza un estado de reserva.
Response 200: Estado de reserva actualizado exitosamente.
DELETE /admin/reservation-statuses/{id}
Elimina un estado de reserva.
Response 204: Estado de reserva eliminado exitosamente.
GET /admin/reservation-types
Obtiene todos los tipos de reserva.
Query Parameters:
* search (opcional): Búsqueda por nombre o descripción
Response 200: Lista de tipos de reserva (ReservationTypeInterface[]).
POST /admin/reservation-types
Crea un nuevo tipo de reserva.
Request Body:
{
"name": "Libre",
"description": "Reserva libre"
}
Campos requeridos:
* name: Nombre del tipo de reserva
Response 201: Tipo de reserva creado exitosamente (ReservationTypeInterface).
Response 400: Datos inválidos
GET /admin/reservation-types/{id}
Obtiene un tipo de reserva por ID.
Response 200: Tipo de reserva encontrado (ReservationTypeInterface).
Response 404: Tipo de reserva no encontrado
PATCH /admin/reservation-types/{id}
Actualiza un tipo de reserva.
Response 200: Tipo de reserva actualizado exitosamente.
DELETE /admin/reservation-types/{id}
Elimina un tipo de reserva.
Response 204: Tipo de reserva eliminado exitosamente.
GET /admin/tariffs
Obtiene todas las tarifas.
Query Parameters:
* search (opcional): Búsqueda por descripción
* court_id (opcional): Filtrar por cancha
* reservation_type_id (opcional): Filtrar por tipo de reserva
Response 200: Lista de tarifas (TariffInterface[]).
POST /admin/tariffs
Crea una nueva tarifa.
Request Body:
{
"court_id": 1,
"reservation_type_id": 1,
"rrule": null,
"start_date": "2024-01-01",
"end_date": "2024-12-31",
"start_time": "18:00:00",
"end_time": "22:00:00",
"adjustment": "-10%",
"description": "Descuento nocturno",
"is_active": true
}
Campos requeridos:
* adjustment: Ajuste (ej: "-10%", "5000", "-2000", "15%")
* is_active: Si la tarifa está activa (boolean)
Campos opcionales:
* court_id: ID de la cancha (null = todas las canchas)
* reservation_type_id: ID del tipo de reserva (null = todos los tipos)
* rrule: Regla recurrente según RFC 5545 (RRULE)
* start_date: Fecha de inicio del período (YYYY-MM-DD)
* end_date: Fecha de fin del período (YYYY-MM-DD)
* start_time: Hora de inicio del rango horario (HH:MM:SS)
* end_time: Hora de fin del rango horario (HH:MM:SS)
* description: Descripción de la tarifa
Response 201: Tarifa creada exitosamente (TariffInterface).
Response 400: Datos inválidos
GET /admin/tariffs/{id}
Obtiene una tarifa por ID.
Response 200: Tarifa encontrada (TariffInterface).
Response 404: Tarifa no encontrada
GET /admin/tariff-classes
Obtiene todas las tarifas de clase.
Query Parameters:
* court_type_id (opcional): Filtrar por tipo de cancha
* reservation_type_id (opcional): Filtrar por tipo de reserva
Response 200: Lista de tarifas de clase (TariffClassInterface[]).
POST /admin/tariff-classes
Crea una nueva tarifa de clase.
Request Body:
{
"court_type_id": 1,
"reservation_type_id": 2,
"single_price": 25000.00,
"total_price": 50000.00,
"max_capacity": 20
}
Campos requeridos:
* court_type_id: ID del tipo de cancha
* reservation_type_id: ID del tipo de reserva
* single_price: Precio por persona
* total_price: Precio total de la clase
* max_capacity: Capacidad máxima de la clase
Response 201: Tarifa de clase creada exitosamente (TariffClassInterface).
Response 400: Datos inválidos
GET /admin/tariff-classes/{id}
Obtiene una tarifa de clase por ID.
Response 200: Tarifa de clase encontrada (TariffClassInterface).
Response 404: Tarifa de clase no encontrada
PATCH /admin/tariff-classes/{id}
Actualiza una tarifa de clase.
Response 200: Tarifa de clase actualizada exitosamente.
DELETE /admin/tariff-classes/{id}
Elimina una tarifa de clase.
Response 204: Tarifa de clase eliminada exitosamente.
GET /admin/dashboard/stats
Obtiene estadísticas del dashboard.
Response 200: Estadísticas del dashboard (DashboardStatsWithRecentInterface).
Campos de respuesta:
* clients: Estadísticas de clientes (total, verified, unverified)
* courts: Estadísticas de canchas (total)
* reservations: Estadísticas de reservas (total, today, this_week, this_month)
* payments: Estadísticas de pagos (total, total_amount, completed_amount, pending)
* recent_reservations: Array de reservas recientes
* recent_payments: Array de pagos recientes
GET /admin/users
Obtiene usuarios de Firebase Auth (para operadores y administradores).
Query Parameters:
* maxResults (opcional, default: 50): Número máximo de resultados (máximo 1000)
* pageToken (opcional): Token para paginación
Response 200: Lista de usuarios con paginación (UsersListResponseInterface).
Interfaces TypeScript
Todas las interfaces TypeScript están definidas en el paquete @cortex-ia-com-co/common y están disponibles para importar:
import {
BookingInterface,
BookingDetailInterface,
BookingFullInterface,
AccountBookingInterface,
AccountBookingPaymentInterface,
AccountPaymentInterface,
PaymentInterface,
ClientInterface,
TrainingClassInterface,
EnrollmentInterface,
TariffClassInterface,
ReservationTypeInterface,
ReservationStatusInterface,
PaymentTypeInterface,
DocumentTypeInterface,
CourtInterface,
CourtTypeInterface,
TariffInterface,
CalculatePriceResponseInterface,
PaginationInterface,
PaginatedResponseInterface,
StudentInterface,
FirebaseUserInterface,
UserInterface,
UsersListResponseInterface,
DashboardStatsWithRecentInterface,
PushNotificationPayload,
ErrorResponseInterface
} from '@cortex-ia-com-co/common';
Interfaces principales:
Reservas
-
BookingInterface: Estructura base de reservas con campos básicos (id,client_id,court_id,reservation_type_id,checking,checkout,notes, etc.) -
BookingDetailInterface: ExtiendeBookingInterfacecon información completa del cliente (client_first_name,client_last_name,client_email,client_phone,client_document,client_address) y de la cancha (court_base_price,court_type_name), además de pagos asociados -
BookingFullInterface: Reservas con información completa de pagos y precios (total_amount,total_paid,total_debt) -
AccountBookingInterface: Reservas con información de pagos para usuarios autenticados, incluyetotal_paid,total_amount,is_payment_complete,can_add_paymenty array depayments -
AccountBookingPaymentInterface: Estructura de pagos dentro de reservas de cuenta, incluyestatus(string: "pending" | "completed") ystatusBoolean(boolean) para compatibilidad
Pagos
-
PaymentInterface: Estructura de pagos (puede tenerreservation_idoenrollment_id, pero no ambos). El campostatuses boolean (false= pendiente,true= completado) -
AccountPaymentInterface: ExtiendePaymentInterfacecon información adicional de la reserva asociada (court_name,checking,checkout)
Clientes y Usuarios
-
ClientInterface: Estructura de clientes con información completa (id,user_id,email,display_name,first_name,last_name,phone,document,document_type_id,address,email_verified,is_available) -
StudentInterface: Estructura de alumnos del entrenador (id,user_id,email,display_name,first_name,last_name,phone,email_verified,created_at) -
FirebaseUserInterface: Estructura de usuarios de Firebase Auth con claims de roles (uid,email,emailVerified,displayName,disabled,role,trainer,operator,admin,sudo,metadata) -
UserInterface: Estructura de usuarios en la base de datos (id,firebase_id,email,email_verified,display_name,phone,disabled,creation_time,last_sign_in_time, etc.) -
UsersListResponseInterface: Respuesta de lista de usuarios con paginación (users,pageToken,total)
Clases y Inscripciones
-
TrainingClassInterface: Estructura de clases de entrenamiento (id,user_id,reservation_id,title,description,start_time,end_time,start_date,end_date,class_start_time,recurrence_days,status,completed_at,trainer_name,enrolled_count, etc.) -
EnrollmentInterface: Estructura de inscripciones (id,class_id,client_id,user_id,status,enrolled_at,accepted_at,rejected_at,attendance_status,attendance_marked_at,payment_type_id,payment_amount,payment_reference,student,training_class)
Canchas y Tipos
-
CourtInterface: Estructura de canchas (id,court_type_id,name,cost,price,court_type_name) -
CourtTypeInterface: Estructura de tipos de cancha (id,name,description,created_at)
Tarifas
-
TariffInterface: Estructura de tarifas con ajustes dinámicos (id,court_id,reservation_type_id,rrule,start_date,end_date,start_time,end_time,adjustment,description,is_active,created_at,updated_at) -
TariffClassInterface: Estructura de tarifas de clase (id,court_type_id,reservation_type_id,single_price,total_price,max_capacity,created_at,updated_at,court_type_name,reservation_type_name)
Tipos y Estados
-
ReservationTypeInterface: Estructura de tipos de reserva (id,name,description) -
ReservationStatusInterface: Estructura de estados de reserva (id,name,color,description). El campocolores un color hexadecimal para representación visual en calendarios -
PaymentTypeInterface: Estructura de tipos de pago (id,name,description) -
DocumentTypeInterface: Estructura de tipos de documento (id,name,description)
Utilidades
-
CalculatePriceResponseInterface: Respuesta del cálculo de precio con información detallada (court,date,checking,checkout,available,hours,price_per_hour,final_price,applied_adjustments) -
PaginationInterface: Información de paginación (page,limit,total,totalPages) -
PaginatedResponseInterface<T>: Respuesta paginada genérica con datos y paginación -
DashboardStatsWithRecentInterface: Estadísticas del dashboard con datos recientes (clients,courts,reservations,payments,recent_reservations,recent_payments) -
PushNotificationPayload: Payload para notificaciones push (clientId,title,body,url) -
ErrorResponseInterface: Estructura de respuestas de error (error,message,stack)
Nota: Todas las interfaces están completamente tipadas y documentadas en el paquete common. Consulta la documentación del paquete para más detalles sobre cada interfaz. Las interfaces están alineadas con el esquema OpenAPI disponible en /api/api-docs.json.
Códigos de Estado HTTP
-
200 OK: Petición exitosa -
201 Created: Recurso creado exitosamente -
204 No Content: Recurso eliminado exitosamente -
400 Bad Request: Error en la petición (validación fallida, datos mal formados) -
Ejemplos:
user_iddebe ser un número válido, email inválido, se requiereuser_idoemail -
401 Unauthorized: No autenticado, token inválido, o API key inválida-
Para Firebase Auth: Token de Firebase inválido o expirado
-
Para API Key: Header
X-Authfaltante o valor deBOT_API_KEYSincorrecto
-
-
403 Forbidden: No autorizado para realizar la acción -
404 Not Found: Recurso no encontrado -
409 Conflict: Conflicto de recursos (recurso ya existe o está en conflicto) -
Ejemplos: Email ya en uso, teléfono ya en uso, usuario ya es cliente, usuario no puede convertirse en cliente
-
500 Internal Server Error: Error del servidor
Nota sobre códigos de estado:
* Los códigos 400 se usan para solicitudes mal formadas o datos inválidos
* Los códigos 409 se usan específicamente para conflictos de recursos (email/teléfono en uso, usuario ya es cliente, etc.)
* Esta separación permite a los clientes distinguir entre errores de validación y conflictos de recursos
Manejo de Errores
Todas las respuestas de error siguen el formato:
{
"error": "Mensaje de error",
"message": "Descripción detallada del error (opcional)"
}
Ejemplo:
{
"error": "Datos incompletos",
"message": "Los campos requeridos no están presentes: court_id, checking"
}
Nota: La interfaz TypeScript correspondiente es ErrorResponseInterface del paquete @cortex-ia-com-co/common.
Webhooks
El sistema expone webhooks para notificaciones de eventos:
POST /webhooks/payment
Webhook para recibir notificaciones de pagos del gateway.
Request Body:
{
"transaction_id": "TXN-123456",
"amount": 50000.00,
"status": "completed",
"gateway_response": "{\"status\":\"completed\"}",
"date": "2024-01-10T08:00:00Z"
}
Nota: El webhook puede recibir status como string desde el gateway (ej: "completed", "pending", "failed"). El sistema convertirá internamente estos valores a boolean según corresponda.
El sistema procesará el webhook y:
1. Buscará si existe un pago con ese transaction_id
2. Si no existe, creará un pago huérfano (sin reservation_id ni enrollment_id)
3. Si existe y tiene reservation_id o enrollment_id, actualizará el estado del pago
4. Si existe sin reservation_id ni enrollment_id, lo mantendrá como huérfano hasta que se alinee manualmente
Response 200:
{
"status": "processed",
"payment_id": 1,
"aligned": false
}
Campos de respuesta:
* status: Estado del procesamiento del webhook ("processed", "error", etc.)
* payment_id: ID del pago creado o actualizado
* aligned: Indica si el pago está alineado con una reserva (true) o es huérfano (false)