Saltar a contenido

Referencia — Aprendizaje

Endpoints de cursos, matrículas y progreso, rutas, evaluaciones, certificados, grupos de acceso, grupos, eventos y Fundae. Todas las rutas cuelgan de /api/v1.

Leyenda de Auth: Bearer = cualquier usuario autenticado del tenant · formador+ = formador, tenant_admin o super_admin · admin = tenant_admin o super_admin · Público = sin sesión.

Cursos — /modules/courses

Método Ruta Auth Qué hace
GET /modules/courses Bearer Lista cursos del tenant; query status, q, category.
POST /modules/courses formador+ Crea curso en DRAFT.
GET /modules/courses/categories Bearer Categorías usadas por cursos publicados.
GET /modules/courses/managed-categories Bearer Categorías curadas del tenant (color, icono).
POST /modules/courses/managed-categories admin Crea categoría curada.
PUT /modules/courses/managed-categories/:id admin Actualiza categoría curada.
DELETE /modules/courses/managed-categories/:id admin Borra categoría curada.
GET /modules/courses/:id Bearer Detalle con módulos y lecciones (ver gating abajo).
PUT /modules/courses/:id formador+ Actualiza metadatos del curso.
POST /modules/courses/:id/modules formador+ Añade módulo al curso.
POST /modules/courses/modules/:moduleId/lessons formador+ Añade lección al módulo.
PUT /modules/courses/lessons/:lessonId formador+ Actualiza contenido de una lección.
POST /modules/courses/:id/publish formador+ Publica (ejecuta el hook courses.publish.validate).
POST /modules/courses/:id/archive · /:id/unarchive formador+ Archiva / vuelve a DRAFT.
POST /modules/courses/lessons/:lessonId/move formador+ Mueve la lección un puesto arriba/abajo.
POST /modules/courses/lessons/:lessonId/move-to-module formador+ Mueve la lección a otro módulo.
POST /modules/courses/modules/:moduleId/reorder-lessons formador+ Reordena lecciones en bloque (drag & drop).
POST /modules/courses/:id/reorder-modules formador+ Reordena módulos del curso en bloque.
DELETE /modules/courses/modules/:moduleId formador+ Soft-delete del módulo (cascade lógico de lecciones).
DELETE /modules/courses/lessons/:lessonId formador+ Soft-delete de la lección (preserva progreso histórico).

Bodies clave — crear curso: slug (kebab-case), title, description?, thumbnailUrl?, language (default es-ES), estimatedMinutes?, category?. slug y language son inmutables. Crear lección: type (VIDEO|HTML|PDF|TEXT|QUIZ|SCORM), title, content (objeto libre), durationMinutes?, publishAt? (fecha futura = bloqueada).

Gating de lectura de GET /:id: formador+ recibe el curso completo; el alumno recibe 404 si no está PUBLISHED, la estructura con content: null si no está matriculado, y content: null solo en lecciones no liberadas si hay drip.

Errores: COURSE_NOT_FOUND 404 · COURSE_SLUG_EXISTS 409 · COURSE_ALREADY_PUBLISHED 409 · COURSE_NO_LESSONS 422 · COURSE_PUBLISH_VALIDATION_FAILED 422 (con array reasons).

Matrículas, progreso y drip — /modules/learning

Método Ruta Auth Qué hace
GET /modules/learning/me/enrollments Bearer Mis matriculaciones.
GET /modules/learning/me/stats Bearer Mis estadísticas (cursos completados, tiempo visto).
GET /modules/learning/me/enrollments/:id/progress Bearer Mi progreso por lección de una matrícula.
POST /modules/learning/enrollments/me Bearer Auto-matriculación en un curso.
POST /modules/learning/enrollments/by-code · by-link Bearer Auto-matriculación con código / token de invitación.
POST /modules/learning/enrollments formador+ Matricula a otro usuario (origen ADMIN).
DELETE /modules/learning/enrollments/:id Bearer Cancela mi matrícula.
DELETE /modules/learning/enrollments/:id/by-admin formador+ Baja de la matrícula de un alumno.
POST /modules/learning/progress Bearer Reporta progreso: { enrollmentId, lessonId, watchedSeconds, resumePositionSec?, completed? }.
GET /modules/learning/courses/:courseId/enrollments formador+ Alumnos matriculados en el curso.
GET /modules/learning/courses/:courseId/enrollments/:id/progress formador+ Progreso detallado de un alumno.
GET /modules/learning/invitations formador+ Invitaciones activas de un curso (?courseId=).
POST /modules/learning/invitations formador+ Crea invitación (courseId, maxUses?, expiresAt?) → código + token.
DELETE /modules/learning/invitations/:id formador+ Revoca invitación.
GET /modules/learning/courses/:courseId/drip formador+ Calendarios de drip del curso.
POST /modules/learning/courses/:courseId/drip formador+ Crea calendario: audienceKind (TIER\|GROUP), audienceRef, unit (LESSON\|MODULE), intervalDays (≥1), startOffsetDays?.
PUT /modules/learning/drip/:id · DELETE formador+ Edita / borra calendario de drip.
GET /modules/learning/courses/:courseId/availability Bearer Fechas de desbloqueo de las lecciones para el alumno actual.
GET/POST/DELETE /modules/learning/lessons/:lessonId/unlock-subscription Bearer Consulta / alta / baja del aviso por email de desbloqueo.
GET /modules/learning/lessons/:lessonId/comments Bearer Comentarios (APPROVED de todos + propios; formador+ ve PENDING).
POST /modules/learning/lessons/:lessonId/comments Bearer Crea comentario (nace PENDING hasta moderación).
GET /modules/learning/courses/:courseId/comments/pending formador+ Cola de moderación del curso.
POST /modules/learning/comments/:id/approve · reject formador+ Modera un comentario (reject admite reason?).
DELETE /modules/learning/comments/:id Bearer (autor) Borra el comentario propio.
GET /modules/learning/me/competencies · /modules/learning/competencies Bearer Mi mapa de competencias / catálogo del tenant.
POST · DELETE /modules/learning/competencies[/:id] formador+ Crea / elimina competencia.
GET · PUT /modules/learning/courses/:courseId/competencies Bearer · formador+ Competencias del curso / reemplaza el set (items: [{competencyId, weight?}]).
POST /modules/learning/lessons/:lessonId/scorm formador+ Sube paquete SCORM 1.2/2004 en base64 (máx. ~100 MiB binarios).
GET /modules/learning/lessons/:lessonId/scorm Bearer Metadata + URL firmada del entry para el iframe (exige matrícula activa salvo editores).
POST /modules/learning/lessons/:lessonId/scorm/attempt · commit Bearer Inicia/reanuda el intento SCORM · persiste el estado cmi (al completar, puentea al progreso).
POST /modules/learning/lesson-unlock/run-now super_admin Fuerza un ciclo del notificador de desbloqueo (QA).

Errores: ALREADY_ENROLLED 409 · ENROLLMENT_NOT_FOUND 404 · INVITATION_INVALID 400 · COURSE_NOT_PUBLISHED 422 · LESSON_LOCKED 403 · TRIAL_CONTENT_LOCKED 403 (contenido de prueba, se desbloquea pagando) · SCORM_* 400/404/422.

Rutas de aprendizaje — /modules/learning/paths

Método Ruta Auth Qué hace
GET /modules/learning/paths Bearer Rutas publicadas con mi progreso.
GET /modules/learning/me/paths Bearer Mis rutas (activas + completadas).
GET /modules/learning/paths/formador formador+ Todas las rutas en cualquier estado (panel formador).
GET /modules/learning/paths/:slug Bearer Detalle de una ruta publicada con sus cursos.
POST /modules/learning/paths formador+ Crea ruta: title, description?, sequenceType? (LINEAR\|FLEXIBLE).
PATCH /modules/learning/paths/:id formador+ Actualiza (incluye courses: [{courseId, position}] — reemplaza el set).
POST /modules/learning/paths/:id/publish · archive · restore formador+ Publica/despublica · archiva · restaura a DRAFT.
POST · DELETE /modules/learning/paths/:id/enroll Bearer Matrícula en la ruta (y sus cursos) · cancelación.

Errores: ruta no encontrada / no publicada 404 · ya matriculado 409 · ruta sin cursos 400.

Evaluaciones — /modules/assessments

Gestión (formador+):

Método Ruta Qué hace
POST /modules/assessments/quizzes Crea quiz en DRAFT: title, lessonId?, passThreshold? (0-100), maxAttempts?, timeLimitMinutes?, shuffleQuestions?, showFeedback?.
GET · PUT /modules/assessments/quizzes/:id Detalle para el formador (incluye isCorrect) · actualización.
POST /modules/assessments/quizzes/:id/questions Añade pregunta: type (SINGLE_CHOICE\|MULTIPLE_CHOICE\|TRUE_FALSE\|FILL_IN_BLANK\|SHORT_ANSWER\|LONG_ANSWER), prompt, options?, acceptedAnswers?, points?.
DELETE /modules/assessments/quizzes/:id/questions/:questionId Soft-delete de la pregunta.
POST /modules/assessments/quizzes/:id/publish Publica (exige ≥1 pregunta).
GET /modules/assessments/attempts/pending Intentos en PENDING_REVIEW (corrección manual de respuestas abiertas).
GET /modules/assessments/attempts/:id/full Intento completo para el corrector.
POST /modules/assessments/attempts/:id/grade Califica manualmente: { grades: [{questionId, scoreEarned, feedback?}] }; emite assessments.attempt.passed/failed.

Alumno (Bearer):

Método Ruta Qué hace
GET /modules/assessments/quizzes/:id/preview Vista del quiz sin soluciones.
POST /modules/assessments/attempts Inicia intento: { quizId, enrollmentId?, lessonId? }.
POST /modules/assessments/attempts/:id/submit Envía respuestas { answers: [{questionId, selectedOptionIds?, textAnswer?}] }; autocorrección + eventos.
GET /modules/assessments/attempts/:id Detalle de un intento propio.
GET /modules/assessments/attempts?quizId= Mis intentos de un quiz.

Errores: QUIZ_NOT_PUBLISHED / QUIZ_HAS_NO_QUESTIONS 422 · ATTEMPT_ALREADY_SUBMITTED / MAX_ATTEMPTS_REACHED 409 · ATTEMPT_EXPIRED 410 · not-found 404.

Certificados — /modules/certificates

Método Ruta Auth Qué hace
GET /modules/certificates/me Bearer Mis certificados emitidos.
GET /modules/certificates/:id · /:id/download Titular o formador+ Detalle · descarga del PDF (regenerado desde snapshot inmutable). Un usuario solo accede a sus propios certificados; el staff, a los de cualquiera. Un id ajeno responde 404.
GET /modules/certificates/verify/:id Público Verificación pública: { number, studentName, courseTitle, issuedAt, valid }. Nunca expone email ni datos internos.
GET · POST /modules/certificates/templates formador+ Lista · crea plantilla: name, body, primaryColor?, logoUrl?, signerName?, signerTitle?, isDefault?.
GET · PATCH · DELETE /modules/certificates/templates/:id formador+ Detalle · edición · borrado (409 si es default o está en uso).
POST /modules/certificates/templates/preview formador+ PDF de previsualización con datos dummy, sin persistir.
POST /modules/certificates/templates/:id/set-default formador+ Marca como plantilla por defecto del tenant.

Grupos de acceso — /modules/access-groups (todo admin)

Método Ruta Qué hace
GET /modules/access-groups Lista paginada (page, limit).
GET /modules/access-groups/catalog/courses · catalog/users Selectores: cursos publicados · usuarios candidatos (?q=).
GET /modules/access-groups/:id Detalle con cursos y miembros.
POST /modules/access-groups Crea: name, slug?, kind (ALL_COURSES\|COURSE\|MULTI_COURSE), courseIds?, autoGrantNewCourses?.
PATCH /modules/access-groups/:id Edita (name, description, autoGrantNewCourses, isDefaultForApproval, linkedTierName — vincula un tier de pagos).
PUT /modules/access-groups/:id/courses Reemplaza el set completo de cursos.
POST /modules/access-groups/:id/members Asigna miembros: { userIds: [] } (máx. 500).
DELETE /modules/access-groups/:id/members/:userId Revoca un miembro.
DELETE /modules/access-groups/:id Elimina el grupo y revoca sus membresías.

Grupos y eventos de comunidad

Método Ruta Auth Qué hace
GET /modules/groups · /me · /:id Bearer Lista paginada · mis grupos · detalle con miembros.
POST /modules/groups formador+ Crea grupo (name, slug, description?); el creador queda como owner.
POST · DELETE /modules/groups/:id/join · /:id/leave Bearer Unirse · abandonar (idempotente).
GET /modules/events · /:id Bearer Eventos por rango de fechas (from, to, limit, order) · detalle con registeredCount, isFull, isRegistered.
POST /modules/events formador+ Crea evento: title, startAt, endAt, location?, capacity?.
POST /modules/events/:id/register · unregister Bearer Inscripción (si está lleno: { registered: false, reason: 'full' }) · cancelación.

Fundae — /modules/fundae (todo admin; el rol formador no accede)

Método Ruta Qué hace
GET · POST /modules/fundae/actions Lista (filtros courseId, status) · crea acción formativa: codigoAccion (≤25), nombre, modalidad (PRESENCIAL\|TELEFORMACION\|MIXTA), horasFormacion, fechaInicio/fechaFin (YYYY-MM-DD), courseId?, lugar?, cifCentro?.
GET · PUT · DELETE /modules/fundae/actions/:id Detalle · actualización (+ status) · archivado (soft).
GET /modules/fundae/actions/:id/participants · /count Participantes con email, DNI, progreso y resultado · recuento.
GET /modules/fundae/actions/:id/export.xml XML Fundae de la acción (descarga).
GET /modules/fundae/actions/:id/participants/:userId/evidence.pdf PDF de evidencia firmada de un participante.
GET /modules/fundae/actions/:id/export.zip ZIP de presentación: XML + un PDF de evidencia por participante.
GET · POST /modules/fundae/actions/:id/blocks Módulos formativos (bloques) · alta (ordinal?, title, hours, modalidad, contenidos?).
PUT · DELETE /modules/fundae/actions/:id/blocks/:blockId Edición · borrado de bloque.

La suma de horas de los bloques no puede superar las horasFormacion de la acción (Fundae lo verifica al subir el XML). El firmante de las evidencias es el administrador que dispara la descarga.