API de Facturación Electrónica

Sistema Integrado de Facturación Electrónica Nacional (SIFEN)

Documentación Técnica v2.0

Introducción

Esta API permite emitir documentos electrónicos válidos ante la SET (Subsecretaría de Estado de Tributación) de Paraguay a través del sistema SIFEN.

Cumplimiento Legal

100% conforme a Manual Técnico SIFEN v150 de la DNIT

Integración Simple

API REST con JSON, autenticación JWT, Swagger interactivo en /api/docs

Seguridad

Firma digital con certificado PKCS#12, core SIFEN como paquete privado en GitHub

Tiempo Real

Emisión síncrona individual y por lotes de hasta 50 documentos

Trazabilidad Completa

Cada documento y evento guarda XML, respuesta SIFEN, estado y metadata en la base de datos

Eventos SIFEN

Cancelación e inutilización de documentos con registro completo del XML y la respuesta

¿Qué es SIFEN?

SIFEN (Sistema Integrado de Facturación Electrónica Nacional) es el sistema oficial de la SET para la emisión de documentos electrónicos en Paraguay.

Documentos Soportados

Tipo Código Descripción Uso
Factura Electrónica 1 Documento de venta Ventas de productos o servicios
Nota de Crédito 5 Anulación o devolución Devoluciones, descuentos
Nota de Débito 6 Ajuste adicional Intereses, gastos adicionales
Nota de Remisión 7 Traslado de mercadería Movimiento de stock

Componentes del Documento Electrónico

Estructura de un Documento Electrónico:
  • XML: Documento estructurado según especificaciones SIFEN v150
  • Firma Digital: Certificado digital válido (.pfx)
  • CDC: Código de Control del Documento (44 dígitos único)
  • QR: Código QR para validación pública
  • Protocolo: Número de autorización de SIFEN

Endpoints de la API

Base URL: https://tu-dominio.com/invoicing

GET/companies

Obtiene la lista de empresas configuradas para facturación.

Respuesta:

[
  {
    "id": "abc-123-def",
    "name": "Mi Empresa SRL",
    "ruc": "80012345-6",
    "business_name": "MI EMPRESA SOCIEDAD DE RESPONSABILIDAD LIMITADA"
  }
]

POST/emit/invoice

Emite una factura electrónica y la envía a SIFEN.

Body (JSON):

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "moneda": "PYG",
  "indicadorPresencia": 1,
  "cliente": {
    "ruc": "80009735-1",
    "razonSocial": "ANDE",
    "tipoContribuyente": 2,
    "tipoOperacion": 3,
    "direccion": "Av. España",
    "numeroCasa": "1234",
    "email": "facturacion@ande.gov.py"
  },
  "items": [
    {
      "codigo": "PROD-001",
      "descripcion": "Silla de Hierro",
      "cantidad": 2,
      "precioUnitario": 110000,
      "ivaTipo": 10,
      "unidadMedida": 77
    },
    {
      "codigo": "PROD-002",
      "descripcion": "Mesa de Madera",
      "cantidad": 1,
      "precioUnitario": 52500,
      "ivaTipo": 5,
      "unidadMedida": 77
    }
  ],
  "condicion": {
    "tipo": 1,
    "entregas": [
      {
        "tipo": 1,
        "monto": 272500,
        "moneda": "PYG"
      }
    ]
  }
}

Respuesta Exitosa:

{
  "ns2:rRetEnviDe": {
    "ns2:rProtDe": {
      "ns2:dEstRes": "Aprobado",
      "ns2:dProtAut": "12345678901234567890",
      "ns2:gResProc": {
        "ns2:dCodRes": "0260",
        "ns2:dMsgRes": "Aprobado"
      }
    }
  },
  "cdc": "01800123456001001000104720241201000000011234567890",
  "qr_url": "https://ekuatia.set.gov.py/consultas/qr?nVersion=150&Id=...",
  "xml": "...",
  "kude_pdf_base64": null,
  "documento_id": "f3a2b1c0-1234-5678-abcd-ef0123456789"
}
Campos Importantes de la Respuesta:
  • cdc: Código único del documento (guárdalo en tu base de datos)
  • qr_url: URL del QR para validación pública
  • xml: XML completo firmado (para imprimir o almacenar)
  • documento_id: UUID del registro en la base de datos local
  • dEstRes: Estado del documento ("Aprobado", "Rechazado")

POST/emit/credit-note

Emite una nota de crédito asociada a una factura.

Campos Adicionales Requeridos (además del body de factura):

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "motivo": 1,
  "documentoAsociado": {
    "tipo": 1,
    "cdc": "01800097351001001000000120260115191611126841"
  },
  "cliente": { ... },
  "items": [ ... ],
  "moneda": "PYG"
}

Motivos de Nota de Crédito:

Código Descripción
1 Devolución y anulación de factura
2 Devolución y anulación parcial
3 Descuento o bonificación
4 Ajuste de precio

POST/emit/debit-note

Emite una nota de débito para ajustes adicionales.

Motivos de Nota de Débito:

Código Descripción
1 Interés por mora
2 Ajuste de precio
3 Gastos adicionales

POST/emit/remission

Emite una nota de remisión para traslado de mercadería.

Importante: Las notas de remisión NO requieren precio ni IVA en los items, solo código, descripción y cantidad.

Ejemplo:

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "moneda": "PYG",
  "cliente": { ... },
  "items": [
    {
      "codigo": "PROD-001",
      "descripcion": "Silla de Oficina",
      "cantidad": 5,
      "unidadMedida": 77
    }
  ],
  "complementoRemision": {
    "motivo": 1,
    "responsableEmi": 1,
    "tipoAccion": 1,
    "fechaInicio": "2026-03-18",
    "fechaFin": "2026-03-18",
    "kilometros": 10,
    "precioFlete": 0
  }
}

POST/consult/ruc

Valida un RUC en el sistema SIFEN.

Body (JSON):

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "ruc": "80009735-1"
}

Respuesta:

{
  "ns2:rResEnviConsRUC": {
    "ns2:xContRUC": {
      "ns2:dRUC": "80009735-1",
      "ns2:dRazSoc": "ADMINISTRACION NACIONAL DE ELECTRICIDAD",
      "ns2:dNomFan": "ANDE",
      "ns2:dEstRUC": "Activo"
    }
  }
}

POST/consult/document

Consulta el estado de un documento por su CDC.

Body (JSON):

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "cdc": "01800097351001001000000120260115191611126841"
}

POST/emit/self-invoice

Emite una Autofactura Electrónica (iTiDE=4). Se usa cuando la empresa compra bienes o servicios a un proveedor que no es contribuyente (sin RUC). El campo cliente contiene los datos del vendedor/proveedor.

Body:

{
  "company_id": "...",
  "tipoTransaccion": 10,
  "cliente": {
    "razonSocial": "María González López",
    "documentoTipo": 1,
    "documentoNumero": "3456789",
    "tipoContribuyente": 1,
    "tipoOperacion": 2,
    "direccion": "Compañía San Miguel",
    "numeroCasa": "0"
  },
  "items": [...],
  "condicion": { "tipo": 1 },
  "moneda": "PYG"
}

POST/events/cancel

Cancela un documento electrónico emitido ante SIFEN. Registra el evento con XML firmado y respuesta SIFEN. Si el documento existe en la base de datos, su estado cambia a cancelado.

Body:

{
  "company_id": "...",
  "cdc": "01800123456001001000104720241201000000011234567890",
  "motivo": "Error en datos del cliente"
}

Respuesta:

{
  "rRetEnviEventoDe": { ... },
  "evento_id": "uuid-del-evento-registrado"
}

POST/events/inutilizacion

Inutiliza un rango de números de documentos ante SIFEN (Evento tipo 2, Manual 150). Usar cuando se emitieron documentos con error y no fueron enviados a SIFEN, o para invalidar una secuencia de numeración.

Body:

{
  "company_id": "...",
  "tipoDocumento": 1,
  "establecimiento": "001",
  "punto": "001",
  "nroDesde": 1,
  "nroHasta": 3,
  "motivo": "Documentos emitidos con error y no enviados a SIFEN",
  "serie": null,
  "timbradoNumero": null
}

Campos:

  • tipoDocumento — 1=Factura, 4=Autofactura, 5=NC, 6=ND, 7=NRE
  • nroDesde / nroHasta — rango de números a inutilizar
  • serie — serie de 3 caracteres (opcional)
  • timbradoNumero — usa el timbrado default si se omite

Respuesta:

{
  "rRetEnviEventoDe": { ... },
  "evento_id": "uuid-del-evento-registrado"
}

POST/kude

Genera el KuDE (Representación Gráfica del Documento Electrónico) en HTML a partir del XML firmado. El HTML puede renderizarse directamente en el navegador o convertirse a PDF. Incluye el logo de la empresa si está configurado en el admin.

Body:

{ "xml": "<?xml version=\"1.0\"...>" }

Respuesta:

HTML con el KuDE listo para imprimir (Content-Type: text/html).

Envío por Lotes (Batch)

SIFEN acepta hasta 50 documentos por lote. El flujo es asíncrono de 3 pasos. SIFEN tarda 5–10 minutos en procesar; no consultar el estado antes.

POST/batch/create

Crea un lote con hasta 50 documentos. Devuelve batch_id y estado pending.

{
  "company_id": "...",
  "documents": [ { ...doc1... }, { ...doc2... } ]
}

POST/batch/{batch_id}/process

Genera y firma todos los XMLs del lote, luego los envía a SIFEN. Estado pasa a sent y se obtiene el sifen_batch_number.

GET/batch/{batch_id}/status

Consulta el estado del lote en SIFEN y actualiza el estado de cada documento (approved / rejected).

GET/batch/{batch_id}

Detalle completo del lote con todos sus documentos.

GET/batch/list

Lista lotes con filtros opcionales: ?company_id=&status=&limit=

Consultas

Trazabilidad de Documentos

Cada operación queda registrada en la base de datos para auditoría y seguimiento completo.

DocumentoElectronico

Creado automáticamente en cada emisión individual (/emit/*). Guarda:

CampoDescripción
cdcCódigo de Control del Documento (44 chars)
numero_docNúmero formateado EST-PTO-NRODOC (ej: 001-001-0000001)
estadopendienteaprobado / rechazado / cancelado / error
xml_generadoXML sin firmar generado por sifen-core
xml_firmadoXML firmado con QR incrustado, listo para SIFEN
payload_entradaRequest JSON original recibido por la API
respuesta_sifenRespuesta completa devuelta por SIFEN (JSON)
error_mensajeDetalle del error si el estado es error
qr_urlURL del QR generado para el KuDE
metadataTimbrado, establecimiento, punto, ambiente (test/prod)

El registro se crea antes de enviar a SIFEN. Si falla en cualquier etapa (generación, firma, envío), queda persistido con estado=error y el mensaje de excepción.

EventoElectronico

Creado en cada cancelación o inutilización. Guarda XML firmado, respuesta SIFEN, metadata del evento y FK al documento cancelado (si aplica).

Visualización en Admin Django

Todos los registros son visibles y filtrables desde /admin con badges de colores por estado, XMLs en secciones colapsables y links entre eventos y documentos.

Generación de XML SIFEN

La API genera automáticamente el XML según las especificaciones SIFEN v150.

Proceso de Generación

1. Validación

Valida todos los datos del request contra las reglas de SIFEN

2. Generación XML

Crea el XML estructurado con todos los campos requeridos

3. Firma Digital

Firma el XML con el certificado digital de la empresa

4. QR Code

Agrega el código QR al XML firmado

5. Envío a SIFEN

Envía el documento a SIFEN para validación

6. Respuesta

Retorna CDC, QR URL y XML completo

Ejemplo de XML Generado

<?xml version="1.0" encoding="UTF-8"?>
<rDE xmlns="http://ekuatia.set.gov.py/sifen/xsd">
  <DE Id="01800123456001001000104720241201000000011234567890">
    <dVerFor>150</dVerFor>
    <gOpeDE>
      <iTipEmi>1</iTipEmi>
      <dDesTipEmi>Normal</dDesTipEmi>
      <dCodSeg>669880626</dCodSeg>
    </gOpeDE>
    <gTimb>
      <iTiDE>1</iTiDE>
      <dDesTiDE>Factura electrónica</dDesTiDE>
      <dNumTim>03970287</dNumTim>
      <dEst>001</dEst>
      <dPunExp>001</dPunExp>
      <dNumDoc>0000001</dNumDoc>
      <dFeIniT>2024-01-01</dFeIniT>
    </gTimb>
    <gDatGralOpe>
      <dFeEmiDE>2024-12-01T10:30:00</dFeEmiDE>
    </gDatGralOpe>
    <gEmis>
      <dRucEm>80012345-6</dRucEm>
      <dRazSocEm>MI EMPRESA SRL</dRazSocEm>
      ...
    </gEmis>
    <gDatRec>
      <dRucRec>80009735-1</dRucRec>
      <dRazSocRec>ANDE</dRazSocRec>
      ...
    </gDatRec>
    <gDtipDE>
      <gCamFE>
        <gCamItem>
          <dCodInt>PROD-001</dCodInt>
          <dDesProSer>Silla de Oficina</dDesProSer>
          <dCantProSer>1.0</dCantProSer>
          <dPUniProSer>150000</dPUniProSer>
          ...
        </gCamItem>
      </gCamFE>
    </gDtipDE>
  </DE>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    ...firma digital...
  </Signature>
  <dCarQR>https://ekuatia.set.gov.py/consultas/qr?...</dCarQR>
</rDE>

Campos Automáticos

La API genera automáticamente los siguientes campos:

Campo Descripción
CDC Código de Control del Documento (44 dígitos único)
Código de Seguridad Número aleatorio de 9 dígitos
Número de Documento Secuencial automático si no se especifica
Fecha de Emisión Fecha/hora actual si no se especifica
Totales Cálculo automático de subtotales, IVA y total

Ejemplos de Uso

Python

import requests

url = "https://api.ejemplo.com/api/invoicing/emit/invoice"
headers = {
    "Authorization": "Bearer <tu_token_jwt>",
    "Content-Type": "application/json"
}

factura = {
    "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
    "moneda": "PYG",
    "indicadorPresencia": 1,
    "cliente": {
        "ruc": "80009735-1",
        "razonSocial": "ANDE",
        "tipoContribuyente": 2,
        "tipoOperacion": 3,
        "direccion": "Av. España",
        "numeroCasa": "1234",
        "email": "facturacion@ande.gov.py"
    },
    "items": [{
        "codigo": "PROD-001",
        "descripcion": "Silla de Hierro",
        "cantidad": 2,
        "precioUnitario": 110000,
        "unidadMedida": 77,
        "ivaTipo": 10
    }],
    "condicion": {
        "tipo": 1,
        "entregas": [{"tipo": 1, "monto": 220000, "moneda": "PYG"}]
    }
}

response = requests.post(url, headers=headers, json=factura)
result = response.json()

print(f"CDC: {result['cdc']}")
print(f"QR: {result['qr_url']}")
print(f"documento_id: {result['documento_id']}")

cURL

curl -X POST "https://api.ejemplo.com/api/invoicing/emit/invoice" \
  -H "Authorization: Bearer <tu_token_jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
    "moneda": "PYG",
    "indicadorPresencia": 1,
    "cliente": {
      "ruc": "80009735-1",
      "razonSocial": "ANDE",
      "tipoContribuyente": 2,
      "tipoOperacion": 3,
      "direccion": "Av. España",
      "numeroCasa": "1234",
      "email": "facturacion@ande.gov.py"
    },
    "items": [{
      "codigo": "PROD-001",
      "descripcion": "Silla de Hierro",
      "cantidad": 2,
      "precioUnitario": 110000,
      "unidadMedida": 77,
      "ivaTipo": 10
    }],
    "condicion": {
      "tipo": 1,
      "entregas": [{"tipo": 1, "monto": 220000, "moneda": "PYG"}]
    }
  }'

Facturación a Entidades del Estado (B2G)

Cuando el receptor de una factura es un Organismo o Entidad del Estado (OEE) — municipalidades, gobernaciones, ministerios, entes autárquicos, etc. — SIFEN exige que el tipo de operación sea B2G (tipoOperacion: 3). Opcionalmente, si la venta está asociada a un contrato de la DNCP (Dirección Nacional de Contrataciones Públicas), se pueden informar los datos de ese contrato en el campo dncp del documento y de cada ítem.

Regla SIFEN obligatoria (error 1332): Si el RUC del receptor corresponde a un OEE registrado en Marangatu, el campo tipoOperacion debe ser 3. SIFEN rechazará el documento con error 1332 si se usa B2B (1) o B2C (2) para un receptor que es entidad del Estado.

¿Cuándo informar el objeto dncp?

El objeto dncp es opcional desde NT-026. Solo se debe incluir cuando la venta está respaldada por un número de contratación emitido por la DNCP (licitación, contratación directa, etc.). Si no existe contrato DNCP, simplemente se omite el campo y SIFEN acepta el documento igual.

Dónde aplica: El objeto dncp está disponible únicamente en POST /emit/invoice (Factura Electrónica). Las notas de crédito, débito y remisiones no tienen grupo de Compras Públicas.

Esquema dncp — nivel documento (grupo gCompPub, E020–E025)

Campo Tipo Long. Requerido Descripción
modalidad string 2 Requerido* Modalidad de contratación emitida por la DNCP (ej: "11")
entidad string 5 Requerido* Código de entidad emitido por la DNCP, relleno con ceros (ej: "00123")
año string 2 Requerido* Año del código de contratación DNCP (ej: "24" para 2024)
secuencia string 7 Requerido* Secuencia emitida por la DNCP, relleno con ceros (ej: "0000045")
fecha date 10 Requerido* Fecha de emisión del código de contratación DNCP en formato AAAA-MM-DD. Debe ser anterior a la fecha de la factura.

* Requeridos solo si se incluye el objeto dncp. Si no hay contrato DNCP, omitir el objeto completo.

Esquema dncp — nivel ítem (campos E704/E705)

Dentro de cada ítem se pueden informar los códigos DNCP de catálogo de bienes y servicios. Son opcionales incluso cuando se informa el grupo a nivel documento.

Campo Tipo Long. Requerido Descripción
codigoNivelGeneral string 8 Requerido* Código DNCP nivel general (E704). Se rellena con ceros a la izquierda hasta 8 caracteres (ej: "00000001")
codigoNivelEspecifico string 3–4 Opcional Código DNCP nivel específico (E705). Requerido por SIFEN si se informó codigoNivelGeneral (ej: "001")

* Requerido si se quiere informar DNCP por ítem. Si se omite el objeto dncp en el ítem, ese ítem no lleva códigos DNCP en el XML.

Ejemplo completo — Factura B2G con contrato DNCP

Factura a una municipalidad con un contrato de la DNCP, dos ítems con distintas tasas de IVA y sus respectivos códigos DNCP.

POST/emit/invoice

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "moneda": "PYG",
  "indicadorPresencia": 1,
  "tipoTransaccion": 1,

  "cliente": {
    "ruc": "11111111-1",
    "razonSocial": "Municipalidad de Asunción",
    "tipoContribuyente": 2,
    "tipoOperacion": 3,
    "direccion": "Chile esq. Palma",
    "numeroCasa": "S/N",
    "departamento": 11,
    "distrito": 143,
    "ciudad": 1532,
    "email": "compras@asuncion.gov.py"
  },

  "dncp": {
    "modalidad": "11",
    "entidad": "00123",
    "año": "24",
    "secuencia": "0000045",
    "fecha": "2024-03-15"
  },

  "items": [
    {
      "codigo": "SRV-001",
      "descripcion": "Servicio de limpieza",
      "cantidad": 10,
      "precioUnitario": 150000,
      "ivaTipo": 10,
      "unidadMedida": 77,
      "dncp": {
        "codigoNivelGeneral": "00000001",
        "codigoNivelEspecifico": "001"
      }
    },
    {
      "codigo": "MAT-005",
      "descripcion": "Materiales de construcción",
      "cantidad": 5,
      "precioUnitario": 200000,
      "ivaTipo": 5,
      "unidadMedida": 77,
      "dncp": {
        "codigoNivelGeneral": "00000002",
        "codigoNivelEspecifico": "003"
      }
    }
  ],

  "condicion": {
    "tipo": 1,
    "entregas": [
      { "tipo": 1, "monto": 2500000, "moneda": "PYG" }
    ]
  }
}

Ejemplo mínimo — B2G sin contrato DNCP

Si la venta al Estado no está asociada a un número de contrato DNCP (prestaciones de servicios directos, compras menores, etc.), simplemente se omite el campo dncp. SIFEN acepta el documento igual desde NT-026.

POST/emit/invoice

{
  "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
  "moneda": "PYG",
  "indicadorPresencia": 1,

  "cliente": {
    "ruc": "11111111-1",
    "razonSocial": "Municipalidad de Asunción",
    "tipoContribuyente": 2,
    "tipoOperacion": 3,
    "direccion": "Chile esq. Palma",
    "numeroCasa": "S/N"
  },

  "items": [
    {
      "codigo": "SRV-001",
      "descripcion": "Servicio de consultoría",
      "cantidad": 1,
      "precioUnitario": 500000,
      "ivaTipo": 10,
      "unidadMedida": 77
    }
  ],

  "condicion": { "tipo": 1 }
}

Ejemplo Python — B2G con DNCP

import requests

url = "https://api.ejemplo.com/api/invoicing/emit/invoice"
headers = {
    "Authorization": "Bearer <tu_token_jwt>",
    "Content-Type": "application/json"
}

payload = {
    "company_id": "a7e9f084-d15c-4a8f-8b3d-0a7d5f24734a",
    "moneda": "PYG",
    "indicadorPresencia": 1,
    "cliente": {
        "ruc": "11111111-1",
        "razonSocial": "Municipalidad de Asunción",
        "tipoContribuyente": 2,
        "tipoOperacion": 3,           # B2G obligatorio para OEE
        "direccion": "Chile esq. Palma",
        "numeroCasa": "S/N",
        "email": "compras@asuncion.gov.py"
    },
    "dncp": {                         # Omitir si no hay contrato DNCP
        "modalidad": "11",
        "entidad": "00123",
        "año": "24",
        "secuencia": "0000045",
        "fecha": "2024-03-15"
    },
    "items": [
        {
            "codigo": "SRV-001",
            "descripcion": "Servicio de limpieza",
            "cantidad": 10,
            "precioUnitario": 150000,
            "ivaTipo": 10,
            "unidadMedida": 77,
            "dncp": {                 # Omitir si no hay código DNCP por ítem
                "codigoNivelGeneral": "00000001",
                "codigoNivelEspecifico": "001"
            }
        }
    ],
    "condicion": {"tipo": 1}
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

print(f"CDC: {result['cdc']}")
print(f"Estado: {result.get('ns2:rRetEnviDe', {}).get('ns2:rProtDe', {}).get('ns2:dEstRes')}")

XML generado para B2G con DNCP

La API inyecta automáticamente los nodos gCompPub (nivel documento) y dDncpG/dDncpE (nivel ítem) en el XML antes de firmarlo:

<gDtipDE>
  <gCamFE>
    <iIndPres>1</iIndPres>
    <dDesIndPres>Operación presencial</dDesIndPres>

    <!-- Grupo Compras Públicas (E020-E025) —— generado si se envía "dncp" -->
    <gCompPub>
      <dModCont>11</dModCont>
      <dEntCont>00123</dEntCont>
      <dAnoCont>24</dAnoCont>
      <dSecCont>0000045</dSecCont>
      <dFeCodCont>2024-03-15</dFeCodCont>
    </gCompPub>
  </gCamFE>

  <gCamItem>
    <dCodInt>SRV-001</dCodInt>
    <!-- Códigos DNCP por ítem (E704/E705) —— antes de dDesProSer -->
    <dDncpG>00000001</dDncpG>
    <dDncpE>001</dDncpE>
    <dDesProSer>Servicio de limpieza</dDesProSer>
    <cUniMed>77</cUniMed>
    <dDesUniMed>UNI</dDesUniMed>
    <dCantProSer>10.0</dCantProSer>
    ...
  </gCamItem>
</gDtipDE>

Resumen de reglas

Situación tipoOperacion Campo dncp doc. Campo dncp ítem
Venta a empresa privada 1 (B2B) No aplica No aplica
Venta a consumidor final 2 (B2C) No aplica No aplica
Venta al Estado sin contrato DNCP 3 (B2G) Obligatorio Omitir Omitir
Venta al Estado con contrato DNCP 3 (B2G) Obligatorio Incluir Incluir si se conoce el código
Cómo obtener los códigos DNCP: Los datos de modalidad, entidad, año, secuencia y fecha los provee la entidad compradora junto con la orden de compra. También están disponibles en el portal dncp.gov.py bajo el número de contratación. Los códigos por ítem (codigoNivelGeneral / codigoNivelEspecifico) corresponden al catálogo de bienes y servicios de la DNCP.

Códigos de Error

Errores Comunes

Error Causa Solución
Empresa no tiene certificado activo Certificado digital no configurado Cargar certificado .pfx válido
RUC inválido Formato incorrecto de RUC Usar formato: 80012345-6 (con DV)
Timbrado vencido Timbrado fuera de vigencia Renovar timbrado en la SET
Items sin precio Falta precioUnitario o ivaTipo Agregar precio e IVA a todos los items
Documento rechazado por SIFEN Datos inválidos según SIFEN Revisar mensaje de error de SIFEN

Códigos de Respuesta SIFEN

Código Estado Descripción
0260 Aprobado Documento aprobado correctamente
0261 Pendiente En proceso de validación
0300-0399 Rechazado Error en datos del documento

Esquema de Datos Completo

Cliente (ClientSchema)

Campo Tipo Requerido Descripción
ruc string Requerido RUC con DV (ej: 80012345-6)
razonSocial string Requerido Razón social o nombre completo
direccion string Requerido Dirección del cliente
numeroCasa string Requerido Número de casa
tipoContribuyente int Requerido 1: Físico, 2: Jurídico
tipoOperacion int Requerido 1: B2B, 2: B2C, 3: B2G
email string Requerido Email del cliente
documentoTipo int Requerido Tipo de documento (si no tiene RUC)
documentoNumero string Requerido Número de documento (si no tiene RUC)

Item (ItemSchema)

Campo Tipo Requerido Descripción
codigo string Requerido Código del producto/servicio
descripcion string Requerido Descripción del item
cantidad float Requerido Cantidad
precioUnitario float Requerido* Precio unitario
ivaTipo int Requerido* 10, 5, o 0 (exento)
unidadMedida int Opcional Código de unidad (default: 77)
descuento float Opcional Descuento unitario
dncp objeto Opcional Códigos DNCP del ítem (E704/E705). Solo para operaciones B2G (tipoOperacion: 3). Ver sección B2G.

* No requerido para notas de remisión

Tipos de IVA

Código Descripción Uso
10 IVA 10% Productos/servicios gravados al 10%
5 IVA 5% Productos/servicios gravados al 5%
0 Exento Productos/servicios exentos de IVA

Envío y Reenvío de KuDE por Email

La API puede enviar automáticamente el KuDE al destinatario del documento cuando SIFEN lo aprueba, adjuntando el PDF y el XML firmado. También es posible reenviar esos archivos en cualquier momento usando el endpoint de reenvío.

Adjuntos del correo: cada correo incluye siempre dos archivos adjuntos:
  • kude_001-001-0000001.pdf — Representación gráfica del documento (KuDE)
  • 001-001-0000001.xml — XML firmado y sellado por SIFEN

Envío automático

Al emitir cualquier documento con /emit/*, si SIFEN devuelve código 0260 (Aprobado) y la empresa tiene configurado el envío de email (send_kude_on_approval = true), el correo se envía automáticamente al cliente.email del payload de emisión. No se requiere ninguna acción adicional.

POST/email/resend

Reenvía el KuDE (PDF) y el XML firmado de un documento ya emitido al destinatario indicado.

Body (JSON):

{
  "documento_id": "f3a2b1c0-1234-5678-abcd-ef0123456789",
  "recipient_email": "otro@ejemplo.com",
  "recipient_name": "Nombre Opcional",
  "cc": ["contabilidad@empresa.com", "gerencia@empresa.com"]
}

Parámetros:

Campo Tipo Requerido Descripción
documento_id UUID string Requerido UUID del DocumentoElectronico. Se obtiene en el campo documento_id de la respuesta de emisión.
recipient_email string Opcional Email de destino principal (TO). Si se omite, se usa el cliente.email guardado en el payload original del documento.
recipient_name string Opcional Nombre del destinatario para el saludo del correo. Si se omite, se usa el cliente.razonSocial del payload original.
cc array de strings Opcional Lista de correos en copia (CC). Pueden ser uno o varios. Todos reciben el mismo PDF y XML adjuntos.

Respuesta exitosa:

// Sin CC
{ "ok": true, "sent_to": "otro@ejemplo.com" }

// Con CC
{
  "ok": true,
  "sent_to": "otro@ejemplo.com",
  "cc": ["contabilidad@empresa.com", "gerencia@empresa.com"]
}

Errores posibles:

HTTPMensajeCausa
404 Documento no encontrado El documento_id no existe en la base de datos
400 El documento no tiene XML firmado almacenado El documento está en estado error o no llegó a firmarse
400 No hay destinatario. Provee recipient_email en el body. El payload original no tenía cliente.email y no se proveyó recipient_email
500 Error al enviar: ... Fallo SMTP (credenciales, servidor, etc.)

Ejemplo Python:

import requests

headers = {
    "Authorization": "Bearer <tu_token_jwt>",
    "Content-Type": "application/json"
}

# Caso 1: usar el email guardado del documento original
response = requests.post(
    "https://api.ejemplo.com/api/invoicing/email/resend",
    headers=headers,
    json={"documento_id": "f3a2b1c0-1234-5678-abcd-ef0123456789"}
)

# Caso 2: enviar a un email distinto con copias
response = requests.post(
    "https://api.ejemplo.com/api/invoicing/email/resend",
    headers=headers,
    json={
        "documento_id": "f3a2b1c0-1234-5678-abcd-ef0123456789",
        "recipient_email": "cliente@empresa.com",
        "recipient_name": "Cliente S.A.",
        "cc": ["contabilidad@empresa.com", "gerencia@empresa.com"]
    }
)

print(response.json())
# {"ok": true, "sent_to": "cliente@empresa.com", "cc": ["contabilidad@empresa.com", "gerencia@empresa.com"]}

Ejemplo cURL:

curl -X POST "https://api.ejemplo.com/api/invoicing/email/resend" \
  -H "Authorization: Bearer <tu_token_jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "documento_id": "f3a2b1c0-1234-5678-abcd-ef0123456789",
    "recipient_email": "cliente@empresa.com",
    "recipient_name": "Cliente S.A.",
    "cc": ["contabilidad@empresa.com", "gerencia@empresa.com"]
  }'
Prerequisito: La empresa debe tener configurado el email en el admin (CompanyEmailConfig). Si send_kude_on_approval está desactivado, el reenvío manual sí funciona igual — ese flag solo controla el envío automático al aprobar.