Saltar al contenido principal

📊 Configuración de Reportes

Autenticación Requerida

Incluir en todos los endpoints de esta sección el header: Authorization: Bearer {token}

Parámetro Multi-Tenant: client_uuid

Si operas como Casa de Software, puedes configurar encabezados y logos de reporte para tus clientes agregando ?client_uuid={{client_uuid}}.

GET {{url}}/company/customers
Authorization: Bearer {token}

📋 Encabezados y Pies de Página​

GET /settings/reports — Listar Encabezados de Reporte
GET {{url}}/settings/reports?client_uuid={{client_uuid}}
Authorization: Bearer {token}
Content-Type: application/json

Descripción: Lista, paginados (15 por página), los encabezados de reporte de la empresa. Si la empresa aún no tiene ninguno, el servidor crea uno vacío y lo devuelve, así que la lista nunca llega vacía.

Parámetros:

NombreUbicaciónRequeridoDescripción
idqueryNoFiltra por el id de un encabezado.
pagequeryNoNúmero de página (default: 1).
client_uuidqueryNoUUID del cliente (Casa de Software).
✅ Respuesta Exitosa (HTTP 200)
{
"dataRecords": {
"current_page": 1,
"data": [
{
"id": 7,
"company_id": 120,
"line1": "<p class=\"ql-align-center\">EMPRESA S.A.S </p><p class=\"ql-align-center\">N.I.T: 999.999.999-2 </p>",
"line2": "<p>Calle 00 # 00-00. Ciudad Ejemplo - Departamento CEL: 300-000-0000</p>",
"foot": "<p style=\"text-align: center;\">Email: contacto@empresa-ejemplo.com</p>",
"image": null
}
],
"per_page": 15,
"total": 1
},
"success": true
}

El paginador incluye además los campos estándar (from, to, last_page, links, etc.).

POST /crud?tbPrefix=T063 — Crear Encabezado de Reporte
POST {{url}}/crud?tbPrefix=T063&client_uuid={{client_uuid}}
Authorization: Bearer {token}
Content-Type: application/json

Descripción: Crea un nuevo encabezado y pie de página para los reportes y representaciones gráficas enviando el contenido formateado en HTML dentro del objeto records serializado en JSON.

💡 Guía para Desarrolladores — Formato HTML en records

Puedes enviar contenido con etiquetas HTML (negrita, alineación, saltos de línea) dentro de line1, line2 y foot.

import axios from 'axios';

const records = {
line1: '<p class="ql-align-center">EMPRESA S.A.S </p><p class="ql-align-center">N.I.T: 999.999.999-2 </p><p class="ql-align-center">IVA REGIMEN COMÚN</p>',
line2: '<p>Calle 00 # 00-00. Ciudad Ejemplo - Departamento CEL: 300-000-0000</p>',
foot: '<p style="text-align: center;">Email: contacto@empresa-ejemplo.com - Sitio web: https://empresa-ejemplo.com</p>'
};

const response = await axios.post(`${url}/crud?tbPrefix=T063`, {
records: JSON.stringify(records)
}, {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
}
});

Propiedades de records:

CampoTipoRequeridoDescripción
line1string (HTML)✅ SíLínea principal del encabezado (Razón social, NIT, régimen).
line2string (HTML)NoLínea secundaria (Dirección, ciudad, teléfonos).
footstring (HTML)NoPie de página del documento (Canales de contacto, web, notas).
✅ Respuesta Exitosa (HTTP 200)

Devuelve la fila creada en payload. Si envías records como arreglo de objetos, payload trae la lista de filas creadas.

{
"message": "Registro creado correctamente.",
"payload": {
"id": 7,
"company_id": 120,
"line1": "<p class=\"ql-align-center\">EMPRESA S.A.S</p><p class=\"ql-align-center\">N.I.T: 999.999.999-2</p>",
"line2": "<p>Calle 00 # 00-00. Ciudad Ejemplo - Departamento CEL: 300-000-0000</p>",
"foot": "<p style=\"text-align: center;\">Email: contacto@empresa-ejemplo.com</p>",
"image": null
},
"success": true
}
📏 Reglas del CRUD genérico (/crud)
  • company_id lo fija siempre el servidor con la empresa del token (o del client_uuid) y no se puede cambiar. created_at y deleted_at se ignoran. Si la tabla exige uuid, el servidor lo genera, y no se puede cambiar en un PUT.
  • records debe ser un objeto JSON o un arreglo de objetos. Con un arreglo, cada registro se valida por separado y la respuesta 400 trae el primer error. En un PUT con arreglo, cada registro debe incluir su llave primaria.
  • Solo se pueden escribir tablas propias de la empresa. Los catálogos y la configuración del sistema son de solo lectura.
  • Un registro de otra empresa responde igual que uno inexistente (404).
  • Un filtro where con condiciones OR no amplía el alcance: siempre se filtra por la empresa.
  • Las personas de recepción (tbPrefix=T005) no se escriben por el CRUD: se gestionan con /events/reception-people. Además, el módulo de recepción exige un plan de pago, también para leerlas: sin él, la respuesta es 403 con error_code: RECEPTION_NOT_IN_PLAN.
HTTPMensajeCausa
400No se ha especificado el prefijo de la tabla (tbPrefix).Falta tbPrefix.
400Debe enviar los registros (records).Falta records o viene vacío.
400Cada registro de records debe ser un objeto JSON.Un elemento de records no es un objeto.
400Cada registro debe incluir su id.PUT con arreglo sin la llave primaria en algún registro.
403La tabla '<tabla>' es de solo lectura: pertenece a la configuración del sistema y no se puede modificar por el CRUD.Escritura sobre un catálogo del sistema.
403La tabla '<tabla>' es de solo lectura por el CRUD: se gestiona con /api/ubl2.1/events/reception-people.Escritura sobre T005.
404El prefijo de tabla '<prefijo>' no existe.tbPrefix desconocido.
404La tabla '<tabla>' no está disponible en este sistema.El prefijo existe pero la tabla no está disponible.
404Recurso no encontrado.El registro no existe o es de otra empresa.
PUT /settings/reports/{id} — Actualizar Encabezado
PUT {{url}}/settings/reports/{id}?client_uuid={{client_uuid}}
Authorization: Bearer {token}
Content-Type: application/json

Parámetros:

NombreUbicaciónRequeridoDescripción
idpath✅ SíID del encabezado a actualizar.
client_uuidqueryNoUUID del cliente (Casa de Software).

Body (JSON): records como string JSON con los campos a actualizar (line1, line2, foot). Si incluyes imgdata para cambiar también el logo, debes enviar imgname (ver Actualizar Logo del Encabezado).

{
"records": "{\"line1\":\"<p>EMPRESA S.A.S</p>\",\"foot\":\"<p>Gracias por su compra</p>\"}"
}
✅ Respuesta Exitosa (HTTP 200)
{
"success": true
}
❌ Registro No Encontrado (HTTP 404)

El encabezado no existe o no pertenece a la empresa. Si falta records o no es un JSON válido, la respuesta es HTTP 422 (El campo records es requerido o El campo records debe ser un JSON válido).

{
"success": false,
"message": "No se encontró el registro con id 7 para la compañía: EMPRESA DE EJEMPLO SAS"
}
DELETE /settings/reports/{id} — Eliminar Encabezado
DELETE {{url}}/settings/reports/{id}?client_uuid={{client_uuid}}
Authorization: Bearer {token}
Content-Type: application/json

Parámetros:

NombreUbicaciónRequeridoDescripción
idpath✅ SíID del encabezado a eliminar.
client_uuidqueryNoUUID del cliente (Casa de Software).
✅ Respuesta Exitosa (HTTP 200)

La respuesta no incluye el campo success:

{
"message": "Configuración eliminada exitosamente"
}
❌ Registro No Encontrado (HTTP 404)
{
"success": false,
"message": "No se encontró el registro con id 7 para la compañía: EMPRESA DE EJEMPLO SAS"
}

🖼️ Logotipo de Reportes​

PUT /settings/reports/{id}/image — Actualizar Logo del Encabezado
PUT {{url}}/settings/reports/{id}/image?client_uuid={{client_uuid}}
Authorization: Bearer {token}
Content-Type: application/json

Descripción: Actualiza el logo asociado a un encabezado de reporte enviando la imagen codificada en Base64 dentro del objeto records.

💡 Guía para Desarrolladores — Carga de Imagen en Base64

Convierte la imagen (PNG/JPG) a Base64 con el prefijo Data URI (ej. data:image/png;base64,...) y envíala en imgdata, junto con imgname, el nombre del archivo original (ej. logo.png).

Propiedades de records:

CampoTipoRequeridoDescripción
imgdatastring✅ SíImagen como Data URI en Base64. Se toma lo que sigue a la primera coma.
imgnamestring✅ SíNombre del archivo original. Solo se usa su extensión: png, jpg, jpeg, gif, webp, svg, jfif, bmp o ico; cualquier otra se guarda como png. El nombre final del archivo lo asigna el servidor.
import fs from 'fs';
import axios from 'axios';

const imgBuffer = fs.readFileSync('logo.png');
const base64Img = 'data:image/png;base64,' + imgBuffer.toString('base64');

const response = await axios.put(`${url}/settings/reports/${id}/image`, {
records: JSON.stringify({ imgdata: base64Img, imgname: 'logo.png' })
}, {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
}
});
✅ Respuesta Exitosa (HTTP 200)
{
"success": true
}
❌ Errores
HTTPMensajeCausa
422El campo records es requeridoFalta records (formato estándar de validación, con errors).
422El campo records debe ser un JSON válidorecords no es un JSON válido.
404No se encontró el registro con id <id> para la compañía: <razón social>El encabezado no existe o no pertenece a la empresa.
404La propiedad IMGDATA no está definida.records no incluye imgdata.
404La cadena base64 de la imagen no es válida.imgdata viene vacío.
500Error interno del servidor. La propiedad RECORDS no está definida.records es un JSON vacío o nulo (por ejemplo null o []).
500Error interno del servidor. ...records no incluye imgname. Envíalo siempre junto con imgdata.
500Respuesta {"success": false, "error": "..."}Falló la actualización del registro.
{
"success": false,
"message": "No se encontró el registro con id 7 para la compañía: EMPRESA DE EJEMPLO SAS"
}

Las respuestas 500 incluyen además un reference para que soporte ubique el error.