Files
math2-platform/docs/API.md
Renato bc43c9e772
Some checks failed
Test Suite / test-backend (push) Has been cancelled
Test Suite / test-frontend (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / coverage-check (push) Has been cancelled
🎓 Initial commit: Math2 Platform - Plataforma de Álgebra Lineal PRO
 Características:
- 45 ejercicios universitarios (Basic → Advanced)
- Renderizado LaTeX profesional
- IA generativa (Z.ai/DashScope)
- Docker 9 servicios
- Tests 123/123 pasando
- Seguridad enterprise (JWT, XSS, Rate limiting)

🐳 Infraestructura:
- Next.js 14 + Node.js 20
- PostgreSQL 15 + Redis 7
- Docker Compose completo
- Nginx + SSL ready

📚 Documentación:
- 5 informes técnicos completos
- README profesional
- Scripts de deployment automatizados

Estado: Producción lista 
2026-03-31 11:27:11 -03:00

778 lines
14 KiB
Markdown

# API Documentation
## Base URL
```
Development: http://localhost:3001/api
Production: https://api.mathplatform.com/api
```
## Autenticación
Todas las rutas (excepto auth) requieren header:
```
Authorization: Bearer {jwt_token}
```
### Flujo de Autenticación
1. **Registro/Login**: Obtiene access token (15 min) + refresh token (7 días)
2. **API Calls**: Usa access token en header
3. **Refresh**: Cuando expira, usa refresh token para obtener nuevo access token
4. **Logout**: Invalida refresh token (agregado a blacklist en Redis)
## Endpoints
### Auth
#### POST /auth/register
Registra nuevo usuario.
**Request:**
```json
{
"email": "user@example.com",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe"
}
```
**Response:**
```json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "USER",
"createdAt": "2024-03-30T12:00:00.000Z"
}
}
}
```
#### POST /auth/login
Autentica usuario existente.
**Request:**
```json
{
"email": "user@example.com",
"password": "SecurePass123!"
}
```
**Response:**
```json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "USER"
}
}
}
```
#### POST /auth/refresh
Renueva access token usando refresh token.
**Request:**
```json
{
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}
```
**Response:**
```json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}
}
```
#### POST /auth/logout
Invalida tokens (agrega refresh token a blacklist).
**Headers:**
```
Authorization: Bearer {access_token}
```
**Request:**
```json
{
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}
```
**Response:**
```json
{
"success": true,
"message": "Logout successful"
}
```
#### GET /auth/me
Obtiene perfil del usuario autenticado.
**Response:**
```json
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "USER",
"createdAt": "2024-03-30T12:00:00.000Z",
"lastLoginAt": "2024-03-30T12:00:00.000Z"
}
}
```
### Modules
#### GET /modules
Lista todos los módulos pedagógicos.
**Response:**
```json
{
"success": true,
"data": [
{
"id": "mod-1",
"name": "Fundamentos",
"description": "Conceptos básicos de álgebra lineal",
"type": "FUNDAMENTOS",
"order": 1,
"topicCount": 5,
"exerciseCount": 25
},
{
"id": "mod-2",
"name": "Sistemas y Espacios",
"description": "Sistemas de ecuaciones y espacios vectoriales",
"type": "SISTEMAS_ESPACIOS",
"order": 2,
"topicCount": 4,
"exerciseCount": 30
},
{
"id": "mod-3",
"name": "Aplicaciones",
"description": "Aplicaciones prácticas de álgebra lineal",
"type": "APLICACIONES",
"order": 3,
"topicCount": 3,
"exerciseCount": 20
}
]
}
```
#### GET /modules/:id
Obtiene detalle de un módulo específico.
**Response:**
```json
{
"success": true,
"data": {
"id": "mod-1",
"name": "Fundamentos",
"description": "Conceptos básicos de álgebra lineal",
"type": "FUNDAMENTOS",
"order": 1,
"topics": [
{
"id": "topic-1",
"name": "Vectores",
"description": "Operaciones con vectores",
"order": 1
}
],
"progress": {
"completedExercises": 10,
"totalExercises": 25,
"percentage": 40
}
}
}
```
### Topics
#### GET /topics
Lista todos los temas.
**Query Parameters:**
- `moduleId` (optional): Filtrar por módulo
**Response:**
```json
{
"success": true,
"data": [
{
"id": "topic-1",
"name": "Vectores",
"description": "Operaciones con vectores",
"moduleId": "mod-1",
"type": "VECTORES",
"order": 1,
"exerciseCount": 8
}
]
}
```
#### GET /topics/:id/theory
Obtiene contenido teórico de un tema.
**Response:**
```json
{
"success": true,
"data": {
"id": "topic-1",
"name": "Vectores",
"content": {
"introduction": "Los vectores son...",
"formulas": [
{
"name": "Magnitud",
"latex": "\\|\\vec{v}\\| = \\sqrt{x^2 + y^2}"
}
],
"examples": [
{
"problem": "Calcular la magnitud del vector...",
"solution": "Usando la fórmula...",
"latex": "\\vec{v} = (3, 4)"
}
]
}
}
}
```
### Exercises
#### GET /exercises
Lista ejercicios con filtros.
**Query Parameters:**
- `moduleId` (optional): Filtrar por módulo
- `topicId` (optional): Filtrar por tema
- `difficulty` (optional): BASIC | INTERMEDIATE | ADVANCED | EXPERT
- `type` (optional): MULTIPLE_CHOICE | OPEN_RESPONSE | CALCULATION | PROOF | TRUE_FALSE
- `limit` (optional): Número de resultados (default: 20)
- `offset` (optional): Paginación (default: 0)
**Response:**
```json
{
"success": true,
"data": {
"exercises": [
{
"id": "ex-1",
"title": "Suma de vectores",
"description": "Calcular la suma de dos vectores",
"type": "CALCULATION",
"difficulty": "BASIC",
"topicId": "topic-1",
"latex": "\\vec{a} = (1, 2), \\vec{b} = (3, 4)",
"points": 10,
"hints": ["Recuerda sumar componente a componente"],
"createdAt": "2024-03-30T12:00:00.000Z"
}
],
"pagination": {
"total": 100,
"limit": 20,
"offset": 0,
"hasMore": true
}
}
}
```
#### GET /exercises/:id
Obtiene detalle de un ejercicio.
**Response:**
```json
{
"success": true,
"data": {
"id": "ex-1",
"title": "Suma de vectores",
"description": "Calcular la suma de dos vectores",
"type": "CALCULATION",
"difficulty": "BASIC",
"topic": {
"id": "topic-1",
"name": "Vectores"
},
"module": {
"id": "mod-1",
"name": "Fundamentos"
},
"latex": "\\vec{a} = (1, 2), \\vec{b} = (3, 4)",
"questions": [
{
"id": "q-1",
"text": "¿Cuál es la suma de los vectores?",
"options": [
"(4, 6)",
"(3, 4)",
"(1, 2)",
"(5, 8)"
]
}
],
"points": 10,
"hints": ["Suma las componentes x", "Suma las componentes y"],
"timeEstimate": 300
}
}
```
#### POST /exercises/:id/attempt
Envía respuesta a ejercicio.
**Request:**
```json
{
"answer": "(4, 6)",
"timeSpent": 120,
"showHints": true
}
```
**Response:**
```json
{
"success": true,
"data": {
"attemptId": "att-123",
"isCorrect": true,
"score": 10,
"feedback": "¡Correcto! La suma de vectores se realiza componente a componente.",
"solution": {
"steps": [
"\\vec{a} + \\vec{b} = (1+3, 2+4)",
"= (4, 6)"
],
"latex": "\\vec{a} + \\vec{b} = (4, 6)"
},
"progress": {
"moduleCompleted": false,
"newAchievements": ["first-step"]
}
}
}
```
### Progress
#### GET /progress
Obtiene progreso general del usuario.
**Response:**
```json
{
"success": true,
"data": {
"overall": {
"totalExercises": 75,
"completedExercises": 25,
"percentage": 33.3,
"totalScore": 250,
"averageScore": 10
},
"modules": [
{
"moduleId": "mod-1",
"moduleName": "Fundamentos",
"completedExercises": 15,
"totalExercises": 25,
"percentage": 60,
"score": 150
}
],
"streak": {
"current": 5,
"longest": 12,
"lastActivity": "2024-03-30T10:00:00.000Z"
}
}
}
```
#### GET /progress/module/:moduleId
Obtiene progreso de un módulo específico.
**Response:**
```json
{
"success": true,
"data": {
"moduleId": "mod-1",
"moduleName": "Fundamentos",
"completedExercises": 15,
"totalExercises": 25,
"percentage": 60,
"score": 150,
"topics": [
{
"topicId": "topic-1",
"topicName": "Vectores",
"completedExercises": 5,
"totalExercises": 8,
"percentage": 62.5
}
],
"recentAttempts": [
{
"exerciseId": "ex-1",
"exerciseTitle": "Suma de vectores",
"isCorrect": true,
"score": 10,
"attemptedAt": "2024-03-30T10:00:00.000Z"
}
]
}
}
```
### Ranking
#### GET /ranking/global
Obtiene ranking global.
**Query Parameters:**
- `limit` (optional): Resultados por página (default: 50)
- `offset` (optional): Paginación (default: 0)
**Response:**
```json
{
"success": true,
"data": {
"rankings": [
{
"position": 1,
"user": {
"id": "user-1",
"firstName": "Alice",
"lastName": "Smith"
},
"score": 1250,
"completedExercises": 75,
"accuracy": 92.5
}
],
"pagination": {
"total": 150,
"limit": 50,
"offset": 0,
"hasMore": true
}
}
}
```
#### GET /ranking/my-position
Obtiene posición del usuario actual.
**Response:**
```json
{
"success": true,
"data": {
"globalPosition": 25,
"score": 450,
"completedExercises": 35,
"accuracy": 85.2,
"modulePositions": [
{
"moduleId": "mod-1",
"moduleName": "Fundamentos",
"position": 15,
"score": 200
}
]
}
}
```
### Achievements
#### GET /achievements
Lista todos los logros disponibles.
**Response:**
```json
{
"success": true,
"data": {
"achievements": [
{
"id": "ach-1",
"name": "Primer Paso",
"description": "Completa tu primer ejercicio",
"category": "EXERCISES",
"rarity": "COMMON",
"icon": "🎯",
"requirement": {
"type": "EXERCISE_COUNT",
"value": 1
}
}
]
}
}
```
#### GET /achievements/my
Obtiene logros desbloqueados del usuario.
**Response:**
```json
{
"success": true,
"data": {
"unlocked": [
{
"id": "ach-1",
"name": "Primer Paso",
"description": "Completa tu primer ejercicio",
"category": "EXERCISES",
"rarity": "COMMON",
"icon": "🎯",
"unlockedAt": "2024-03-30T12:00:00.000Z"
}
],
"progress": [
{
"achievementId": "ach-2",
"name": "En Marcha",
"progress": 5,
"required": 10,
"percentage": 50
}
]
}
}
```
### AI Generation
#### POST /ai/generate-exercise
Genera ejercicio usando AI.
**Request:**
```json
{
"topicId": "topic-1",
"difficulty": "INTERMEDIATE",
"type": "CALCULATION",
"context": "Vectores en 3D"
}
```
**Response:**
```json
{
"success": true,
"data": {
"exercise": {
"title": "Producto cruz en 3D",
"description": "Calcular el producto cruz de dos vectores en 3D",
"latex": "\\vec{a} = (1, 2, 3), \\vec{b} = (4, 5, 6)",
"solution": {
"steps": [
"\\vec{a} \\times \\vec{b} = (2\\cdot6 - 3\\cdot5, 3\\cdot4 - 1\\cdot6, 1\\cdot5 - 2\\cdot4)",
"= (12-15, 12-6, 5-8)",
"= (-3, 6, -3)"
],
"latex": "\\vec{a} \\times \\vec{b} = (-3, 6, -3)"
},
"difficulty": "INTERMEDIATE",
"points": 15
}
}
}
```
#### POST /ai/validate-answer
Valida respuesta usando AI.
**Request:**
```json
{
"exerciseId": "ex-1",
"userAnswer": "(4, 6)",
"context": "Suma de vectores 2D"
}
```
**Response:**
```json
{
"success": true,
"data": {
"isCorrect": true,
"confidence": 0.95,
"feedback": "Respuesta correcta. La suma de vectores (1,2) + (3,4) = (4,6)",
"explanation": "Se sumaron correctamente las componentes x (1+3=4) y y (2+4=6)"
}
}
```
## Códigos de Error
| Código | HTTP | Descripción |
|--------|------|-------------|
| `BAD_REQUEST` | 400 | Datos inválidos o faltantes |
| `UNAUTHORIZED` | 401 | Token inválido o expirado |
| `FORBIDDEN` | 403 | Sin permisos para el recurso |
| `NOT_FOUND` | 404 | Recurso no existe |
| `VALIDATION_ERROR` | 422 | Error de validación de datos |
| `RATE_LIMIT` | 429 | Rate limit excedido |
| `INTERNAL_ERROR` | 500 | Error interno del servidor |
| `SERVICE_UNAVAILABLE` | 503 | Servicio temporalmente no disponible |
### Formato de Error
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Datos de entrada inválidos",
"details": {
"field": "email",
"issue": "Email inválido"
}
},
"meta": {
"timestamp": "2024-03-30T12:00:00.000Z",
"requestId": "req_abc123"
}
}
```
## Rate Limiting
- **Auth endpoints**: 5 requests / 15 min / IP
- **API general**: 100 requests / 15 min / user
- **AI generation**: 10 requests / hour / user
- **Exercise attempts**: Sin limitación
Headers de respuesta:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1711802400
```
## Versionado
La API usa versionado en URL:
- `/api/v1/...` - Versión actual
- `/api/...` - Alias a v1 (default)
## Webhooks (Admin)
### POST /webhooks/telegram
Endpoint para recibir actualizaciones de Telegram.
### POST /webhooks/pdf-processed
Notificación cuando un PDF es procesado.
## Health Check
### GET /health
Verifica estado del servicio.
**Response:**
```json
{
"status": "healthy",
"timestamp": "2024-03-30T12:00:00.000Z",
"version": "1.0.0",
"services": {
"database": "connected",
"redis": "connected",
"ai": "available"
}
}
```
## Paginación
Todas las listas soportan paginación con:
- `limit`: Número de items (max: 100)
- `offset`: Índice inicial (0-based)
- `cursor`: Para paginación basada en cursor (alternativa)
Formato de respuesta paginada:
```json
{
"data": [...],
"pagination": {
"total": 150,
"limit": 20,
"offset": 0,
"hasMore": true,
"nextCursor": "eyJpZCI6..."
}
}
```