> ## Documentation Index
> Fetch the complete documentation index at: https://help.impactu.colav.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Enviar archivo de Staff

> Sube un Excel de talento humano (.xlsx), lo valida contra las reglas de negocio y devuelve un reporte de calidad en PDF.

> [!NOTE]
>
> Requiere sesión activa. El JWT se lee desde la cookie `access_token_cookie`
> y la solicitud debe llevar el encabezado `X-CSRF-TOKEN`. Se envía como
> `multipart/form-data`.

El reporte de calidad se envía por correo cada vez que el archivo se puede validar. Si el archivo no tiene errores, se guardan en la carpeta de la institución en Google Drive dos copias: el archivo original, con el prefijo `ORIGINAL_`, y el normalizado. Si Drive falla, se guardan en el almacenamiento local del servidor.

## Cuerpo de la solicitud

**file** `file` *required*

Archivo Excel `.xlsx` con los datos de talento humano. Debe contener una fila
por persona vinculada. Otro formato, un archivo que no se puede leer o un
archivo sin datos responden `400`.

## Formato del archivo

Todas las columnas de la tabla deben estar en el archivo, salvo `nombre_completo`, que es opcional. Si falta alguna o hay una columna sin nombre con datos, responde `422`. Los encabezados se reconocen sin importar mayúsculas, tildes ni espacios alrededor, y las columnas que no están en la tabla se ignoran.

| Columna | Valor obligatorio | Descripción |
| - | - | - |
| `tipo_documento` | ✅ | Tipo de documento de identidad. |
| `identificacion` | ✅ | Número de documento. |
| `primer_apellido` | ✅\* | Primer apellido. Requerido si no se envía `nombre_completo`. |
| `segundo_apellido` | — | Segundo apellido. Puede estar vacío sin penalización. |
| `nombres` | ✅\* | Nombres. Requerido si no se envía `nombre_completo`. |
| `nombre_completo` | — | Nombre completo. Si la columna está presente, reemplaza `primer_apellido`, `segundo_apellido` y `nombres`, que dejan de ser obligatorias. No puede contener números. |
| `orcid` | — | ORCID. Se normaliza a `https://orcid.org/0000-0000-0000-0000`. |
| `cvlac` | — | CvLAC. Se guarda el código, aunque venga la URL con `cod_rh`. |
| `scholar` | — | Google Scholar. Se normaliza a `https://scholar.google.com/citations?user=...`. |
| `nivel_academico` | — | Valor de catálogo. Fuera de catálogo → normalizado a `desconocido`. |
| `tipo_contrato` | — | Valor de catálogo. Fuera de catálogo → normalizado a `desconocido`. |
| `jornada_laboral` | — | Valor de catálogo. Fuera de catálogo → normalizado a `desconocido`. |
| `categoria_laboral` | — | Valor de catálogo. Fuera de catálogo → normalizado a `desconocido`. |
| `sexo` | — | Valor de catálogo. Fuera de catálogo → normalizado a `desconocido`. |
| `fecha_nacimiento` | — | Fecha en formato `DD/MM/YYYY`. |
| `fecha_inicial_vinculacion` | — | Fecha en formato `DD/MM/YYYY`. |
| `fecha_final_vinculacion` | — | Fecha en formato `DD/MM/YYYY`. |
| `codigo_unidad_academica` | ✅ | Código único de la unidad académica. |
| `unidad_academica` | ✅ | Nombre de la unidad académica. |
| `codigo_subunidad_academica` | — | Puede estar vacío sin penalización. |
| `subunidad_academica` | — | Puede estar vacío sin penalización. |

> [!NOTE]
>
> Los campos de catálogo (`sexo`, `nivel_academico`, etc.) no generan error si
> su valor no pertenece al catálogo, pero se normalizan a `desconocido` y se
> reportan como advertencia. Las fechas con alias de "sin información" (`n/a`,
> `no aplica`, etc.) también se normalizan a `desconocido`.

Las filas en blanco se ignoran sin correr la numeración: cada hallazgo del reporte apunta a su fila original de la hoja.

## Respuesta

**success** `boolean`

`true` si el archivo no tiene errores. Con errores, la respuesta es `400` con
el mismo reporte.

**errors** `integer`

Número de errores encontrados en el archivo.

**warnings** `integer`

Número de advertencias.

**duplicates** `integer`

Número de registros duplicados detectados.

**normalized\_unique\_values\_count** `integer`

Número de valores distintos que se normalizaron (por ejemplo, `M` → `hombre`).

**pdf\_base64** `string | null`

Reporte de calidad en formato PDF codificado en Base64. Incluye el resumen
de errores, advertencias y normalizaciones aplicadas. `null` si no hay nada
que reportar.

**file\_msg** `string`

Solo con `200`: resultado del guardado del archivo normalizado.

**msg** `string`

Solo en los errores: motivo del rechazo. Si faltan columnas o hay columnas
sin nombre, la respuesta es `422` y `details` lista cada problema. Si el
archivo no se puede guardar, la respuesta es `500`.

```json 200 theme={null}
{
  "success": true,
  "errors": 0,
  "warnings": 3,
  "duplicates": 0,
  "normalized_unique_values_count": 2,
  "pdf_base64": "JVBERi0xLjQKJ...",
  "file_msg": "Archivo staff_example-institution-id_2026-10-15_14:32.xlsx guardado correctamente."
}
```

```json 400 theme={null}
{ "success": false, "msg": "Archivo requerido" }
```

```json 400 — archivo con errores theme={null}
{
  "success": false,
  "errors": 2,
  "warnings": 1,
  "duplicates": 1,
  "normalized_unique_values_count": 0,
  "pdf_base64": "JVBERi0xLjQKJ..."
}
```

```json 400 — archivo vacío theme={null}
{ "success": false, "msg": "El archivo cargado está vacío. Verifique que contenga información." }
```

```json 401 theme={null}
{"msg": "Token inválido o expirado", "success": false}
```

```json 422 theme={null}
{
  "success": false,
  "errors": 1,
  "duplicates": 0,
  "msg": "El archivo enviado no cumple con el formato requerido de columnas",
  "details": ["Columnas faltantes: orcid, cvlac, scholar"],
  "pdf_base64": "JVBERi0xLjQKJ..."
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.