Saltar al contenido principal

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

Obtener Estadísticas del Dashboard

GET/api/schools/{schoolId}/dashboard

Obtiene 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 actual
  • stats.instructors.total: Número total de instructores
  • stats.instructors.active: Número de instructores activos
  • stats.horses.total: Número total de caballos
  • stats.horses.active: Número de caballos activos
  • stats.horses.resting: Número de caballos en descanso
  • stats.classes.total: Número total de clases creadas
  • stats.classes.active: Número de clases activas
  • today.classes_count: Número de clases programadas para hoy
  • today.students_expected: Número total de estudiantes esperados hoy
  • today.attendance_recorded: Número de clases con asistencia ya registrada
  • today.attendance_rate: Porcentaje de asistencia registrada hasta ahora
  • finances.month_income: Ingresos del mes actual (solo pagos completados)
  • finances.pending_payments: Cantidad de pagos pendientes
  • finances.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

GET/api/schools/{schoolId}/students

Obtiene la lista de estudiantes con filtros y paginación

Query Parameters:

ParámetroTipoDescripción
searchstringBuscar por nombre
statusstringFiltrar por estado: active, inactive, suspended, graduated
levelstringFiltrar por nivel: beginner, intermediate, advanced
class_iduuidFiltrar por clase
pageintNúmero de página
per_pageintItems 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

POST/api/schools/{schoolId}/students

Crea 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

GET/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

PUT/api/schools/{schoolId}/students/{studentId}

Actualiza la información de un estudiante

Eliminar Estudiante

DELETE/api/schools/{schoolId}/students/{studentId}

Elimina un estudiante (solo si no tiene historial)

Importar Estudiantes desde CSV

POST/api/schools/{schoolId}/students/import

Importa múltiples estudiantes desde un archivo CSV

Content-Type: multipart/form-data

Body:

  • file: Archivo CSV con los datos de estudiantes

Instructores

Listar Instructores

GET/api/schools/{schoolId}/instructors

Obtiene la lista de instructores de la escuela

Crear Instructor

POST/api/schools/{schoolId}/instructors

Crea 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

GET/api/schools/{schoolId}/instructors/{instructorId}/availability

Obtiene la disponibilidad horaria de un instructor

Query Parameters:

  • date: Fecha específica (YYYY-MM-DD)
  • week: Semana (YYYY-Www)

Clases

Listar Clases

GET/api/schools/{schoolId}/classes

Obtiene la lista de clases de la escuela

Query Parameters:

  • type: individual o group
  • level: beginner, intermediate, advanced, professional
  • discipline: chalanería, salto, doma, etc.
  • status: active o inactive

Crear Clase

POST/api/schools/{schoolId}/classes

Crea 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

GET/api/schools/{schoolId}/schedules/weekly

Obtiene 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

POST/api/schools/{schoolId}/schedules

Crea 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

POST/api/schools/{schoolId}/enrollments

Inscribe 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

POST/api/schools/{schoolId}/attendance

Registra 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 - Presente
  • absent - Ausente
  • late - Tarde
  • excused - Excusado

Reporte de Asistencia

GET/api/schools/{schoolId}/attendance/report

Obtiene un reporte de asistencia para un período específico

Query Parameters:

  • start_date: Fecha inicio
  • end_date: Fecha fin
  • student_id: Filtrar por estudiante
  • class_id: Filtrar por clase

Caballos

Listar Caballos

GET/api/schools/{schoolId}/horses

Obtiene la lista de caballos de la escuela

Query Parameters:

  • status: active, resting, injured, retired
  • level: beginner, intermediate, advanced, all

Obtener Uso del Caballo

GET/api/schools/{schoolId}/horses/{horseId}/usage

Obtiene el uso diario de un caballo

Query Parameters:

  • date: Fecha específica
  • start_date, end_date: Rango de fechas

Pagos

Listar Pagos

GET/api/schools/{schoolId}/payments

Obtiene la lista de pagos con filtros

Query Parameters:

  • student_id: Filtrar por estudiante
  • status: pending, paid, overdue, cancelled
  • start_date, end_date: Rango de fechas

Registrar Pago

POST/api/schools/{schoolId}/payments/{paymentId}/pay

Registra un pago recibido

Body:

{
"payment_method": "transfer",
"paid_date": "2025-01-03",
"receipt_number": "REC-001",
"notes": "Transferencia Bancolombia"
}

Métodos de pago:

  • cash - Efectivo
  • transfer - Transferencia bancaria
  • card - Tarjeta
  • nequi - Nequi
  • other - Otro

Generar Cobros Mensuales

POST/api/schools/{schoolId}/payments/generate-monthly

Genera cobros mensuales para todos los estudiantes activos

Body:

{
"month": "2025-01",
"due_day": 5
}

Competencias

Listar Competencias

GET/api/schools/{schoolId}/competitions

Obtiene 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 tipo
  • search (string, opcional): Buscar por nombre o ubicación
  • per_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

POST/api/schools/{schoolId}/competitions

Crea 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, other
  • name (string, requerido): Descripción de la tarifa
  • amount (number, requerido): Monto a cobrar
  • is_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

GET/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

PUT/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

DELETE/api/schools/{schoolId}/competitions/{competitionId}

Elimina una competencia de la escuela

Obtener Resultados de una Competencia

GET/api/schools/{schoolId}/competitions/{competitionId}/results

Obtiene 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

POST/api/schools/{schoolId}/competitions/{competitionId}/results

Agrega 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_id debe existir en la tabla schools_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

GET/api/schools/{schoolId}/competitions/{competitionId}/entries

Obtiene la lista paginada de inscripciones de una competencia

Query Parameters:

  • category (string, opcional): Filtrar por categoría
  • status (string, opcional): Filtrar por estado (pending, confirmed, cancelled, completed)
  • per_page (int, opcional): Elementos por página (default: 50)

Inscribir Estudiante

POST/api/schools/{schoolId}/competitions/{competitionId}/entries

Inscribe 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 categories de 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:

  1. Se crea la inscripción con estado pending
  2. Se generan automáticamente los pagos según las tarifas configuradas (fees)
  3. Se recalcula el orden de salida para la categoría (por edad, mayor a menor)

Obtener Inscripción

GET/api/schools/{schoolId}/competitions/{competitionId}/entries/{entryId}

Obtiene los detalles de una inscripción específica

Actualizar Inscripción

PUT/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

DELETE/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

POST/api/schools/{schoolId}/competitions/{competitionId}/entries/recalculate-order

Recalcula 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 pending o confirmed
  • Asigna números consecutivos comenzando desde 1

Listado para Imprimir

GET/api/schools/{schoolId}/competitions/{competitionId}/entries/print-list

Obtiene 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

GET/api/schools/{schoolId}/competitions/{competitionId}/payments

Obtiene 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 concepto
  • student_id (string, opcional): Filtrar por estudiante
  • per_page (int, opcional): Elementos por página (default: 50)

Crear Pago

POST/api/schools/{schoolId}/competitions/{competitionId}/payments

Crea 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

GET/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}

Obtiene los detalles de un pago específico

Actualizar Pago

PUT/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}

Actualiza los datos de un pago

Registrar Pago (Marcar como Pagado)

POST/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}/pay

Registra 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, card
  • paid_date (date, opcional): Fecha de pago (default: hoy)
  • receipt_number (string, opcional): Número de recibo
  • notes (string, opcional): Notas adicionales

Cancelar Pago

DELETE/api/schools/{schoolId}/competitions/{competitionId}/payments/{paymentId}

Cancela un pago (marca como cancelado)

Resumen Financiero

GET/api/schools/{schoolId}/competitions/{competitionId}/payments/summary

Obtiene 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

GET/api/schools/{schoolId}/reports/financial

Obtiene 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


💡Documentación Completa

Para documentación más detallada de cada endpoint, consulta el archivo OpenAPI en: https://api.equinos.co/docs.openapi.json