API - Módulo Escuelas
Documentación completa del API REST para el módulo de Escuelas de Chalanería.
Base URL
/api/schools/{schoolId}
Todas las rutas del módulo Escuelas requieren un schoolId que identifica la escuela específica.
Primero debes obtener el ID de tu escuela usando el endpoint GET /api/schools.
Autenticación
Todas las peticiones requieren autenticación con Firebase JWT Token:
Authorization: Bearer YOUR_JWT_TOKEN
Recursos Disponibles
El API del módulo Escuelas incluye endpoints para:
- 📊 Dashboard - Estadísticas y resumen general
- 👥 Estudiantes - Gestión de estudiantes
- 👨🏫 Instructores - Gestión de instructores
- 📚 Clases - Gestión de clases
- 📅 Horarios - Programación de horarios
- 📝 Inscripciones - Inscripción de estudiantes
- ✅ Asistencia - Registro de asistencia
- 🐴 Caballos - Gestión de caballos
- 💰 Pagos - Gestión de pagos
- 🏆 Competencias - Competencias internas
- 📊 Reportes - Reportes y estadísticas
Dashboard
Obtener Estadísticas del Dashboard
/api/schools/{schoolId}/dashboardObtiene un resumen completo del dashboard con estadísticas y métricas clave
Parámetros de la respuesta:
stats.students.total: Número total de estudiantes registrados (independientemente de su estado)stats.students.active: Número de estudiantes con estado 'active'stats.students.new_this_month: Contador de estudiantes creados desde el inicio del mes actual hasta la fecha actualstats.instructors.total: Número total de instructoresstats.instructors.active: Número de instructores activosstats.horses.total: Número total de caballosstats.horses.active: Número de caballos activosstats.horses.resting: Número de caballos en descansostats.classes.total: Número total de clases creadasstats.classes.active: Número de clases activastoday.classes_count: Número de clases programadas para hoytoday.students_expected: Número total de estudiantes esperados hoytoday.attendance_recorded: Número de clases con asistencia ya registradatoday.attendance_rate: Porcentaje de asistencia registrada hasta ahorafinances.month_income: Ingresos del mes actual (solo pagos completados)finances.pending_payments: Cantidad de pagos pendientesfinances.pending_amount: Monto total de pagos pendientes
El cálculo de new_this_month considera todos los estudiantes cuyo created_at se encuentra entre el inicio del mes actual (00:00:00) y el inicio del próximo mes. Se actualiza automáticamente al consultar el endpoint.
Response:
{
"data": {
"stats": {
"students": {
"total": 45,
"active": 42,
"new_this_month": 3
},
"instructors": {
"total": 8,
"active": 8
},
"horses": {
"total": 12,
"active": 10,
"resting": 2
},
"classes": {
"total": 15,
"active": 15
}
},
"today": {
"classes_count": 8,
"students_expected": 35,
"attendance_rate": 85
},
"finances": {
"month_income": 4500000,
"pending_payments": 5,
"pending_amount": 750000
}
}
}
Estudiantes
Listar Estudiantes
/api/schools/{schoolId}/studentsObtiene la lista de estudiantes con filtros y paginación
Query Parameters:
| Parámetro | Tipo | Descripción |
|---|---|---|
search | string | Buscar por nombre |
status | string | Filtrar por estado: active, inactive, suspended, graduated |
level | string | Filtrar por nivel: beginner, intermediate, advanced |
class_id | uuid | Filtrar por clase |
page | int | Número de página |
per_page | int | Items por página (default: 20) |
Ejemplo:
curl -X GET "https://api.equinos.co/api/schools/{schoolId}/students?status=active&level=beginner" \
-H "Authorization: Bearer YOUR_TOKEN"
Crear Estudiante
/api/schools/{schoolId}/studentsCrea un nuevo estudiante en la escuela
Body:
{
"first_name": "Ana María",
"last_name": "López",
"birth_date": "2010-05-15",
"gender": "female",
"document_type": "TI",
"document_number": "1234567890",
"phone": "+57 300 123 4567",
"email": "ana@email.com",
"address": {
"street": "Calle 10 #20-30",
"city": "Medellín",
"state": "Antioquia"
},
"emergency_contact": {
"name": "María López",
"relationship": "Madre",
"phone": "+57 300 765 4321"
},
"level": "beginner"
}
Obtener Estudiante
/api/schools/{schoolId}/students/{studentId}Obtiene la información completa de un estudiante
Response: Incluye información personal, inscripciones activas, estadísticas de asistencia y pagos.
Actualizar Estudiante
/api/schools/{schoolId}/students/{studentId}Actualiza la información de un estudiante
Eliminar Estudiante
/api/schools/{schoolId}/students/{studentId}Elimina un estudiante (solo si no tiene historial)
Importar Estudiantes desde CSV
/api/schools/{schoolId}/students/importImporta múltiples estudiantes desde un archivo CSV
Content-Type: multipart/form-data
Body:
file: Archivo CSV con los datos de estudiantes
Instructores
Listar Instructores
/api/schools/{schoolId}/instructorsObtiene la lista de instructores de la escuela
Crear Instructor
/api/schools/{schoolId}/instructorsCrea un nuevo instructor
Body:
{
"first_name": "Juan",
"last_name": "Pérez",
"document_type": "CC",
"document_number": "1234567890",
"phone": "+57 300 123 4567",
"email": "juan@email.com",
"specialties": ["chalanería", "salto"],
"experience_years": 10,
"bio": "Instructor con más de 10 años de experiencia",
"hourly_rate": 50000
}
Obtener Disponibilidad del Instructor
/api/schools/{schoolId}/instructors/{instructorId}/availabilityObtiene la disponibilidad horaria de un instructor
Query Parameters:
date: Fecha específica (YYYY-MM-DD)week: Semana (YYYY-Www)
Clases
Listar Clases
/api/schools/{schoolId}/classesObtiene la lista de clases de la escuela
Query Parameters:
type:individualogrouplevel:beginner,intermediate,advanced,professionaldiscipline:chalanería,salto,doma, etc.status:activeoinactive
Crear Clase
/api/schools/{schoolId}/classesCrea una nueva clase
Body:
{
"name": "Chalanería Básica",
"description": "Clase introductoria de chalanería para principiantes",
"type": "group",
"level": "beginner",
"discipline": "chalanería",
"max_students": 8,
"duration_minutes": 60,
"price": 80000,
"price_type": "per_class"
}
Horarios
Vista Semanal de Horarios
/api/schools/{schoolId}/schedules/weeklyObtiene todos los horarios de una semana específica
Query Parameters:
week: Semana en formato YYYY-Www o fecha de inicio
Response: Incluye todos los horarios programados con información de clase, instructor y estudiantes inscritos.
Crear Horario
/api/schools/{schoolId}/schedulesCrea un nuevo horario para una clase
Body:
{
"class_id": "uuid",
"instructor_id": "uuid",
"day_of_week": 1,
"start_time": "08:00",
"end_time": "09:00",
"location": "Pista 1",
"max_students": 8
}
Inscripciones
Crear Inscripción
/api/schools/{schoolId}/enrollmentsInscribe un estudiante en una clase y horario específico
Body:
{
"student_id": "uuid",
"class_id": "uuid",
"schedule_id": "uuid",
"horse_id": "uuid",
"start_date": "2025-01-01"
}
Asistencia
Registrar Asistencia
/api/schools/{schoolId}/attendanceRegistra la asistencia de una clase completa
Body:
{
"date": "2025-12-16",
"schedule_id": "uuid",
"attendance": [
{
"enrollment_id": "uuid",
"status": "present",
"horse_id": "uuid",
"performance_rating": 4,
"notes": "Excelente progreso"
},
{
"enrollment_id": "uuid",
"status": "absent",
"notes": "Enfermedad"
}
]
}
Estados de asistencia:
present- Presenteabsent- Ausentelate- Tardeexcused- Excusado
Reporte de Asistencia
/api/schools/{schoolId}/attendance/reportObtiene un reporte de asistencia para un período específico
Query Parameters:
start_date: Fecha inicioend_date: Fecha finstudent_id: Filtrar por estudianteclass_id: Filtrar por clase
Caballos
Listar Caballos
/api/schools/{schoolId}/horsesObtiene la lista de caballos de la escuela
Query Parameters:
status:active,resting,injured,retiredlevel:beginner,intermediate,advanced,all
Obtener Uso del Caballo
/api/schools/{schoolId}/horses/{horseId}/usageObtiene el uso diario de un caballo
Query Parameters:
date: Fecha específicastart_date,end_date: Rango de fechas
Pagos
Listar Pagos
/api/schools/{schoolId}/paymentsObtiene la lista de pagos con filtros
Query Parameters:
student_id: Filtrar por estudiantestatus:pending,paid,overdue,cancelledstart_date,end_date: Rango de fechas
Registrar Pago
/api/schools/{schoolId}/payments/{paymentId}/payRegistra un pago recibido
Body:
{
"payment_method": "transfer",
"paid_date": "2025-01-03",
"receipt_number": "REC-001",
"notes": "Transferencia Bancolombia"
}
Métodos de pago:
cash- Efectivotransfer- Transferencia bancariacard- Tarjetanequi- Nequiother- Otro
Generar Cobros Mensuales
/api/schools/{schoolId}/payments/generate-monthlyGenera cobros mensuales para todos los estudiantes activos
Body:
{
"month": "2025-01",
"due_day": 5
}
Competencias
Listar Competencias
/api/schools/{schoolId}/competitionsObtiene la lista paginada de competencias de una escuela
Query Parameters:
status(string, opcional): Filtrar por estado (upcoming,ongoing,completed,cancelled)type(string, opcional): Filtrar por tiposearch(string, opcional): Buscar por nombre o ubicaciónper_page(int, opcional): Elementos por página (default: 20)
Response:
{
"data": [
{
"id": "...",
"name": "Competencia Interna Diciembre 2025",
"date": "2025-12-20",
"location": "Arena Principal",
"status": "upcoming",
"categories": ["Principiantes", "Intermedios"],
"results_count": 0
}
],
"meta": {...}
}
Crear Competencia
/api/schools/{schoolId}/competitionsCrea una nueva competencia interna
Body:
{
"name": "Competencia Interna Diciembre 2025",
"description": "Competencia de fin de año",
"date": "2025-12-20",
"location": "Arena Principal",
"type": "internal",
"categories": ["Principiantes", "Intermedios", "Avanzados"],
"fees": [
{
"concept": "inscription",
"name": "Inscripción Principiantes",
"amount": 50000,
"is_required": true,
"applies_to": "entry",
"description": "Costo de inscripción"
},
{
"concept": "stable",
"name": "Cuota de Establo",
"amount": 30000,
"is_required": false,
"applies_to": "horse",
"description": "Si trae caballo"
}
],
"status": "upcoming"
}
Campos de fees:
concept(string, requerido):inscription,school_fee,stable,rental,equipment,transport,othername(string, requerido): Descripción de la tarifaamount(number, requerido): Monto a cobraris_required(boolean, opcional): Si la tarifa es obligatoria (default:true)applies_to(string, opcional):entry(por inscripción),student(por estudiante),horse(por caballo)description(string, opcional): Descripción adicional
Nota: Si no se proporciona type, se usa internal por defecto. Si no se proporciona status, se usa upcoming por defecto.
Obtener Competencia
/api/schools/{schoolId}/competitions/{competitionId}Obtiene los detalles de una competencia específica, incluyendo inscripciones y resultados
Response:
{
"data": {
"id": "...",
"name": "Competencia Interna Diciembre 2025",
"date": "2025-12-20",
"location": "Arena Principal",
"status": "upcoming",
"categories": ["Principiantes", "Intermedios"],
"fees": [...],
"results": [...]
}
}
Actualizar Competencia
/api/schools/{schoolId}/competitions/{competitionId}Actualiza los datos de una competencia existente
Body: Similar al crear, todos los campos son opcionales (excepto fees que requiere validación si se envía).
Nota: fees puede ser un array vacío [] para eliminar todas las tarifas.
Eliminar Competencia
/api/schools/{schoolId}/competitions/{competitionId}Elimina una competencia de la escuela
Obtener Resultados de una Competencia
/api/schools/{schoolId}/competitions/{competitionId}/resultsObtiene todos los resultados de una competencia, ordenados por posición
Response:
{
"data": [
{
"id": "...",
"entry_id": "...",
"student_id": "...",
"student": {
"id": "...",
"full_name": "Juan Pérez"
},
"ribbon": "gold",
"position": 1,
"notes": "..."
}
]
}
Agregar Resultado a una Competencia
/api/schools/{schoolId}/competitions/{competitionId}/resultsAgrega un resultado de estudiante a una competencia. Requiere que el estudiante esté inscrito (entry_id)
Body:
{
"entry_id": "550e8400-e29b-41d4-a716-446655440002",
"ribbon": "gold",
"notes": "Excelente desempeño"
}
Validaciones:
entry_iddebe existir en la tablaschools_competition_entries- La inscripción debe pertenecer a la competencia
- No debe existir ya un resultado para esa inscripción
Comportamiento:
- El estado de la inscripción se actualiza automáticamente a
completed - Se copia información de la inscripción (categoría, caballo) al resultado
Cambio importante: Este endpoint ahora requiere entry_id en lugar de solo student_id. Esto asegura que solo se registren resultados para estudiantes que estén inscritos en la competencia.
Competencias - Inscripciones
Listar Inscripciones
/api/schools/{schoolId}/competitions/{competitionId}/entriesObtiene la lista paginada de inscripciones de una competencia
Query Parameters:
category(string, opcional): Filtrar por categoríastatus(string, opcional): Filtrar por estado (pending,confirmed,cancelled,completed)per_page(int, opcional): Elementos por página (default: 50)
Inscribir Estudiante
/api/schools/{schoolId}/competitions/{competitionId}/entriesInscribe un estudiante a una competencia. Genera automáticamente los pagos según las tarifas configuradas y calcula el orden de salida
Body:
{
"student_id": "550e8400-e29b-41d4-a716-446655440001",
"category": "Principiantes",
"horse_id": "550e8400-e29b-41d4-a716-446655440003",
"notes": "Estudiante entusiasta"
}
Validaciones:
- La categoría debe existir en el array
categoriesde la competencia - El estudiante no puede estar inscrito dos veces en la misma categoría
- Si se proporciona
horse_id, debe existir en la escuela
Comportamiento automático:
- Se crea la inscripción con estado
pending - Se generan automáticamente los pagos según las tarifas configuradas (
fees) - Se recalcula el orden de salida para la categoría (por edad, mayor a menor)
Obtener Inscripción
/api/schools/{schoolId}/competitions/{competitionId}/entries/{entryId}Obtiene los detalles de una inscripción específica
Actualizar Inscripción
/api/schools/{schoolId}/competitions/{competitionId}/entries/{entryId}Actualiza los datos de una inscripción. Si cambia la categoría, recalcula el orden automáticamente
Body:
{
"category": "Intermedios",
"horse_id": "...",
"order_number": 5,
"status": "confirmed",
"notes": "..."
}
Cancelar Inscripción
/api/schools/{schoolId}/competitions/{competitionId}/entries/{entryId}Cancela una inscripción y recalcula el orden de salida para la categoría
Recalcular Orden de Salida
/api/schools/{schoolId}/competitions/{competitionId}/entries/recalculate-orderRecalcula el orden de salida para una categoría específica o todas las categorías
Body (opcional):
{
"category": "Principiantes"
}
Si no se proporciona category, recalcula todas las categorías.
Comportamiento:
- Ordena por edad del estudiante (mayor a menor)
- Solo considera inscripciones con estado
pendingoconfirmed - Asigna números consecutivos comenzando desde 1
Listado para Imprimir
/api/schools/{schoolId}/competitions/{competitionId}/entries/print-listObtiene un listado optimizado para impresión, agrupado por categoría
Query Parameters:
category(string, opcional): Filtrar por categoría específica
Response:
{
"data": {
"competition": {
"name": "Competencia Interna Diciembre 2025",
"date": "20/12/2025",
"location": "Arena Principal"
},
"categories": {
"Principiantes": [
{
"order_number": 1,
"student_name": "Juan Pérez",
"student_age": 12,
"horse_name": "Tornado",
"result": {
"ribbon": "gold",
"ribbon_label": "Oro"
}
}
]
},
"total_entries": 15,
"generated_at": "07/01/2026 16:30"
}
}
Competencias - Pagos
Listar Pagos
/api/schools/{schoolId}/competitions/{competitionId}/paymentsObtiene la lista paginada de pagos relacionados con una competencia
Query Parameters:
status(string, opcional): Filtrar por estado (pending,paid,cancelled,refunded)concept(string, opcional): Filtrar por conceptostudent_id(string, opcional): Filtrar por estudianteper_page(int, opcional): Elementos por página (default: 50)
Crear Pago
/api/schools/{schoolId}/competitions/{competitionId}/paymentsCrea un pago manual relacionado con la competencia
Body:
{
"entry_id": "...",
"student_id": "...",
"concept": "inscription",
"concept_detail": "Inscripción Principiantes",
"amount": 50000,
"due_date": "2025-12-15",
"notes": "..."
}
Obtener Pago
/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}Obtiene los detalles de un pago específico
Actualizar Pago
/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}Actualiza los datos de un pago
Registrar Pago (Marcar como Pagado)
/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}/payRegistra un pago (marca como pagado)
Body:
{
"payment_method": "cash",
"paid_date": "2025-12-10",
"receipt_number": "REC-001",
"notes": "..."
}
Campos:
payment_method(string, requerido):cash,transfer,cardpaid_date(date, opcional): Fecha de pago (default: hoy)receipt_number(string, opcional): Número de recibonotes(string, opcional): Notas adicionales
Cancelar Pago
/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}Cancela un pago (marca como cancelado)
Resumen Financiero
/api/schools/{schoolId}/competitions/{competitionId}/payments/summaryObtiene un resumen financiero completo de la competencia
Response:
{
"data": {
"total_expected": 1500000,
"total_paid": 1200000,
"total_pending": 300000,
"by_concept": [
{
"concept": "inscription",
"total": 1000000,
"paid": 800000,
"pending": 200000,
"count": 20
}
],
"by_status": [
{
"status": "paid",
"count": 24,
"amount": 1200000
},
{
"status": "pending",
"count": 6,
"amount": 300000
}
]
}
}
Reportes
Reporte Financiero
/api/schools/{schoolId}/reports/financialObtiene un reporte financiero detallado
Ejemplos Completos
Crear un Estudiante e Inscribirlo
# 1. Crear estudiante
curl -X POST "https://api.equinos.co/api/schools/{schoolId}/students" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ana",
"last_name": "López",
"level": "beginner"
}'
# 2. Inscribir en clase
curl -X POST "https://api.equinos.co/api/schools/{schoolId}/enrollments" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"student_id": "student-uuid",
"class_id": "class-uuid",
"schedule_id": "schedule-uuid"
}'
Próximos Pasos
- 👉 Autenticación - Guía completa de autenticación
- 👉 Ver códigos de error - Lista completa de códigos de estado HTTP
Para documentación más detallada de cada endpoint, consulta el archivo OpenAPI en: https://api.equinos.co/docs.openapi.json