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

14 KiB

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:

{
  "email": "user@example.com",
  "password": "SecurePass123!",
  "firstName": "John",
  "lastName": "Doe"
}

Response:

{
  "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:

{
  "email": "user@example.com",
  "password": "SecurePass123!"
}

Response:

{
  "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:

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}

Response:

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
  }
}

POST /auth/logout

Invalida tokens (agrega refresh token a blacklist).

Headers:

Authorization: Bearer {access_token}

Request:

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}

Response:

{
  "success": true,
  "message": "Logout successful"
}

GET /auth/me

Obtiene perfil del usuario autenticado.

Response:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "answer": "(4, 6)",
  "timeSpent": 120,
  "showHints": true
}

Response:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "topicId": "topic-1",
  "difficulty": "INTERMEDIATE",
  "type": "CALCULATION",
  "context": "Vectores en 3D"
}

Response:

{
  "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:

{
  "exerciseId": "ex-1",
  "userAnswer": "(4, 6)",
  "context": "Suma de vectores 2D"
}

Response:

{
  "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

{
  "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:

{
  "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:

{
  "data": [...],
  "pagination": {
    "total": 150,
    "limit": 20,
    "offset": 0,
    "hasMore": true,
    "nextCursor": "eyJpZCI6..."
  }
}