Saltar a contenido

API REST

Eval360Pro expone una API REST con documentación interactiva via Swagger / OpenAPI.

Acceso a Swagger UI

En producción, /swagger muestra la API pública (/api/v1), pensada para integradores:

https://{slug}.eval360pro.com/swagger

Ahí ves los endpoints públicos, sus schemas y puedes probarlos autenticándote con tu API key (botón AuthorizeX-Api-Key; la clave se crea en Integraciones).

En desarrollo (la app corriendo en local) el mismo /swagger incluye además la API interna completa (autenticación JWT). La API interna no se expone en producción.

Autenticación

Dos esquemas soportados (según el endpoint):

A) JWT Bearer (recomendado para clientes API)

  1. Obtener token:
    POST /api/auth/token
    Content-Type: application/json
    
    {
      "email": "tu@email.com",
      "password": "tu-password",
      "tenantSlug": "acme"   // opcional si el subdominio ya identifica el tenant
    }
    

Respuesta:

{
  "accessToken": "eyJ...",
  "refreshToken": "eyJ...",
  "expiresInSeconds": 3600,
  "user": { "id": "...", "email": "...", "fullName": "...", "roles": [...] }
}

  1. Usar el token en cada request:

    GET /api/employees
    Authorization: Bearer eyJ...
    

  2. Renovar antes de que expire (~1 hora):

    POST /api/auth/refresh
    Content-Type: application/json
    
    { "refreshToken": "eyJ..." }
    

  3. Logout (invalida el refresh token):

    POST /api/auth/logout
    Authorization: Bearer eyJ...
    

Si tu cliente es un browser ya logueado en la app, las cookies se envían automáticamente. Funciona en endpoints que aceptan ambos schemes (AuthSchemes.Cookie + AuthSchemes.Jwt).

Códigos de error estándar

HTTP errorCode Significado
400 VALIDATION Body inválido. Ver validationErrors[] con campo + mensaje
400 BAD_REQUEST Request malformado
401 (sin body) Token ausente o inválido
403 (sin body) Autenticado pero sin rol
403 TENANT_SUSPENDED El tenant del usuario está suspendido
403 TENANT_CANCELLED El tenant del usuario fue cancelado
404 NOT_FOUND Recurso no existe
409 ONBOARDING_REQUIRED El tenant no completó el wizard de onboarding
409 PLAN_LIMIT_EMPLOYEES Se superaría el límite del plan al crear empleados
409 PLAN_LIMIT_CYCLES Se superaría el límite de ciclos del año
429 RATE_LIMITED Demasiados requests. Esperar y reintentar
500 (sin body) Error interno. Mirar audit log + Serilog

Forma del body de error:

{
  "success": false,
  "errorCode": "PLAN_LIMIT_EMPLOYEES",
  "errorMessage": "El plan 'Starter' permite 50 empleados activos. Actualmente hay 50.",
  "validationErrors": []
}

Endpoints principales

Lista de los grupos de endpoints. Detalle exacto en Swagger.

Auth (/api/auth/*)

Método Path Auth Descripción
POST /token Anonymous Login → JWT + refresh token
POST /refresh Anonymous Renovar JWT
POST /logout Bearer Invalidar refresh token

Rate limited (auth policy).

Tenants (/api/tenants/*) — solo SystemAdmin

Método Path Descripción
GET / Listar tenants (con filtro opcional search, status)
GET /{id} Detalle de un tenant
POST / Crear tenant + primer admin
PUT /{id} Editar tenant
POST /{id}/status/{status} Cambiar status (0=Trial, 1=Active, 2=Suspended, 3=Cancelled)

Plans (/api/plans/*) — solo SystemAdmin

Método Path Descripción
GET / Listar planes
GET /{id} Detalle
POST / Crear plan
PUT /{id} Editar plan
DELETE /{id} Eliminar (solo si no hay tenants asignados)
POST /assign/{tenantId} Asignar plan a tenant. Body: { planId: Guid }
GET /usage/{tenantId} Snapshot de uso del tenant (empleados actuales/máx, ciclos)

Employees (/api/employees/*) — HRManager / TenantAdmin

Método Path Descripción
GET / Listar empleados (paginado, filtros: search, departmentId, status)
GET /options Lista compacta para dropdowns
GET /{id} Detalle
POST / Crear empleado
PUT /{id} Editar
DELETE /{id} Soft-delete
POST /{id}/photo Subir foto
POST /{id}/invite Crear cuenta de acceso + enviar email con contraseña temporal
POST /{id}/reset-password Generar nueva contraseña temporal
POST /import-csv Importar masivo desde CSV (multipart, max 2 MB)

Departments (/api/departments/*)

CRUD básico + listado tipo árbol.

Job Profiles (/api/job-profiles/*)

CRUD + versionado (POST /{id}/version clona como nueva versión).

Competencies (/api/competencies/*)

CRUD + import CSV (POST /import-csv).

Competency Categories (/api/competency-categories/*)

CRUD básico.

Skill Frameworks (/api/skill-frameworks/*)

CRUD + import JSON (formato genérico, tipo SFIA). Frameworks pueden ser globales (gestionados por SystemAdmin) o propios del tenant.

Evaluation Templates (/api/evaluation-templates/*)

CRUD + clonado para versionado.

Evaluation Cycles (/api/evaluation-cycles/*)

Método Path Descripción
GET / Listar ciclos
GET /{id} Detalle
POST / Crear ciclo
PUT /{id} Editar
POST /{id}/status/{status} Cambiar status (0=Draft, 1=Open, 2=InProgress, 3=Closed, 4=Archived)
POST /{id}/generate-evaluations Crear evaluaciones para todos los empleados activos
POST /{id}/auto-assign-peers Auto-asignar pares a todos los subjects
POST /{id}/auto-assign-direct-reports Auto-asignar reportes directos como evaluadores

My Evaluations (/api/my-evaluations/*) — cualquier usuario

Método Path Descripción
GET / Listar evaluaciones donde soy participant
GET /{id} Detalle de la evaluación
POST /{id}/respond Guardar respuestas (auto-save de borrador)
POST /{id}/submit Enviar (validar + lockear)
POST /{id}/acknowledge Acuso recibo de mis resultados (como subject)

Evaluation Results (/api/evaluation-results/*)

Resultados agregados de un ciclo, exports a PDF.

Peer Assignments (/api/peer-assignments/*)

Asignar/quitar peers manualmente.

Email Triggers (/api/email-triggers/*)

Método Path Descripción
POST /cycle/{id}/notify-opened Disparar cycle-opened
POST /cycle/{id}/deadline-reminder Disparar deadline-reminder (a quienes no enviaron)
POST /cycle/{id}/results-published Disparar results-published a los subjects

Email Templates (/api/email-templates/*)

CRUD del editor + send-test. Scope tenant o platform según rol.

Email Settings (/api/email-settings/*)

Configuración del proveedor de email del tenant.

Goals (/api/goals/*) y Key Results

CRUD + reportes de avance.

Development Plans (/api/development-plans/*) y Actions

CRUD + flujo de aprobación.

Career Paths (/api/career-paths/*)

CRUD de paths + readiness por empleado.

Gap Analysis (/api/gap-analysis/*)

Snapshot de brechas, análisis on-demand.

Gap Heatmap (/api/gap-heatmap/*)

Datos del heatmap + export Excel.

Nine Box (/api/nine-box/*)

Datos del 9-Box + export Excel.

Calibration (/api/calibration/*)

Sesiones de calibración (HR override de scores).

Dashboards (/api/dashboards/*)

Datos para dashboards (organizacional, plataforma, manager).

My Dashboard (/api/my-dashboard/*)

Datos del dashboard personal del empleado.

Tenant Settings (/api/tenant-settings/*)

Configuración del tenant (branding, locale).

Platform Settings (/api/platform-settings/*) — solo SystemAdmin

Método Path Descripción
GET /email Leer configuración de email de plataforma
PUT /email Guardar configuración de email

Users Admin (/api/users-admin/*) — TenantAdmin

Método Path Descripción
GET / Listar usuarios del tenant
POST / Crear usuario
PUT /{id} Editar (incluye roles)
POST /{id}/reset-password Generar contraseña temporal nueva
POST /{id}/activate / /deactivate Toggle activo
POST /{id}/unlock Desbloquear cuenta
GET /{id}/sessions Listar tokens activos
POST /{id}/revoke-all-sessions Revocar todas las sesiones

Audit Logs (/api/audit-logs/*) — TenantAdmin / SystemAdmin

Método Path Descripción
GET / Listar eventos (filtros: eventType, entityType, dateFrom, dateTo)
GET /{id} Detalle

Notifications (/api/notifications/*) — cualquier usuario

Método Path Descripción
GET / Mis notificaciones
GET /unread-count Cantidad no leídas (para el badge)
POST /{id}/mark-read Marcar como leída

Files (/api/files/*)

Upload / download de archivos (fotos, evidencias).

My Profile (/api/my-profile/*)

Perfil del usuario actual: get, update, change avatar, change password.

Convenciones

Naming

  • Snake-case en URLs (/api/development-plans no /api/developmentPlans)
  • camelCase en JSON request/response (configurado en Program.cs con JsonNamingPolicy.CamelCase)

Paginación

Endpoints de listado típicamente:

GET /api/employees?page=1&pageSize=50&search=...&departmentId=...&status=...
Default page=1, pageSize=50. Max pageSize=200.

Response paginado:

{
  "items": [...],
  "totalCount": 1234,
  "page": 1,
  "pageSize": 50,
  "totalPages": 25
}

IDs

Todos los IDs son Guid (UUID v4). Generados client o server-side.

Timestamps

Todos en UTC, formato ISO 8601 (2026-05-09T15:30:00Z).

Soft delete

Las entidades de negocio (Employee, JobProfile, etc.) usan soft-delete. DELETE /api/... marca IsDeleted=true, no borra físicamente.

Multi-tenancy en API

El tenant del request se resuelve por (en orden): 1. Claim tenant_id del JWT/cookie 2. Header X-Tenant: {slug} (para clientes confiables) 3. Subdominio del request (acme.eval360pro.com → tenant slug acme)

Si el tenant del usuario no matchea con el del subdominio, devuelve 401 con errorCode: TENANT_MISMATCH.

Rate limiting

Aplicado por IP del cliente: - Política auth (login, refresh, password reset, 2FA challenge): 10 req/min/IP - Default global: 200 req/min/IP

Si se supera: HTTP 429 con errorCode: RATE_LIMITED.

API pública v1 (/api/v1/*) — integradores y BI

Superficie de solo lectura para consumo externo, autenticada por API key (header X-Api-Key, se crea en Integraciones). El tenant se resuelve desde la propia clave. Es la que /swagger muestra en producción.

Método Path Descripción
GET /ping Verifica la clave; devuelve el tenant resuelto
GET /employees Empleados (paginado: page, pageSize ≤ 200; filtros search, departmentId, status)
GET /cycles Ciclos de evaluación
GET /goals Objetivos / OKR con avance
GET /pulse-surveys Encuestas de pulso (eNPS y fechas)
GET /pulse-surveys/{id}/results Resultados de una encuesta (respeta el umbral de anonimato)
GET /datasets/scores Plano: resultados por ciclo × colaborador (?cycleId= opcional)
GET /datasets/gaps Plano: brechas por ciclo × colaborador × requisito (?cycleId= opcional)
GET /datasets/nine-box Plano: 9-Box por ciclo × colaborador (?cycleId= opcional)

Los datasets/* devuelven filas planas y denormalizadas, con las claves (cycleId, employeeId) para modelar en estrella. Guía paso a paso para conectar Power BI (y similares): Power BI y otras herramientas de BI.

Versionado

La API interna (/api/*, JWT/cookie) no está versionada: los endpoints se mantienen estables y los cambios breaking se anuncian en el changelog.

La API pública para integradores vive bajo /api/v1/* y es la única que se expone en producción. Versiones nuevas irían en /api/v2, manteniendo v1 mientras haya consumidores.