Patrón de endpoint
https://[tenant].studeia.com/api/institution/[resource]
Para tenants con dominio personalizado:
https://api.escuela.com/api/institution/[resource]
Autenticación — dual auth
La mayoría de las rutas /api/institution/* acepta 2 modos de autenticación. Las rutas que gestionan credenciales, OAuth, billing, SSO, proveedores de video/avatar y verificación de dominio son session-only por seguridad (no aceptan API key).
Bearer API key
GET /api/institution/courses
Authorization: Bearer mia_abc123...
API key resuelta mediante caché Redis (60s TTL) + lookup por prefijo.
Session cookie
GET /api/institution/courses
Cookie: sb-access-token=...; sb-refresh-token=...
Para llamadas del propio frontend de Studeia.
Scopes (granulares)
Cada ruta de recurso declara requiredScopes; la API key debe tener los scopes correspondientes. El backend reconoce 35 scopes en total.
| Ruta | Scopes |
|---|---|
| courses | courses:read |
| users | users:read |
| enrollments | enrollments:read |
| classes | classes:read |
| media | media:read |
| gradebook | grades:read |
| rubrics | rubrics:read |
| question-banks | question-banks:read |
| live-classes | live-classes:read |
| tags | tags:read |
| invites | invites:read |
| lti-tools | lti:read |
| drive | drive:read |
| settings, themes, api-keys, profile-config | settings:read |
| automations | automations:read |
| prompts, ai-limits | ai:read |
| ai-analytics | reports:read |
| reports | reports:read |
| video-provider | settings:read |
API key con scope vacío ([]) = acceso total (claves admin).
Rate limiting
| Tier | Req/hora | Burst/min |
|---|---|---|
| standard | 1.000 | 100 |
| high | 5.000 | 300 |
| custom | configurable | custom/60 |
Headers de respuesta:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 947
X-RateLimit-Reset: 1716480000
Rate exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 120
{ "error": "rate_limit_exceeded", "retryAfter": 120 }
Patrón de respuesta
Éxito
{
"data": [...],
"pagination": {
"page": 1,
"perPage": 50,
"total": 247,
"totalPages": 5
}
}
Error
{
"error": "validation_failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
}
Status codes:
- 200 OK
- 201 Created
- 204 No Content (DELETE)
- 400 Bad Request (validation)
- 401 Unauthorized (auth inválida)
- 403 Forbidden (sin scope o role)
- 404 Not Found
- 409 Conflict (inconsistencia de estado)
- 422 Unprocessable Entity (regla de negocio)
- 429 Rate limit
- 500 Server error
Paginación
Por defecto: cursor-based.
GET /api/institution/courses?page=1&perPage=50&search=matematica
perPage máx. 100 (cap server-side).
CORS
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept-Language
Access-Control-Max-Age: 86400
Preflight (OPTIONS) responde 204.
i18n
Los errores se localizan mediante el header Accept-Language: es-ES (o en-US, pt-BR, fr-FR). Fallback pt-BR si el idioma no está soportado.
Quickstart
# 1. Genera la API key en /institution/settings > API Keys
# 2. Lista cursos
curl https://[tenant].studeia.com/api/institution/courses \
-H "Authorization: Bearer mia_abc123..." \
-H "Accept-Language: es-ES"
# 3. Crea un alumno
curl -X POST https://[tenant].studeia.com/api/institution/users \
-H "Authorization: Bearer mia_abc123..." \
-H "Content-Type: application/json" \
-d '{
"name": "Maria Silva",
"email": "maria@example.com",
"role": "student",
"sendInvite": true
}'
Grupos de endpoints (33 grupos)
Documentación detallada por grupo en /docs/api/[group]:
- Institución, Cursos, Módulos, Lecciones, Usuarios, Matrículas, Grupos
- Medios, Calificaciones, Rúbricas, Banco de Preguntas, Clases en Vivo, Video Providers
- Webhooks, Invitaciones, Tags, LTI, Configuraciones, Automatizaciones
- RAG, Reportes, Análisis IA, Gamificación, Email, Drive, Calendario