Convenciones de la API
Headers comunes
Sección titulada «Headers comunes»| Header | Obligatorio | Descripción |
|---|---|---|
x-tenant-id |
Siempre | Alias del tenant. En peticiones autenticadas debe coincidir con el claim tenant del JWT. |
Authorization |
En endpoints autenticados | Bearer <jwt> obtenido en login/refresh. |
Content-Type |
En POST/PATCH/PUT | application/json. |
Dos generaciones de rutas
Sección titulada «Dos generaciones de rutas»La API tiene dos generaciones de endpoints activas y equivalentes en autenticación:
| Generación | Prefijo | Ejemplo |
|---|---|---|
| Legacy (v1) | sin prefijo | GET /me/time-off/balance-annual |
| API v2 | /v2 |
GET /v2/me/events |
La superficie que consume una app móvil es la de autoservicio: rutas me/* y /v2/me/* (los recursos del usuario autenticado). Las rutas sin me son de administración y requieren permisos adicionales.
Paginación y filtros
Sección titulada «Paginación y filtros»Los listados paginados siguen el estándar de nestjs-paginate.
Query params de entrada:
| Param | Ejemplo | Descripción |
|---|---|---|
page |
page=1 |
Página (base 1). |
limit |
limit=20 |
Ítems por página. |
sortBy |
sortBy=createdAt:DESC |
Orden columna:ASC|DESC. |
search |
search=juan |
Búsqueda de texto libre (columnas definidas por el endpoint). |
filter.<columna> |
filter.status=APPROVED |
Filtro por columna. La clave es plana (filter.status), no un objeto anidado. |
Respuesta:
{ "data": [ ... ], "meta": { "itemsPerPage": 20, "totalItems": 87, "currentPage": 1, "totalPages": 5, "sortBy": [["createdAt", "DESC"]] }, "links": { "current": "...?page=1&limit=20" }}Para el scroll infinito típico de mobile: pide page + 1 mientras currentPage < totalPages.
Formato de errores
Sección titulada «Formato de errores»Los errores siguen el formato estándar de NestJS:
{ "statusCode": 400, "message": "validation error detail", "error": "Bad Request"}message puede ser un string o un array de strings (errores de validación de DTO).
| Código | Significado | Qué debe hacer la app |
|---|---|---|
400 |
Body/params inválidos | Corregir el request; mostrar mensaje de validación. |
401 |
Token expirado/inválido o tenant no coincide | Intentar refresh una vez → reintento → si falla, login. |
403 |
Sin permiso, o usuario deshabilitado | Ocultar/deshabilitar la acción; no reintentar. |
404 |
Recurso o tenant inexistente | Verificar x-tenant-id y el id del recurso. |
409 |
Conflicto de negocio (p. ej. solicitud duplicada) | Mostrar el message al usuario. |
500 |
Error del servidor | Reintentar con backoff; reportar. |
Las fechas viajan como strings ISO 8601 (2026-07-16 o 2026-07-16T14:30:00.000Z). Salvo indicación contraria en el módulo, interpreta fechas de negocio (solicitudes, saldos) como fecha local del tenant, sin conversión de zona horaria.
Enumerados
Sección titulada «Enumerados»Los valores de conjunto cerrado (estados, tipos, flags S/N) se documentan como tablas de enum en cada módulo. Regla general del sistema:
- Flags booleanos legacy usan
'S'(sí) /'N'(no), y a veces'A'según el módulo. - Los estados de solicitudes/procesos son strings en mayúsculas (cada módulo documenta los suyos).
Permisos y visibilidad
Sección titulada «Permisos y visibilidad»Además de estar autenticado, el usuario tiene un perfil de seguridad que habilita módulos y acciones. La app debe construir su menú a partir de GET /me/tenancy/products y de los parámetros del tenant — no asumas que todos los módulos de este manual están activos para todos los tenants ni para todos los usuarios.