FINORA ERP · Referencia
API de nómina: informe técnico
La API de integración de nómina permite que sistemas externos trabajen las nóminas de FINORA ERP: el sistema de Recursos Humanos da de alta trabajadores y cambia salarios, el control de asistencia carga las horas extra y las inasistencias, y un portal consulta el resultado de cada quincena. Llega con el módulo Nómina (diccionario 1.2.8).
La API no reemplaza al motor de nómina: los montos los calcula FINORA. El sistema externo envía hechos (cédulas, horas, días, fechas) y recibe resultados.
Cómo es la API
Sección titulada «Cómo es la API»Cada operación es un proceso de iDempiere que se ejecuta por REST:
POST https://erp.tuempresa.com/api/v1/processes/<slug>Authorization: Bearer <token>Content-Type: application/jsonEl cuerpo lleva los parámetros del proceso. El contenido de negocio viaja como una cadena JSON dentro del
parámetro FVE_NOM_Payload. Es el mismo contrato que usan la app del chofer de FINORA Transporte y FINORA Merchant.
| Tipo | Parámetros |
|---|---|
| Lectura | Solo FVE_NOM_Payload, con la consulta ({} si no hay filtros) |
| Escritura | FVE_NOM_IdemKey (clave de idempotencia, hasta 120 caracteres), FVE_NOM_PayloadSha256 (sha256 del contenido) y FVE_NOM_Payload |
Autenticación
Sección titulada «Autenticación»ERP=https://erp.tuempresa.com/api/v1curl -s -X POST "$ERP/auth/tokens" -H 'Content-Type: application/json' -d '{ "userName": "integracion-rrhh", "password": "***", "parameters": {"clientId": 1000000, "roleId": 1000100, "organizationId": 0}}'La respuesta trae token. Guárdalo en TOKEN y úsalo en cada llamada. Ante un HTTP 401, pide otro token una vez y
repite la llamada; el primer 401 puede llegar como página HTML, así que no lo leas como JSON.
- Usa un usuario de integración propio de la empresa, con un rol de nómina. Nunca uses un usuario de una persona.
- El alcance es el del rol: la empresa del token y sus organizaciones. Una organización fuera del rol responde
FUERA_DE_ALCANCE; en las consultas, sus trabajadores y corridas no aparecen. - La organización del token puede ser 0. Al crear una corrida o un trabajador sin indicar
organizacion, FINORA usa la de la nómina; si la nómina es compartida, la única organización con Datos laborales de la organización. Si hay más de una, la pide.
JSON canónico y hash
Sección titulada «JSON canónico y hash»El contenido viaja en JSON canónico, para que el sistema externo y FINORA calculen el mismo hash:
- Claves ordenadas por punto de código Unicode y sin espacios.
- Cadenas con el escape mínimo; los acentos van tal cual, en UTF-8.
- Solo números enteros. Los montos, las cantidades y las tasas viajan como texto decimal (
"180000.00","2.5"; también se acepta la coma,"2,5", nunca separador de miles). Las fechas, como"AAAA-MM-DD". - El hash es el
sha256de los bytes UTF-8 del texto canónico, en hexadecimal minúscula.
FINORA vuelve a canonizar el contenido y compara el hash; si no coincide, responde VALIDACION. Los campos desconocidos
se ignoran, pero cuentan para el hash.
Una función de ayuda en Bash, con jq y shasum (en producción usa tu lenguaje; Java, Kotlin y Python producen los
mismos bytes):
nom() { # nom <slug> '<json>' [clave] con clave es una escritura local canon hash body canon=$(printf '%s' "$2" | jq -cS .) if [ -n "$3" ]; then hash=$(printf '%s' "$canon" | shasum -a 256 | cut -d' ' -f1) body=$(jq -n --arg k "$3" --arg h "$hash" --arg p "$canon" \ '{FVE_NOM_IdemKey:$k, FVE_NOM_PayloadSha256:$h, FVE_NOM_Payload:$p}') else body=$(jq -n --arg p "$canon" '{FVE_NOM_Payload:$p}') fi curl -s -X POST "$ERP/processes/$1" -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' -d "$body"}La respuesta: el sobre
Sección titulada «La respuesta: el sobre»La respuesta HTTP es 200 siempre que el proceso se ejecutó, también cuando FINORA rechaza la operación. Lee
isError y el sobre, que es una cadena JSON en summary:
{"advertencias":[],"clave":"corrida-Q-2026-10-01","codigo":"OK","resultado":{"corrida":1000123,"documento":"90010","estado":"DR"},"v":1,"yaExistia":false}{"codigo":"ESTADO_INVALIDO","detalle":"la corrida 90010 está en estado CO: las novedades solo se registran en una corrida en borrador","estado":409,"v":1}Cada elemento de una lista viaja en una entrada de logs[], también como JSON. Su campo tipo dice qué es: concepto,
trabajador, salario, vacaciones, corrida, novedad o linea.
Códigos
Sección titulada «Códigos»codigo | estado | Qué significa y qué hacer |
|---|---|---|
OK | 200 | Lee resultado, advertencias y logs[] |
VALIDACION | 400 | El contenido no es válido. Corrígelo y envíalo con otra clave: el rechazo queda guardado con la clave usada |
FUERA_DE_ALCANCE | 403 | La organización no es del rol |
NO_ENCONTRADO | 404 | No existe la cédula, la nómina, el departamento, el cargo, el período o la corrida. No queda guardado: puedes repetir con la misma clave cuando exista |
CONFLICTO | 409 | La clave ya se usó con otro contenido, o el dato choca con uno existente: otra relación laboral abierta, otra corrida ordinaria del período, otro salario el mismo día |
ESTADO_INVALIDO | 409 | La corrida no está en borrador |
REINTENTAR | 503 | Falla pasajera: repite con la misma clave y el mismo contenido |
ERROR_INTERNO | 500 | Repórtalo a soporte con la clave |
Advertencias
Sección titulada «Advertencias»| Advertencia | Dónde | Significado |
|---|---|---|
RECALCULAR | Novedades | La corrida estaba calculada: hay que calcularla de nuevo antes de completarla |
LINEAS_RECHAZADAS | Novedades | Alguna línea del lote se rechazó; las demás se registraron |
PRE_NOMINA | Resultado | La corrida todavía no está completada |
SIN_CALCULAR | Resultado | La corrida no tiene cálculo |
ANULADA | Resultado | La corrida está anulada |
SIN_DATOS_LABORALES | Crear corrida | La organización no tiene Datos laborales de la organización; el cálculo fallará |
TERCERO_EXISTENTE | Alta | Se reutilizó un tercero que ya tenía ese código |
BANCO_NO_REGISTRADO | Alta | La empresa no tiene registrado el banco de la cuenta |
OTRA_CUENTA_ACTIVA | Alta | El tercero ya tenía otra cuenta: el archivo del banco paga la más antigua |
RETROACTIVO | Salario | La fecha cae en un período ya completado: la diferencia va en una corrida complementaria |
Idempotencia
Sección titulada «Idempotencia»Cada escritura lleva una clave que el sistema externo genera y guarda antes de enviar. FINORA la bloquea mientras procesa y guarda, en la misma transacción que los datos, la llamada con su respuesta:
- Misma clave y mismo contenido: FINORA devuelve la respuesta guardada con
yaExistia: true, también las líneas de un lote. Un reintento tras un corte de red es siempre seguro. - Misma clave y otro contenido:
CONFLICTO. - Clave nueva: se procesa.
Además hay reglas de negocio que impiden duplicados aunque cambie la clave: una sola corrida ordinaria no anulada por
nómina y período, una sola relación laboral abierta por cédula, un salario por trabajador y fecha, y la referencia
de cada novedad, única dentro de la corrida.
Una buena clave es <sistema>-<operación>-<id propio>, por ejemplo asistencia-2026-10-01-lote-3. Las llamadas
quedan en la tabla Llamadas de la API de nómina (FVE_NOM_ApiCall).
Límites
Sección titulada «Límites»- Cada contenido admite como máximo 3.999 caracteres. Un lote de novedades ocupa unos 110 caracteres por línea con fecha y referencia: unas 35 líneas por llamada.
- Hasta 200 líneas por lote y 200 elementos por página en las consultas.
- No hay límite de llamadas por minuto, pero no envíes en paralelo escrituras sobre la misma corrida: FINORA las procesa una a una.
Los procesos
Sección titulada «Los procesos»Los ejemplos usan la función nom y datos ficticios.
Catálogo de conceptos: fve_nom_conceptos
Sección titulada «Catálogo de conceptos: fve_nom_conceptos»nom fve_nom_conceptos '{"soloNovedades": true}'Filtros: fase (EARNING, NON_SALARY, PAYOUT, DEDUCTION, EMPLOYER, LEDGER) y soloNovedades. Cada concepto trae su
código, nombre, fase, las bases que alimenta y la norma. Los que se cargan como novedad traen novedad con la unidad
(HORAS o DIAS), si es entera, el tipo de corrida y si requiere fecha de inicio.
Trabajadores: fve_nom_trabajadores
Sección titulada «Trabajadores: fve_nom_trabajadores»nom fve_nom_trabajadores '{"nomina": "Q", "estado": "ACTIVO", "pagina": 1, "porPagina": 50}'Filtros: nomina, departamento (sus códigos), estado (ACTIVO, EGRESADO, TODOS), cedula, fecha (por defecto hoy),
pagina y porPagina. Cada trabajador trae cédula, nombres, nómina, departamento, cargo, ingreso, egreso, tipo de
contrato, tipo de salario, jornada, el salario normal vigente a la fecha y la cuenta bancaria enmascarada (código
del banco y últimos 4 dígitos).
Ficha del trabajador: fve_nom_trabajador
Sección titulada «Ficha del trabajador: fve_nom_trabajador»nom fve_nom_trabajador '{"cedula": "V-00000001"}'La ficha de la relación laboral más reciente de la cédula, con el saldo de prestaciones (garantía e intereses), los días
de vacaciones pendientes y el porcentaje de la AR-I del año. En logs[], el historial de salario y las vacaciones por
año de servicio. La cédula se acepta como V00000001, V-00.000.001 o solo los dígitos.
Alta de trabajador: fve_nom_trabajador_alta
Sección titulada «Alta de trabajador: fve_nom_trabajador_alta»nom fve_nom_trabajador_alta '{"cedula": "V-00000001", "primerNombre": "TRABAJADOR", "primerApellido": "DE EJEMPLO", "fechaIngreso": "2026-10-01", "nomina": "Q", "departamento": "ADM", "cargo": "ANA", "salarioMensual": "180000.00", "jornada": "DIURNA", "tipoContrato": "INDETERMINADO", "tipoSalario": "FIJO", "cuentaBancaria": "00000000000000000001"}' alta-V00000001Crea en una sola transacción el tercero, la relación laboral, los datos legales, el salario desde el ingreso y, si se
envía, la cuenta de nómina. Si algo falla, no queda nada a medias. Aplica las mismas reglas que las ventanas: nombres
sin comas (el archivo del BANAVIH separa por comas), valores válidos de las listas, cuenta de 20 dígitos y salario no
negativo. salarioMensual es el salario normal (LOTTT art. 104), no el básico.
Una cédula con una relación laboral abierta responde CONFLICTO. La AR-I y el egreso no están en la API: la AR-I la
revisa el contador y el egreso decide la liquidación, así que se registran en las ventanas o por /models.
Cambio de salario: fve_nom_salario
Sección titulada «Cambio de salario: fve_nom_salario»nom fve_nom_salario '{"cedula": "V-00000001", "desde": "2026-11-01", "salarioMensual": "200000.00"}' salario-V00000001-20261101Solo agrega una fila al historial de salario. El mismo monto el mismo día responde sinCambios: true; otro monto el
mismo día responde CONFLICTO. Una fecha en un período ya completado se acepta con la advertencia RETROACTIVO.
Corridas: fve_nom_corridas
Sección titulada «Corridas: fve_nom_corridas»nom fve_nom_corridas '{"nomina": "Q", "estado": "DR"}'Filtros: nomina, periodo, desde y hasta (fecha de pago), estado (DR borrador, CO completada, VO anulada…) y
tipo. Cada corrida trae su número, estado, período, fecha de pago, si está calculada, cuántos trabajadores tiene y el
neto.
Crear corrida: fve_nom_corrida_crear
Sección titulada «Crear corrida: fve_nom_corrida_crear»nom fve_nom_corrida_crear '{"nomina": "Q", "fecha": "2026-10-01", "tipo": "ORDINARIA"}' corrida-Q-2026-10-01Crea la corrida en borrador. El período se indica con periodo (su número interno) o con fecha (cualquier día del
período). Tipos: ORDINARIA, VACACIONES, UTILIDADES, PRESTACIONES y LIQUIDACION. Opcionales: fechaPago (por defecto, el
fin del período), fechaContable, nombre y organizacion. Guarda el corrida que devuelve: es el número que usan los
demás procesos.
Novedades: fve_nom_novedades
Sección titulada «Novedades: fve_nom_novedades»nom fve_nom_novedades '{"corrida": 1000123, "lineas": [ {"cedula": "V-00000001", "concepto": "ASI_HE_DIURNA", "cantidad": "6", "fecha": "2026-10-09", "referencia": "MARC-1"}, {"cedula": "V-00000001", "concepto": "ASI_BONO_NOCTURNO", "cantidad": "3", "fecha": "2026-10-10", "referencia": "MARC-2"}, {"cedula": "V-00000001", "concepto": "ASI_FERIADO_TRAB", "cantidad": "1", "fecha": "2026-10-12", "referencia": "MARC-3"}]}' asistencia-2026-10-01-1Solo se aceptan las novedades que el cálculo lee, por cantidad:
| Concepto | Unidad | Corrida |
|---|---|---|
ASI_HE_DIURNA, ASI_HE_NOCTURNA | horas, hasta 2 decimales | ORDINARIA |
ASI_BONO_NOCTURNO | horas | ORDINARIA |
ASI_FERIADO_TRAB, ASI_DESCANSO_TRAB | días enteros | ORDINARIA |
DED_INASISTENCIA | días, hasta 2 decimales | ORDINARIA |
ASI_VACACIONES | días hábiles enteros, con inicio (primer día de vacaciones) | VACACIONES |
Un concepto de monto (préstamo, embargo, comisión) y el campo monto se rechazan: el motor no los lee y quedarían
guardados sin efecto. La fecha debe estar dentro del período (por defecto, su último día) y el trabajador debe ser de
la nómina de la corrida y estar activo en el período.
Cada línea se responde en logs[] con su estado: REGISTRADA, EXISTENTE (la misma referencia con los mismos datos
ya estaba), ANULADA o RECHAZADA con el motivo. Una línea rechazada no detiene las demás; con "atomico": true se
registran todas o ninguna. Para corregir una novedad, anúlala con {"anular": true, "referencia": "MARC-1"} y vuelve a
enviarla con otra referencia.
Resultado de la corrida: fve_nom_corrida_resultado
Sección titulada «Resultado de la corrida: fve_nom_corrida_resultado»nom fve_nom_corrida_resultado '{"corrida": 1000123}'En resultado, los totales de la corrida: asignaciones salariales y no salariales, pagos de prestaciones, deducciones,
neto y aportes patronales. En logs[], por trabajador, una entrada con sus totales seguida de sus líneas por sección
(asignaciones, no salariales, pagos de prestaciones, deducciones, aportes patronales y movimientos de libro). Son los
mismos números del recibo, del asiento contable y del archivo del banco: nada se recalcula. Con cedula, un solo
trabajador.
El ciclo de la corrida
Sección titulada «El ciclo de la corrida»Calcular, completar, anular, los recibos y el archivo del banco son los procesos de nómina de siempre. Responden texto en
summary (no el sobre) e isError. Se ejecutan sobre la corrida:
curl -s -X POST "$ERP/processes/fve_payrollcalculate" -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' -d '{"record-id": 1000123, "model-name": "hr_process"}'| Paso | Proceso | Nota |
|---|---|---|
| Calcular | fve_payrollcalculate | Se puede repetir: reemplaza lo calculado y nunca toca las novedades |
| Completar | fve_payrollcomplete | Genera el asiento contable y alimenta los libros de ISLR, prestaciones y vacaciones |
| Anular | fve_payrollvoid | Reversa el asiento; una corrida completada nunca se borra |
| Recibos | fve_payrollpayslip | {"HR_Process_ID": 1000123, "report-type": "PDF"}; el PDF llega en reportFile (base64) |
| Archivo del banco | fve_payrollbankfile | Solo corrida completada; el total es igual al neto; el archivo llega en exportFile |
Completar exige el cálculo vigente
Sección titulada «Completar exige el cálculo vigente»Al calcular, FINORA guarda una huella (hash) de la corrida: los movimientos calculados y las novedades. Al completar
la vuelve a calcular. Si una novedad se registró, cambió, desactivó o borró después del cálculo, por la API, por
/models o en la ventana, completar responde:
Los movimientos o las novedades cambiaron después del cálculo: ejecute Calcular de nuevo (payroll-processes §9)Así nunca se paga una nómina que no incluye las últimas novedades. La API además avisa RECALCULAR en cuanto registras
la novedad.
El flujo completo
Sección titulada «El flujo completo»- Crear la corrida con
fve_nom_corrida_creary guardar su número. - Cargar las novedades con
fve_nom_novedades, en lotes de unas 35 líneas, cada lote con su clave. - Calcular con
fve_payrollcalculate. - Revisar con
fve_nom_corrida_resultado(pre-nómina, advertenciaPRE_NOMINA). - Si llega una novedad tarde: cargarla, calcular de nuevo y revisar.
- Completar con
fve_payrollcomplete; después, las novedades de esa corrida respondenESTADO_INVALIDO. - Recibos con
fve_payrollpayslipy archivo del banco confve_payrollbankfile.
Con el caso de prueba de la documentación de nómina (salario de 180.000,00, 6 horas extra diurnas, 3 horas nocturnas y un feriado trabajado en la primera quincena de octubre de 2026), el neto es 71.300,39 en el resultado, en el recibo y en el archivo del banco.
Permisos y seguridad
Sección titulada «Permisos y seguridad»- Los nueve procesos se dan a los roles que ya ejecutan Calcular nómina, y a los roles con el módulo Nómina en Configurar tenant. Quita el acceso a los roles que no deben ver salarios.
- Los salarios son datos sensibles: no des estos procesos al rol de consulta. Las cuentas bancarias siempre se devuelven enmascaradas.
- Cada escritura queda registrada con su clave, usuario, contenido y respuesta. Una novedad con
referenciala guarda en su descripción comoref:<referencia>.
Ver también
Sección titulada «Ver también»- Integrar la nómina por API: el tutorial para el integrador del control de asistencia.
- Recursos Humanos y Nómina: las tareas de nómina en las ventanas.
- 10. La API REST de iDempiere.