Base URL:
https://api.appfasia.com/api/v1
Autenticación:Authorization: Bearer <JWT>en todos los endpoints salvo los de Auth
Formato: JSON (Content-Type: application/json)
Versión: 0.1
{
"error": "CHILD_NOT_FOUND",
"message": "El perfil de niño con id 'abc-123' no existe o no pertenece a este tutor.",
"status": 404
}| Código | Significado |
|---|---|
SESSION_LIMIT_REACHED |
Se alcanzó el límite diario de la sesión (dosificación AAP) |
DIAGNOSTIC_REQUIRED |
El niño no tiene diagnóstico inicial — debe completarlo primero |
LOW_CONFIDENCE_AUDIO |
Azure STT no pudo procesar el audio con suficiente confianza |
TIMEOUT_REGISTERED |
Silencio de 10s registrado como intento nulo |
HARDWARE_OVERRIDE |
El motor cambió la modalidad de V-M a T-S por bloqueo fonológico |
Registro de un tutor (padre/cuidador).
Request:
{
"nombre": "María González",
"email": "maria@email.com",
"password": "S3cur3P@ss"
}Response 201:
{
"id_tutor": "uuid-tutor-001",
"nombre": "María González",
"email": "maria@email.com",
"created_at": "2026-05-12T20:00:00Z"
}Autenticación. Devuelve el par de tokens JWT.
Request:
{
"email": "maria@email.com",
"password": "S3cur3P@ss"
}Response 200:
{
"access_token": "<JWT>",
"refresh_token": "<JWT_refresh>",
"token_type": "bearer",
"expires_in": 3600
}El
access_tokenexpira en 1 hora. Elrefresh_tokenen 30 días.
Renueva el access_token usando el refresh_token.
Request:
{ "refresh_token": "<JWT_refresh>" }Response 200:
{
"access_token": "<nuevo_JWT>",
"expires_in": 3600
}Devuelve el perfil del tutor autenticado.
Response 200:
{
"id_tutor": "uuid-tutor-001",
"nombre": "María González",
"email": "maria@email.com",
"children": ["uuid-child-001", "uuid-child-002"]
}Crea un perfil de niño asociado al tutor autenticado.
Request:
{
"nombre": "Lucía",
"fecha_nac": "2020-03-15"
}Response 201:
{
"id_child": "uuid-child-001",
"nombre": "Lucía",
"fecha_nac": "2020-03-15",
"edad_meses": 62,
"nivel_actual": null,
"diagnostico_completado": false,
"created_at": "2026-05-12T20:00:00Z"
}
nivel_actual: nullindica que el diagnóstico inicial aún no se ha realizado.
Lista todos los niños del tutor autenticado.
Response 200:
[
{
"id_child": "uuid-child-001",
"nombre": "Lucía",
"edad_meses": 62,
"nivel_actual": 2,
"diagnostico_completado": true,
"ultima_sesion": "2026-05-11T18:30:00Z"
}
]Detalle completo de un perfil de niño.
Response 200:
{
"id_child": "uuid-child-001",
"nombre": "Lucía",
"fecha_nac": "2020-03-15",
"edad_meses": 62,
"nivel_actual": 2,
"diagnostico_completado": true,
"bkt_summary": {
"hitos_dominados": 12,
"hitos_en_practica": 3,
"hitos_bloqueados": 1
},
"racha_dias": 5
}Actualiza datos del perfil (solo nombre o fecha de nacimiento).
Request:
{ "nombre": "Luci" }Response 200: mismo esquema que GET /children/{child_id}
El diagnóstico implementa el algoritmo Basal/Ceiling de la Sección 14 del plan. Es una conversación de máximo 15 interacciones que determina el nivel real del niño.
Inicia la prueba diagnóstica. El motor calcula el punto de inicio (medio nivel por debajo de la edad cronológica).
Request:
{ "child_id": "uuid-child-001" }Response 200:
{
"session_diag_id": "diag-uuid-001",
"interaccion_num": 1,
"max_interacciones": 15,
"ejercicio": {
"plantilla": "Identificador",
"hardware_req": "T-S",
"nivel_prueba": 1,
"prompt_audio": {
"audio_url": "https://cdn.appfasia.com/recursos/audios/vaca.mp3",
"texto_estimulo": "Toca el animal que hace muuu"
},
"opciones": [
{ "id": "W_001", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/vaca.png" },
{ "id": "W_045", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/perro.png" },
{ "id": "W_089", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/gato.png" }
],
"umbrales": { "tra_max_ms": 4000 }
},
"avatar_mensaje": "¡Hola! Vamos a jugar un juego. ¿Cuál hace muuu?"
}Envía la respuesta de una interacción diagnóstica. El motor decide si continúa o termina (condición de Techo).
Request:
{
"session_diag_id": "diag-uuid-001",
"tipo_respuesta": "seleccion",
"id_seleccionado": "W_001",
"tra_ms": 2800,
"audio_base64": null
}Response 200 — Continúa la prueba:
{
"estado": "EN_CURSO",
"interaccion_num": 2,
"max_interacciones": 15,
"ejercicio": { ... },
"avatar_mensaje": "¡Muy bien! Siguiente..."
}Response 200 — Prueba terminada (Ceiling o máximo de interacciones):
{
"estado": "COMPLETADO",
"nivel_detectado": 2,
"descripcion_nivel": "Estructuración Telegráfica y Expansión (2 a 4 años)",
"avatar_mensaje": "¡Lo hiciste genial! Ya sé cómo podemos jugar juntos.",
"resumen": {
"aciertos_consecutivos_inicio": 3,
"errores_consecutivos_fin": 3,
"total_interacciones": 9
}
}Consulta el resultado del último diagnóstico completado.
Response 200:
{
"nivel_detectado": 2,
"fecha_diagnostico": "2026-05-12T20:00:00Z",
"total_interacciones": 9,
"p_l0_inicial": 0.15
}Este es el endpoint más crítico del sistema. Cada llamada a /session/response ejecuta el pipeline completo: Azure STT → Métricas → BKT → RulesEngine → ContentEngine → respuesta.
Inicia una nueva sesión diaria. El motor verifica que no se haya superado el límite diario (dosificación AAP).
Request:
{ "child_id": "uuid-child-001" }Response 200:
{
"session_id": "sess-uuid-001",
"child_id": "uuid-child-001",
"nivel_sesion": 2,
"ejercicios_max": 4,
"minijuegos_max": 1,
"tiempo_max_min": 12,
"ejercicio_actual": {
"id_actividad": "ACT_042",
"plantilla": "Nombrador",
"hardware_req": "V-M",
"prompt_visual": {
"imagen_url": "https://cdn.appfasia.com/recursos/imagenes/mariposa.png",
"texto_oculto": "Mariposa"
},
"instruccion_avatar": "¿Qué animal ves aquí?",
"umbrales": {
"ipf_min": 80,
"tra_max_ms": 5000,
"timeouts_max": 3
}
},
"avatar_mensaje": "¡Hola, Lucía! ¿Lista para jugar? Mira bien esta imagen..."
}Response 403 — Límite diario alcanzado:
{
"error": "SESSION_LIMIT_REACHED",
"message": "Lucía ya completó su sesión de hoy. ¡Vuelve mañana!",
"proxima_sesion_disponible": "2026-05-13T00:00:00Z"
}El endpoint central. Recibe la respuesta del niño y devuelve la decisión del motor más el siguiente ejercicio (o la señal de fin de sesión).
Request:
{
"session_id": "sess-uuid-001",
"id_actividad": "ACT_042",
"tipo_respuesta": "audio",
"audio_base64": "<base64_del_audio_wav>",
"id_seleccionado": null,
"orden_bloques": null,
"tra_ms": 3200,
"es_timeout": false
}
tipo_respuestapuede ser:"audio"(V-M),"seleccion"(T-S),"orden"(T-A),"timeout"
Response 200 — Continuar con siguiente ejercicio:
{
"estado_sesion": "EN_CURSO",
"decision_motor": {
"accion": "SIGUIENTE",
"metricas": {
"ipf": 83.3,
"lme": 2.0,
"tra_ms": 3200,
"p_maestria": 0.62
},
"ema_score": 79.5,
"hardware_override": null
},
"siguiente_ejercicio": {
"id_actividad": "ACT_043",
"plantilla": "Identificador",
"hardware_req": "T-S",
"prompt_audio": {
"audio_url": "https://cdn.appfasia.com/recursos/audios/instruccion_04.mp3",
"texto_estimulo": "Toca la ropa que usarías si hace frío"
},
"opciones": [
{ "id": "W_210", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/abrigo.png" },
{ "id": "W_211", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/shorts.png" },
{ "id": "W_212", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/camiseta.png" }
],
"umbrales": { "tra_max_ms": 4000 }
},
"avatar_mensaje": "¡Casi! Inténtalo una vez más despacio."
}Response 200 — Cambio de modalidad (hardware override):
{
"estado_sesion": "EN_CURSO",
"decision_motor": {
"accion": "CAMBIO_MODALIDAD",
"hardware_override": "T-S",
"razon": "IPF < 50% en 3 intentos consecutivos"
},
"siguiente_ejercicio": { ... },
"avatar_mensaje": "¡Probemos de otra forma! Ahora toca la imagen correcta."
}Response 200 — Lanzar minijuego:
{
"estado_sesion": "EN_CURSO",
"decision_motor": {
"accion": "MINIJUEGO",
"tipo_minijuego": "Memorama_Auditivo"
},
"minijuego": {
"id_minijuego": "MJ_003",
"tipo": "Memorama_Auditivo",
"instruccion": "Encuentra los pares que suenan igual",
"pares": [
{ "id": "P1", "audio_url": "https://cdn.appfasia.com/recursos/audios/perro.mp3" },
{ "id": "P1_img", "imagen_url": "https://cdn.appfasia.com/recursos/imagenes/perro.png" }
]
},
"avatar_mensaje": "¡3 en fila! ¡Eres increíble! Ganaste un juego especial."
}Response 200 — Fin de sesión:
{
"estado_sesion": "COMPLETADA",
"resumen_sesion": {
"ejercicios_completados": 4,
"precision_promedio_ipf": 81.2,
"hitos_dominados_hoy": 1,
"racha_dias": 6
},
"avatar_mensaje": "¡Lo hiciste increíble hoy, Lucía! Descansa y mañana seguimos.",
"proxima_sesion_disponible": "2026-05-13T00:00:00Z"
}Verifica si hay una sesión activa (para resumir si el niño cerró la app).
Response 200 — Sesión activa:
{
"session_id": "sess-uuid-001",
"ejercicios_completados": 2,
"ejercicios_max": 4,
"ejercicio_actual": { ... }
}Response 204 — No hay sesión activa.
Termina la sesión explícitamente (el niño cierra la app o el tutor detiene la sesión).
Response 200:
{
"session_id": "sess-uuid-001",
"estado": "INTERRUMPIDA",
"ejercicios_completados": 2,
"datos_guardados": true
}Resumen ejecutivo del progreso, traducido a lenguaje para padres.
Response 200:
{
"child_id": "uuid-child-001",
"nombre": "Lucía",
"nivel_actual": 2,
"descripcion_nivel": "Estructuración Telegráfica y Expansión (2 a 4 años)",
"racha_dias": 6,
"resumen_semana": {
"sesiones_completadas": 5,
"minutos_totales": 52,
"palabras_practicadas": 38,
"hitos_dominados": 2
},
"metricas_traducidas": {
"precision_habla": "Su pronunciación mejoró un 12% esta semana.",
"velocidad_respuesta": "Responde más rápido que la semana pasada.",
"nivel_equivalente": "Su nivel de lenguaje equivale al de un niño de 3 años y 2 meses."
},
"alertas": [
{
"tipo": "REZAGO",
"mensaje": "Lucía tiene dificultad con los colores básicos. El sistema ya está trabajando en ello.",
"nivel": "INFO"
}
]
}Historial de sesiones para el panel de padres.
Query params: ?limit=10&offset=0
Response 200:
{
"total": 23,
"sessions": [
{
"session_id": "sess-uuid-001",
"fecha": "2026-05-12T18:30:00Z",
"duracion_min": 11,
"ejercicios": 4,
"ipf_promedio": 81.2,
"etiqueta_tutor": null
}
]
}El tutor etiqueta una sesión con factores externos (Sección 19 del plan).
Request:
{
"etiqueta": "Cansancio",
"nota": "Durmió mal la noche anterior"
}
etiquetapuede ser:"Cansancio","Distracción","Enfermedad","Otro"
Response 200:
{
"session_id": "sess-uuid-001",
"etiqueta": "Cansancio",
"r0_weight_ajustado": 0.2,
"mensaje": "El rendimiento de esta sesión tendrá menos peso en el cálculo del progreso de Lucía."
}El tutor reporta un avance observado fuera de la app (Sección 19 del plan).
Request:
{
"descripcion": "Hoy dijo su primera oración completa de 4 palabras en casa.",
"id_hito_relacionado": "H_N2_001"
}Response 200:
{
"mensaje": "¡Excelente noticia! Hemos programado una prueba de verificación para la próxima sesión de Lucía.",
"prueba_verificacion_programada": true
}Envía un mensaje al chatbot de padres y recibe la respuesta del LLM.
Request:
{
"child_id": "uuid-child-001",
"mensaje": "¿Qué es la disfasia y cómo puedo ayudar a Lucía en casa?",
"historial": [
{ "rol": "user", "contenido": "¿Qué significa IPF?" },
{ "rol": "assistant", "contenido": "El IPF es el Índice de Precisión Fonológica..." }
]
}
historialcontiene los últimos N turnos de la conversación (el frontend lo gestiona).
Máximo 10 turnos recomendado para no saturar el context window.
Response 200:
{
"respuesta": "La disfasia es una dificultad en la adquisición del lenguaje durante la infancia...",
"modelo_usado": "gemini-2.5-flash",
"fuente_sugerida": "Si deseas profundizar, te recomiendo consultar con un logopeda especializado."
}| Módulo | Método | Ruta | Auth | Descripción |
|---|---|---|---|---|
| Auth | POST | /auth/register |
❌ | Registro de tutor |
| Auth | POST | /auth/login |
❌ | Login → JWT |
| Auth | POST | /auth/refresh |
❌ | Renovar token |
| Auth | GET | /auth/me |
✅ | Perfil del tutor |
| Children | POST | /children |
✅ | Crear perfil de niño |
| Children | GET | /children |
✅ | Listar niños |
| Children | GET | /children/{child_id} |
✅ | Detalle de niño |
| Children | PUT | /children/{child_id} |
✅ | Actualizar niño |
| Diagnostic | POST | /diagnostic/start |
✅ | Iniciar diagnóstico |
| Diagnostic | POST | /diagnostic/response |
✅ | Responder diagnóstico |
| Diagnostic | GET | /diagnostic/result/{child_id} |
✅ | Resultado diagnóstico |
| Session | POST | /session/start |
✅ | Iniciar sesión diaria |
| Session | POST | /session/response |
✅ | Enviar respuesta → motor |
| Session | GET | /session/current/{child_id} |
✅ | Sesión activa actual |
| Session | POST | /session/{session_id}/end |
✅ | Terminar sesión |
| Progress | GET | /progress/{child_id} |
✅ | Dashboard resumen |
| Progress | GET | /progress/{child_id}/sessions |
✅ | Historial de sesiones |
| Progress | POST | /progress/{child_id}/sessions/{session_id}/label |
✅ | Etiquetar sesión |
| Progress | POST | /progress/{child_id}/external-advance |
✅ | Reportar avance externo |
| Chatbot | POST | /chatbot/message |
✅ | Mensaje al asistente de padres |