Send Staff file
curl --request POST \
--url https://api.dev.impactu.colav.co/submit/staff \
--header 'Content-Type: application/json' \
--data '{}'import requests
url = "https://api.dev.impactu.colav.co/submit/staff"
payload = {}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({})
};
fetch('https://api.dev.impactu.colav.co/submit/staff', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dev.impactu.colav.co/submit/staff",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.dev.impactu.colav.co/submit/staff"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.dev.impactu.colav.co/submit/staff")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dev.impactu.colav.co/submit/staff")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_body{
"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."
}
{ "success": false, "msg": "Archivo requerido" }
{
"success": false,
"errors": 2,
"warnings": 1,
"duplicates": 1,
"normalized_unique_values_count": 0,
"pdf_base64": "JVBERi0xLjQKJ..."
}
{ "success": false, "msg": "El archivo cargado está vacío. Verifique que contenga información." }
{"msg": "Token inválido o expirado", "success": false}
{
"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..."
}
Submit
Send Staff file
Uploads a human resources Excel file (.xlsx), validates it against the business rules and returns a quality report in PDF.
POST
/
submit
/
staff
Send Staff file
curl --request POST \
--url https://api.dev.impactu.colav.co/submit/staff \
--header 'Content-Type: application/json' \
--data '{}'import requests
url = "https://api.dev.impactu.colav.co/submit/staff"
payload = {}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({})
};
fetch('https://api.dev.impactu.colav.co/submit/staff', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dev.impactu.colav.co/submit/staff",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.dev.impactu.colav.co/submit/staff"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.dev.impactu.colav.co/submit/staff")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dev.impactu.colav.co/submit/staff")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_body{
"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."
}
{ "success": false, "msg": "Archivo requerido" }
{
"success": false,
"errors": 2,
"warnings": 1,
"duplicates": 1,
"normalized_unique_values_count": 0,
"pdf_base64": "JVBERi0xLjQKJ..."
}
{ "success": false, "msg": "El archivo cargado está vacío. Verifique que contenga información." }
{"msg": "Token inválido o expirado", "success": false}
{
"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..."
}
Requires an active session. The JWT is read from the
access_token_cookie cookie
and the request must carry the X-CSRF-TOKEN header. It is sent as
multipart/form-data.ORIGINAL_, and the normalized one. If Drive fails, they are saved in the server’s local storage.
Request body
file
required
Excel
.xlsx file with the human resources data. It must contain one row
per affiliated person. Another format, a file that cannot be read or a
file without data return 400.File format
Every column of the table must be in the file, exceptnombre_completo, which is optional. If one is missing or there is an unnamed column with data, it returns 422. Headers are recognized regardless of case, accents or surrounding spaces, and columns that are not in the table are ignored.
| Column | Mandatory value | Description |
|---|---|---|
tipo_documento | ✅ | Type of identity document. |
identificacion | ✅ | Document number. |
primer_apellido | ✅* | First last name. Required if nombre_completo is not sent. |
segundo_apellido | — | Second last name. It can be empty without penalty. |
nombres | ✅* | First names. Required if nombre_completo is not sent. |
nombre_completo | — | Full name. If the column is present, it replaces primer_apellido, segundo_apellido and nombres, which are no longer mandatory. It cannot contain numbers. |
orcid | — | ORCID. Normalized to https://orcid.org/0000-0000-0000-0000. |
cvlac | — | CvLAC. The code is stored, even if the URL with cod_rh is given. |
scholar | — | Google Scholar. Normalized to https://scholar.google.com/citations?user=.... |
nivel_academico | — | Catalogue value. Outside the catalogue → normalized to desconocido. |
tipo_contrato | — | Catalogue value. Outside the catalogue → normalized to desconocido. |
jornada_laboral | — | Catalogue value. Outside the catalogue → normalized to desconocido. |
categoria_laboral | — | Catalogue value. Outside the catalogue → normalized to desconocido. |
sexo | — | Catalogue value. Outside the catalogue → normalized to desconocido. |
fecha_nacimiento | — | Date in the format DD/MM/YYYY. |
fecha_inicial_vinculacion | — | Date in the format DD/MM/YYYY. |
fecha_final_vinculacion | — | Date in the format DD/MM/YYYY. |
codigo_unidad_academica | ✅ | Unique code of the academic unit. |
unidad_academica | ✅ | Name of the academic unit. |
codigo_subunidad_academica | — | It can be empty without penalty. |
subunidad_academica | — | It can be empty without penalty. |
Catalogue fields (
sexo, nivel_academico, etc.) don’t produce an error if
their value is not in the catalogue, but they are normalized to desconocido and
reported as a warning. Dates with “no information” aliases (n/a,
no aplica, etc.) are also normalized to desconocido.Response
boolean
true if the file has no errors. With errors, the response is 400 with
the same report.integer
Number of errors found in the file.
integer
Number of warnings.
integer
Number of duplicate records detected.
integer
Number of distinct values that were normalized (for example,
M → hombre).string | null
Quality report in PDF format encoded in Base64. It includes the summary
of errors, warnings and normalizations applied.
null if there is nothing
to report.string
Only with
200: result of saving the normalized file.string
Only on errors: reason for the rejection. If columns are missing or there are unnamed
columns, the response is
422 and details lists each problem. If the
file cannot be saved, the response is 500.{
"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."
}
{ "success": false, "msg": "Archivo requerido" }
{
"success": false,
"errors": 2,
"warnings": 1,
"duplicates": 1,
"normalized_unique_values_count": 0,
"pdf_base64": "JVBERi0xLjQKJ..."
}
{ "success": false, "msg": "El archivo cargado está vacío. Verifique que contenga información." }
{"msg": "Token inválido o expirado", "success": false}
{
"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..."
}