Nómina Electrónica DIAN
Emite Documentos Soporte de Pago de Nómina Electrónica (NominaIndividual, TipoXML=102) y Notas de Ajuste (NominaIndividualDeAjuste, TipoXML=103) según la Resolución 000013/2021 de la DIAN. Tu sistema envía los datos en un solo POST y la API genera el XML, calcula el CUNE (SHA-384), firma con XAdES-BES, zipea y transmite a la DIAN.
🔑 Empresa y ambiente por API Key: El endpoint determina la empresa y el ambiente (producción/habilitación) a partir del header X-Api-Key. NO envíes id_empresa ni ambiente en el body — son redundantes, se ignoran, y constituyen un riesgo de seguridad (un cliente con una API Key de prueba no debería poder emitir a nombre de otra empresa).
⚠️ Importante: La API NO requiere empleados, contratos ni periodos pre-existentes. Tu sistema de nómina envía los datos completos en un solo POST y la API se encarga de todo el proceso.
POST /v1/api/nomina/enviar
Genera el XML, calcula el CUNE (SHA-384), firma con XAdES-BES, zipea, transmite a la DIAN y persiste. Retorna CUNE, trackId, QR URL y respuesta DIAN.
Parámetros del Body
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| transmit | boolean | No | true=enviar a DIAN. false=solo generar XML/CUNE (default: true) |
| empleado | object | Sí | Datos del trabajador (ver sub-tabla empleado) |
| periodo | object | Sí | Periodo liquidado (ver sub-tabla periodo) |
| devengados | array | Sí | Líneas devengadas (ver sub-tabla devengados) |
| deducciones | array | No | Líneas deducidas (ver sub-tabla deducciones) |
| totales | object | No | Auto-calculados desde devengados/deducciones si se omiten |
| notas | array<string> | No | Notas libres (NIE031) |
| novedad | boolean | No | Marca novedad contractual (default: false) |
| cune_nov | string | No | CUNE del documento anterior (requerido si novedad=true) |
| prefijo | string | No | Prefijo del consecutivo (default: "NOM") |
| fecha_gen | string | No | YYYY-MM-DD (default: hoy) |
| hora_gen | string | No | HH:MM:SS-05:00 (default: hora actual Colombia) |
| periodo_nomina | string | No | 1=Ordinario, 2=Extraordinario (default: 1) |
| tipo_moneda | string | No | COP por defecto |
| trm | number | No | Tasa de cambio (solo si tipo_moneda != COP) |
| lugar_generacion | object | No | Override { pais, departamento, municipio, idioma } — usa empresa por defecto |
| empleador | object | No | Override del empleador — usa empresa por defecto |
| pago | object | No | Información del medio de pago |
| fechas_pagos | array<string> | No | Fechas en que se paga (YYYY-MM-DD) |
| redondeo | number | No | Centavos de redondeo |
| novedades | array | No | Novedades del periodo |
| sanciones | array | No | Sanciones disciplinarias |
empleado
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| tipo_documento | string | No | 13=CC, 22=CE, 41=Pasaporte (default: 13) |
| numero_documento | string | Sí | Número de documento del trabajador |
| primer_nombre | string | Sí | Primer nombre |
| otros_nombres | string | No | Segundos nombres (si aplica) |
| primer_apellido | string | Sí | Primer apellido |
| segundo_apellido | string | No | Segundo apellido |
| tipo_trabajador | string | No | DIAN 5.5.3: 01=Dependiente, 02=Independiente, 09=Aprendiz SENA (default: 01) |
| sub_tipo_trabajador | string | No | DIAN 5.5.4: 00=Sin subtipo, 01=Rural, 02=Urbano (default: 00) |
| alto_riesgo_pension | boolean | No | Decreto 2090/2003 |
| codigo_trabajador | string | No | Código interno del trabajador |
| tipo_contrato | string | No | DIAN 5.5.2: 1=Fijo, 2=Indefinido, 3=Obra, 4=Aprendizaje, 5=Prestación (default: 2) |
| lugar_trabajo_pais | string | No | ISO 3166-1 alfa-2 (default: CO) |
| lugar_trabajo_departamento | string | No | Código DANE departamento |
| lugar_trabajo_municipio | string | No | Código DANE municipio |
| lugar_trabajo_direccion | string | No | Dirección del lugar de trabajo |
periodo
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| fecha_ingreso | string | No | YYYY-MM-DD |
| fecha_retiro | string | No | YYYY-MM-DD (opcional) |
| fecha_liquidacion_inicio | string | Sí | YYYY-MM-DD |
| fecha_liquidacion_fin | string | Sí | YYYY-MM-DD |
| tiempo_laborado_dias | integer | Sí | Días trabajados (>= 1) |
devengados[]
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| seccion | string | Sí | BASICO, TRANSPORTE, HED, HEN, HRD, HRN, SND, VACACIONES, PRIMAS, CESANTIAS, INCAPACIDAD, LICENCIA, BONIFICACION, AUXILIO, OTRO |
| descripcion | string | No | Descripción libre |
| dias_trabajados | integer | No | Solo para BASICO |
| sueldo_trabajado | number | No | Solo para BASICO (si valor_total se omite) |
| auxilio_transporte | number | No | Solo para TRANSPORTE (si valor_total se omite) |
| valor_total | number | No | Valor total del devengado. Si se omite, se usa sueldo_trabajado o auxilio_transporte |
deducciones[]
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| seccion | string | Sí | SALUD, FONDO_PENSION, FONDO_SP, SINDICATO, SANCION, LIBRANZA, ANTICIPO, RETENCION, AFC, COOPERATIVA, EMBARGO |
| descripcion | string | No | Descripción libre |
| porcentaje | number | No | Porcentaje (ej 4 para salud) |
| base_calculo | number | No | Base de cálculo (IBC) |
| valor_total | number | Sí | Valor total de la deducción |
Ejemplo
{
"transmit": true,
"empleado": {
"tipo_documento": "13",
"numero_documento": "1234567890",
"primer_nombre": "JUAN",
"otros_nombres": "CARLOS",
"primer_apellido": "PEREZ",
"segundo_apellido": "GOMEZ",
"tipo_trabajador": "01",
"sub_tipo_trabajador": "00",
"alto_riesgo_pension": false,
"lugar_trabajo_pais": "CO",
"lugar_trabajo_departamento": "76",
"lugar_trabajo_municipio": "76001",
"lugar_trabajo_direccion": "Calle 1 #2-3",
"tipo_contrato": "2"
},
"periodo": {
"fecha_ingreso": "2026-01-15",
"fecha_liquidacion_inicio": "2026-07-01",
"fecha_liquidacion_fin": "2026-07-31",
"tiempo_laborado_dias": 30
},
"devengados": [
{
"seccion": "BASICO",
"dias_trabajados": 30,
"sueldo_trabajado": 1300000,
"valor_total": 1300000,
"descripcion": "Salario basico julio"
},
{
"seccion": "TRANSPORTE",
"auxilio_transporte": 162000,
"valor_total": 162000,
"descripcion": "Auxilio de transporte"
}
],
"deducciones": [
{
"seccion": "SALUD",
"porcentaje": 4,
"base_calculo": 1300000,
"valor_total": 52000,
"descripcion": "Aporte salud EPS"
},
{
"seccion": "FONDO_PENSION",
"porcentaje": 4,
"base_calculo": 1300000,
"valor_total": 52000,
"descripcion": "Aporte pension AFP"
}
],
"notas": [
"Liquidacion de julio 2026"
]
}Ejemplos de código
curl -X POST https://api.jcflow.com.co/v1/api/nomina/enviar \
-H "X-Api-Key: sk_test_tu_api_key_aqui" \
-H "Content-Type: application/json" \
-d '{"transmit":true,"empleado":{"tipo_documento":"13","numero_documento":"1234567890","primer_nombre":"JUAN","otros_nombres":"CARLOS","primer_apellido":"PEREZ","segundo_apellido":"GOMEZ","tipo_trabajador":"01","sub_tipo_trabajador":"00","alto_riesgo_pension":false,"lugar_trabajo_pais":"CO","lugar_trabajo_departamento":"76","lugar_trabajo_municipio":"76001","lugar_trabajo_direccion":"Calle 1 #2-3","tipo_contrato":"2"},"periodo":{"fecha_ingreso":"2026-01-15","fecha_liquidacion_inicio":"2026-07-01","fecha_liquidacion_fin":"2026-07-31","tiempo_laborado_dias":30},"devengados":[{"seccion":"BASICO","dias_trabajados":30,"sueldo_trabajado":1300000,"valor_total":1300000,"descripcion":"Salario basico julio"},{"seccion":"TRANSPORTE","auxilio_transporte":162000,"valor_total":162000,"descripcion":"Auxilio de transporte"}],"deducciones":[{"seccion":"SALUD","porcentaje":4,"base_calculo":1300000,"valor_total":52000,"descripcion":"Aporte salud EPS"},{"seccion":"FONDO_PENSION","porcentaje":4,"base_calculo":1300000,"valor_total":52000,"descripcion":"Aporte pension AFP"}],"notas":["Liquidacion de julio 2026"]}'Respuesta Exitosa
{
"success": true,
"message": "Nómina Electrónica procesada exitosamente",
"data": {
"id": 1,
"cune": "A1B2C3D4E5F6...",
"cune_scheme": "CUNE-SHA384",
"qr_url": "https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey=A1B2C3D4...",
"trackId": "uuid-track-id",
"transmission": {
"isValid": true,
"statusCode": "00",
"statusDescription": "Procesado Correctamente",
"errors": []
},
"totales": { "devengados": 1462000, "deducciones": 104000, "comprobante": 1358000 },
"ambiente": 2,
"xml": "<NominaIndividual>...</NominaIndividual>"
}
}POST /v1/api/nomina/ajuste
Crea una Nota de Ajuste (NominaIndividualDeAjuste, TipoXML=103) que REEMPLAZA o ELIMINA una nómina anterior referenciada por su CUNE. La API consulta la nómina original por CUNE (no por id) y genera el XML de ajuste.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| cune_referencia | string | Sí | CUNE de la nómina original a reemplazar/eliminar |
| empleado | object | Sí | Datos del trabajador |
| tipo_nota | integer | No | 1=Reemplazar, 2=Eliminar (DIAN 5.5.8, default: 1) |
| numero_referencia | string | No | Número de la nómina original (default: consecutivo almacenado) |
| fecha_referencia | string | No | YYYY-MM-DD (default: fecha_gen almacenada) |
| transmit | boolean | No | true=enviar a DIAN (default: true) |
| prefijo | string | No | Prefijo del consecutivo (default: "NOM") |
| fecha_gen | string | No | YYYY-MM-DD (default: hoy) |
| hora_gen | string | No | HH:MM:SS-05:00 (default: hora actual Colombia) |
| periodo_nomina | string | No | 1=Ordinario, 2=Extraordinario (default: usa el de la original) |
| lugar_generacion | object | No | Override del lugar de generación |
| empleador | object | No | Override del empleador |
| periodo | object | No | Periodo liquidado (default: usa el de la original) |
| devengados | array | No | Devengados corregidos (default: vacío) |
| deducciones | array | No | Deducciones corregidas (default: vacío) |
| totales | object | No | Totales (default: ceros) |
| notas | array<string> | No | Notas libres |
GET /v1/api/nomina/estado/:trackId
Consulta el estado actual de una nómina consultando GetStatus de la DIAN y actualiza el estado en la BD. El trackId va en la URL, no se envía id_empresa.
GET /v1/api/nomina/listar
Lista las nóminas de la empresa con paginación y filtros opcionales. La empresa se determina por la API Key.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| page | integer | No | Página (default 1) |
| limit | integer | No | Items por página (default 20) |
| tipo | string | No | INDIVIDUAL | AJUSTE |
| estado | string | No | enviada | aceptada | rechazada | error | borrador |
| fecha_desde | string | No | YYYY-MM-DD |
| fecha_hasta | string | No | YYYY-MM-DD |
GET /v1/api/nomina/:id
Retorna el detalle de una nómina específica, incluyendo sus devengados y deducciones.
GET /v1/api/nomina/:id/xml
Descarga el XML firmado de la nómina (text/xml).
GET /v1/api/nomina/:id/zip
Descarga el ZIP con el XML firmado (application/zip).
💡 Tip: En ambiente de pruebas (Habilitación) la DIAN acepta cualquier CUNE calculado correctamente. Puedes usar una API Key sk_test_ sin necesidad de un certificado digital real durante el desarrollo.