Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Glemynart/SaaS/llms.txt
Use this file to discover all available pages before exploring further.
La Oficina Nítida models every employee according to the Colombian civil registry standard: four distinct name fields, a typed document identifier drawn from Colombia’s official catalog, a work-schedule classification, and an optional branch assignment. All employee data is scoped to a single tenant — no record is ever visible across organizations — and every mutating operation is logged to the platform audit trail.
Employee Data Model
The Four-Part Name Structure
Colombian law registers natural persons with up to four name components. La Oficina Nítida stores each component in its own field rather than in a single free-text string:
| Field | Required | Description |
|---|
primerNombre | ✅ | First given name |
segundoNombre | — | Second given name (optional) |
primerApellido | ✅ | First (paternal) surname |
segundoApellido | — | Second (maternal) surname (optional) |
Keeping names disaggregated enables reliable sorting, searching, and document generation. The search query parameter on GET /employees matches independently against every name component and the document number, so a partial match on any part of the name returns the correct result.
Constructing a full name must always be done through the formatNombreCompleto() utility exported from @saas/types:
import { formatNombreCompleto } from '@saas/types';
const fullName = formatNombreCompleto({
primerNombre: 'María',
segundoNombre: 'Camila',
primerApellido: 'Rodríguez',
segundoApellido: 'López',
});
// → "María Camila Rodríguez López"
The function filters out blank or null segments and joins the remaining parts with a single space. It is the only approved way to build a display name anywhere in the platform — frontend or backend.
Document Identity (tipoDocumento)
Every employee carries a structured document identifier. The tipoDocumento field accepts one of seven enum values corresponding to official Colombian identity documents:
| Value | Document |
|---|
CC | Cédula de Ciudadanía |
CE | Cédula de Extranjería |
TI | Tarjeta de Identidad |
PA | Pasaporte |
NIT | Número de Identificación Tributaria |
PEP | Permiso Especial de Permanencia |
PPT | Permiso de Protección Temporal |
The cedula value (the document number itself) is unique per tenant: creating two employees with the same number under the same organization returns 400 Bad Request. If a soft-deleted employee already holds that number, the API surfaces a specific message asking you to reactivate the existing record instead.
Work Schedule (jornadaLaboral)
| Value | Meaning |
|---|
COMPLETA | Full working day |
MEDIA | Half working day |
POR_HORAS | Hourly schedule |
Employee Status (estado)
| Value | Meaning |
|---|
ACTIVO | Currently employed |
INACTIVO | Inactive (set automatically on soft-delete) |
SUSPENDIDO | Employment temporarily suspended |
RETIRADO | Employment terminated; motivoRetiro and fechaRetiro should be populated |
Other Key Fields
cargo — Job title (required). Stored as a snapshot inside each contract so the historical record is preserved even if this field changes later.
salario — Base salary in Colombian pesos (minimum 0).
tipoContrato — Default contract type associated with this employee record (e.g., TERMINO_FIJO, PRESTACION_SERVICIOS).
fechaIngreso — Hire date as an ISO date string (required).
sedeId — Optional UUID reference to a Sede. Must belong to the same tenant; the API validates this cross-tenant constraint on every write.
email — Optional. An empty string is coerced to undefined by the DTO transformer so the field is never stored as an empty string.
salarioIntegral — Boolean flag for integral salary (salario integral). Defaults to false.
municipioExpedicionDocId — DANE municipality code for the document issuance location.
CRUD Operations
All endpoints are protected by JwtAuthGuard and ActiveTenantGuard. The tenant is resolved automatically from the authenticated JWT — you never pass tenantId in the request body.
POST, PATCH, and DELETE additionally require the ADMIN or OPERADOR
role. DELETE is restricted to ADMIN only. GET operations are available
to all roles including VIEWER.
Create an employee
POST /employees
Content-Type: application/json
{
"cedula": "1020304050",
"tipoDocumento": "CC",
"primerNombre": "Carlos",
"segundoNombre": "Andrés",
"primerApellido": "Pérez",
"segundoApellido": "Gómez",
"cargo": "Docente de Primaria",
"salario": 1800000,
"tipoContrato": "TERMINO_FIJO",
"fechaIngreso": "2024-01-15",
"jornadaLaboral": "COMPLETA",
"sedeId": "a1b2c3d4-..."
}
Returns the created employee record with 201 Created.
List employees (paginated)
GET /employees?page=1&limit=10&search=Carlos&estado=ACTIVO
Returns a paginated envelope:
{
"data": [...],
"meta": {
"total": 48,
"page": 1,
"limit": 10,
"totalPages": 5
}
}
Each employee object includes a sedeRef shape ({ id, nombre }) for display purposes.
Get a single employee
Returns the full employee record including sedeRef. Returns 404 if the employee does not exist within the authenticated tenant.
Update an employee
PATCH /employees/:id
Content-Type: application/json
{
"cargo": "Coordinador Académico",
"salario": 2200000
}
All UpdateEmployeeDto fields are optional. The service validates that any new cedula does not collide with another active employee in the same tenant. Updating sedeId re-validates tenant membership.
Delete an employee (soft delete)
Sets deletedAt to the current timestamp and transitions estado to INACTIVO. Employees are never physically removed — their full history (contracts, expediente, alerts) remains intact.
Bulk Import via Excel
For initial onboarding or large roster updates, La Oficina Nítida provides an atomic Excel import workflow. Requires the ADMIN role.
Step 1 — Download the template
GET /employees/import/template
Returns a file download with Content-Disposition: attachment; filename="plantilla_empleados.xlsx". The template contains all required and optional columns with the correct headers and validation hints.
Step 2 — Fill in the data
Populate the spreadsheet following the column definitions. Key points:
- Sede resolution — Enter the sede name as a plain text string. The importer looks up the
Sede by name within the tenant. If no matching sede is found, that row fails validation.
- Date format — Use ISO dates (
YYYY-MM-DD).
- Maximum 500 rows per file. Files exceeding this limit are rejected before any processing begins.
- File size limit — 5 MB maximum.
Step 3 — Upload and import
POST /employees/import
Content-Type: multipart/form-data
file=@plantilla_empleados_filled.xlsx
The import is atomic: the service validates every row first. If any row contains an error (missing required field, duplicate cedula, unknown sede name), the entire import is aborted and a structured error report is returned. No partial writes occur.
A successful response reports the number of employees created and includes a per-row summary.
The maximum import size is 500 rows per file. Files with more rows are
rejected immediately. For large initial loads, split the data into multiple
files and import sequentially.
Search and Filtering
GET /employees accepts the following query parameters via EmployeeQueryDto:
| Parameter | Type | Default | Description |
|---|
search | string | — | Case-insensitive partial match against primerNombre, segundoNombre, primerApellido, segundoApellido, cedula, and email |
estado | EmpleadoEstado | — | Filter by status: ACTIVO, INACTIVO, SUSPENDIDO, or RETIRADO |
page | number | 1 | Page number (1-based) |
limit | number | 10 | Records per page |
Results are always ordered by createdAt descending (most recent first). Soft-deleted employees (deletedAt IS NOT NULL) are excluded from all list responses.
Always use formatNombreCompleto() from @saas/types when you need to
display a person’s full name — in UI components, document generation, alert
descriptions, or audit messages. Manual string concatenation of the four name
fields is not permitted anywhere in the platform. The legacy nombre and
apellido fields were removed in FASE 4B and must not be re-introduced.