Manual de integración

Cómo enviar tu JSON a la API

Tu sistema (ERP, punto de venta, aplicación en Delphi o cualquier otro) arma un JSON con los datos de la venta y lo envía por HTTP POST. La API hace todo lo demás con SIFEN. Este documento es el contrato completo: con esto alcanza para integrar.

00 Qué hace esta API

El sistema emisor solo arma el JSON de la venta y lo manda. La API se encarga de todo lo de SIFEN:

  • genera el CDC (los 44 dígitos de control)
  • genera el XML rDE y lo firma digitalmente con el certificado de la empresa
  • calcula el código QR (dCarQR / cHashQR)
  • arma el lote, lo envía a SIFEN y hace el seguimiento del estado
  • guarda el XML firmado y el JSON original
  • genera el KUDE (la representación gráfica en PDF para el cliente)

El sistema emisor no necesita certificado, CSC, librerías de XML o firma, ni conocer los WebServices de SIFEN.

Tipos de comprobante que emite la API — campo tipoDocumento

1Factura Electrónica — el caso normal
4Autofactura Electrónica — compra a un no contribuyente / extranjero; el emisor se factura a sí mismo
5Nota de Crédito Electrónica
6Nota de Débito Electrónica
7Nota de Remisión Electrónica — traslado de mercadería; sin valores ni IVA

Por defecto solo están habilitados 1, 5 y 6. Para emitir Autofactura (4) o Nota de Remisión (7) el proveedor debe habilitarlas para tu empresa; si mandás un tipo no habilitado la API responde 422 (ver N13).

Inicio rápido

  1. Pedí al proveedor de la API tu {BASE_URL} y un token (o el alta de tu IP para la ruta legacy).
  2. Armá el JSON de la venta según el contrato y hacé POST {BASE_URL}/api/v1/documentos con la cabecera Authorization: Bearer <TOKEN>.
  3. Guardá el cdc y el nro_lote de la respuesta. El comprobante ya es válido; el KUDE se puede imprimir aunque el estado sea Pendiente.

01 La URL de la API puede variar

Esta API funciona bajo cualquier URL: dominio propio, subdominio, IP con puerto o incluso una subcarpeta. Ejemplos válidos de base:

https://facturacion.miempresa.com
https://erp.miempresa.com.py:8443
http://192.168.10.20:8080
https://apps.miempresa.com/facturacion

En este manual esa parte se escribe como {BASE_URL} (sin barra final). El proveedor de la API te entrega el valor real al dar de alta la empresa. Todos los endpoints se arman igual: {BASE_URL} + ruta.

API nueva — recomendada para sistemas nuevos

MétodoRutaPara
POST/api/v1/documentosemitir
GET/api/v1/documentos/{cdc}ver estado
GET/api/v1/documentos/{cdc}/xmlXML firmado
GET/api/v1/documentos/{cdc}/jsonJSON original
GET/api/v1/documentos/{cdc}/qrURL del QR
GET/api/v1/documentos/{cdc}/kude?format=pdfKUDE PDF
GET/api/v1/documentos/{cdc}/kude?format=htmlKUDE HTML
POST/api/v1/documentos/{cdc}/reenviarreintentar el envío (ver)
POST/api/v1/documentos/{cdc}/anularanular
POST/api/v1/documentos/{cdc}/consultarforzar consulta a SIFEN
GET/api/v1/lotes/{nroLote}estado del lote
GET/api/v1/saluddiagnóstico (sin token)

API legacy — compatible con el sistema PHP anterior

El cliente Delphi existente sigue funcionando cambiando solo el host de la URL. La ruta y el formato de respuesta no cambian.

MétodoRutaPara
POST/api-py/firmar-enviar.phpemitir
POST/api-py/anular.phpanular
GET/api-py/consultar.php?lote={n}estado del lote
GET/api-py/get_xml.php?cdc={cdc}XML firmado
GET/api-py/get_json.php?cdc={cdc}JSON original
GET/api-py/get_qr.php?cdc={cdc}URL del QR
GET/api-py/kude.php?cdc={cdc}&format=pdfKUDE
GET/api-py/diagnostico.phpdiagnóstico

Sobre los enlaces que devuelve la API

La respuesta de emitir incluye un bloque links con URLs absolutas ya armadas (xml, json, kude, qr). Usalas tal cual: la API las construye a partir de la misma URL con la que llegó tu request, así que siempre apuntan al lugar correcto.

El qr_url del comprobante apunta a SIFEN (ekuatia.set.gov.py), no a esta API. Nunca lo reconstruyas por tu cuenta: usalo tal como viene.

02 Autenticación

API nueva — token Bearer

Cabecera Authorization: Bearer <TOKEN>. El token se genera una vez en el panel de administración: {BASE_URL}/admin/tokens (o {BASE_URL}/e/{tu-slug}/admin/tokens si tu proveedor activó el modo multiempresa, ver §15) → «Nuevo token» → se copia (no se vuelve a mostrar). Un token por sistema consumidor.

API legacy (/api-py/*)

Sin token de sesión. El acceso se restringe opcionalmente por lista de IPs y/o una cabecera X-Legacy-Token, ambas configuradas del lado del servidor. Si tu IP está permitida, no mandás nada.

El ambiente (test / producción) lo decide la API por su propia configuración. El sistema emisor no lo envía.

03 Reglas que debe cumplir el sistema emisor

Leer antes de integrar. Cada regla tiene un identificador (N0N14) que se referencia en el resto del manual.

N0 recordID

Cada envío lleva recordID (string, ≤ 20) con el identificador de la empresa emisora (ej. 5F-7111E5F9). Lo entrega el proveedor de la API. No cambia entre comprobantes y no aparece en el XML ni en el KUDE: solo sirve para validar y enrutar la empresa. Si no coincide → HTTP 403.

N1 Numeración

El sistema emisor es el dueño del número. Enviar siempre establecimiento y punto como strings de 3 dígitos ("001") y numero como string de 7 dígitos con ceros a la izquierda ("0000123"). No repetir un número ya emitido: si se repite → HTTP 409 (y en la ruta legacy, un error en el cuerpo). Ver Idempotencia.

N2 Fecha

fecha siempre en formato YYYY-MM-DDTHH:MM:SS (hora de Paraguay). La fecha es parte del CDC: un error acá invalida el documento.

N3 CDC

Normalmente no se envía (la API lo genera). Enviarlo solo si el sistema externo ya lo calculó (facturación offline o contingencia). Si se envía, manda sobre establecimiento, punto, numero, tipoEmision y codigoSeguridadAleatorio (esos campos se toman del CDC).

N4 Importes

Números JSON, sin separador de miles, con punto decimal.

Correcto
45000  ·  45000.00
Incorrecto
"45.000"  ·  "45,000"  ·  "45000,00"

N5 IVA por ítem — lo recalcula la API

Mandá por ítem solo totalItem, ivaTipo, iva (tasa 0/5/10) y ivaBase (proporción gravada, 100 = todo). La API calcula basGravIVA y liqIVAItem con la fórmula exacta de SIFEN e ignora lo que mandes en esos dos campos (si no coinciden con SIFEN, el DE se rechaza — código 1911).

dBasGravIVA = 100 * totalItem * ivaBase / (10000 + ivaBase * tasa)
dLiqIVAItem = dBasGravIVA * tasa / 100

ejemplo:  totalItem 45000 al 10%  →  basGravIVA 40909.09090909
                                     liqIVAItem  4090.90909091
Exento (ivaTipo 3) / Exonerado (ivaTipo 2):  basGravIVA = 0 ; liqIVAItem = 0

Si no mandás unidadMedida, se asume 77 (UNI). cUniMed / dDesUniMed son obligatorios en el XML.

N6 Totales

La API recalcula a partir de los ítems: dSubExe, dSubExo, dSub5, dSub10, dTotOpe, dTotGralOpe, dIVA5, dIVA10, dTotIVA, dBaseGrav5, dBaseGrav10, dTBasGraIVA.

El sistema emisor igual debe mandar el bloque totales con estos 8 campos (van tal cual al XML). Si no hay descuentos ni anticipos, todos en 0: dTotDesc, dTotDescGlotem, dTotAntItem, dTotAnt, dPorcDescTotal, dDescTotal, dAnticipo, dRedon.

N7 Pagos

Si condicion.tipo = 1 (contado): la suma de condicion.contado[].monto debe coincidir con el total del comprobante.

N8 Cliente sin RUC

contribuyente = false + TipoDocumentoIdentidad + NumeroDocumentoIdentidad. Ojo: esas dos claves llevan mayúsculas iniciales. Consumidor final sin datos: TipoDocumentoIdentidad = 5 (Innominado); la API pone dNumIDRec = 00000000 y dNomRec = "Sin Nombre".

N9 Nota de crédito / débito

tipoDocumento = 5 (crédito) o 6 (débito), con notaCreditoDebito.motivo (1–8, default 1) y documentoAsociado (formato 1 = electrónico + cdc de la factura original de 44 dígitos). En NC/ND no se envía el bloque factura.

N10 Reintentos ante timeout de red

Si la API no responde: no generes un número nuevo. Reintentá el mismo JSON con el mismo número. Si además mandás la cabecera Idempotency-Key, el reintento devuelve el documento ya emitido (HTTP 200) en vez de un 409.

N11 Autofactura Electrónica (tipoDocumento = 4)

Se usa cuando el emisor compra a alguien que no puede emitir factura (no contribuyente, microproductor, extranjero). El emisor se factura a sí mismo.

  • cliente (receptor) debe ser el propio emisor: contribuyente = true y ruc = el RUC del emisor (número-DV). Si no coincide → 422.
  • No se envía el bloque factura.
  • Sí se envía condicion (contado/crédito) e items con IVA, como en una factura normal.
  • Bloque vendedor obligatorio (datos de a quién se le compró).
  • documentoAsociado con formato 3 (constancia electrónica de no ser contribuyente / de microproductor) es lo habitual, pero no se exige.

N12 Nota de Remisión Electrónica (tipoDocumento = 7)

Ampara el traslado de mercadería. No traslada valores: no lleva precios, ni IVA, ni totales.

  • No se envía: factura, condicion, totales, tipoImpuesto, condicionAnticipo.
  • items[] solo describen la mercadería: codigo, descripcion, cantidad, unidadMedida, pais/paisDescripcion (ncm/observacion opcionales). No mandar precioUnitario / ivaTipo / iva / totalItem.
  • Bloques remision y transporte obligatorios.
  • cliente (a quién se entrega) sí se envía, igual que siempre.
  • moneda se sigue enviando (formalidad; no afecta el traslado).

N13 Tipos de documento habilitados por empresa

Cada empresa tiene una lista de tipos permitidos. El default es 1, 5 y 6. Autofactura (4) y Nota de Remisión (7) ya están implementadas, pero el proveedor debe agregarlas a tu empresa (una vez probadas en test). Si enviás un tipoDocumento fuera de tu lista → HTTP 422 con el error en el campo tipoDocumento («El tipo de documento N no esta habilitado para esta empresa.»).

N14 Venta al Estado / B2G (cliente.tipoOperacion = 3)

Se usa cuando el receptor es una entidad de gobierno (ej. un ministerio).

  • Bloque compraPublica obligatorio: modalidad, entidad, anio, secuencia y fechaCodigo (el código de contratación que emite la DNCP para ese proceso de compra). Sin este bloque → HTTP 422.
  • fechaCodigo no puede ser posterior a fecha (fecha de emisión del comprobante) → HTTP 422 si lo es.
  • Para cualquier otro tipoOperacion (1, 2 o 4) no se envía compraPublica; si se envía igual, la API lo ignora.
  • Por ahora solo implementado para Factura Electrónica (tipoDocumento 1); ver ejemplo 5.8.

04 Contrato JSON — campo por campo

Leyenda: R requerido   O opcional   C condicional.

Raíz

CampoTipo / valores
RrecordIDstring ≤ 20 — identificador de la empresa (N0)
Ocdcstring 44 dígitos (N3)
CtipoDocumentoint 1 | 4 | 5 | 6 | 7 (default 1) — ver N11–N13
RtipoEmisionint 1 Normal, 2 Contingencia
Restablecimientostring(3)
Rpuntostring(3)
Rnumerostring(7)
OcodigoSeguridadAleatoriostring(9) — si falta, la API genera uno
RfechaYYYY-MM-DDTHH:MM:SS
RmonedaPYG (también USD, BRL, ARS, EUR)
CtipoImpuestoint 1–5 (1 = IVA) — no enviar si tipoDocumento = 7
OtipoTransaccionint 1–13
CcondicionAnticipoint 1 | 2 — no enviar si tipoDocumento = 7
Oobservacionstring → dInfoEmi
Odescripcionstring → dInfoFisc
OtimbradoNumero / timbradoFechanormalmente lo pone la API

factura — obligatorio solo si tipoDocumento = 1

CampoTipo / valores
Rpresenciaint 1–6
OfechaEnviofecha

vendedor — obligatorio solo si tipoDocumento = 4 (Autofactura, N11)

CampoTipo / valores
Rnaturalezaint 1 No contribuyente, 2 Extranjero
RtipoDocumentoIdentidadint 1–4
RnumeroDocumentoIdentidadstring ≤ 20
Rnombrestring ≤ 60
Rdireccionstring ≤ 255
RnumeroCasastring | int
Rdepartamento / ciudadint + su …Descripcion
Odistritoint + distritoDescripcion
OlugarTransaccionobjeto con direccion, departamento, ciudad… — si se omite, se asume la dirección del vendedor

cliente

CampoTipo / valores
Rcontribuyentebool
RtipoOperacionint 1 B2B, 2 B2C, 3 B2G, 4 B2F
Rpais / paisDescripcionPRY / PARAGUAY
RrazonSocialstring
Cruc1234567-8 — si contribuyente = true
CtipoContribuyenteint 1 | 2 — si contribuyente = true
CTipoDocumentoIdentidadint 1–6 — si contribuyente = false (N8)
CNumeroDocumentoIdentidadstring — si contribuyente = false (N8)
OnombreFantasiastring
Odireccion / numeroCasastring
Odepartamento / distrito / ciudadint + su …Descripcion
Otelefono / celular / email / codigostring (codigo = código externo del ERP)

compraPublica — obligatorio solo si cliente.tipoOperacion = 3 (B2G, N14)

CampoTipo / valores
Rmodalidadstring(2) — código de modalidad de la DNCP
Rentidadstring(5) — código de entidad de la DNCP
Raniostring(2) — año del código de contratación
Rsecuenciastring(7) — secuencia del código de contratación
RfechaCodigoYYYY-MM-DD — fecha de emisión del código de contratación (no posterior a fecha)

Estos 5 datos los emite la Dirección Nacional de Contrataciones Públicas (DNCP) para el proceso de compra; sin ellos SIFEN rechaza la Factura a un organismo del Estado (código 1400 del Manual Técnico SIFEN). No enviar este bloque si tipoOperacion es 1, 2 o 4.

condicion

CampoTipo / valores
Rtipoint 1 Contado, 2 Crédito
Ccontado[]si tipo = 1 — lista de pagos: tipo (1–16), monto, moneda, infoTarjeta [O], infoCheque [O]
Ccreditosi tipo = 2iCondCred (1 Plazo, 2 Cuota), dDCondCred, dPlazoCre, dCuotas, dMonEnt, cuotas[]

Si tipo = 2 sin bloque credito, la API inyecta { iCondCred: 1, dDCondCred: "Plazo", dPlazoCre: "30 dias" }. En infoTarjeta: si la procesadora no tiene RUC, "ruc": "-"; si tipo = 99, agregar tipoDescripcion.

items[] — al menos 1

CampoTipo / valores
Rcodigo / descripcionstring
Rcantidadnumérico
CprecioUnitarionumérico — no enviar si tipoDocumento = 7
Rpais / paisDescripcionPRY / PARAGUAY
OunidadMedida / unidadMedidaDescint (77 = UNI) / string
Oncm / partidaArancelaria / observacionstring
Cdescuento / descuentoPorcentaje / descuentoGlobalnumérico
Canticipo / anticipoGlobalnumérico
CtotalItemnumérico (= precioUnitario × cantidad − dtos)
CivaTipoint 1 Gravado, 2 Exonerado, 3 Exento, 4 Grav. parcial
CivaBaseint 0–100 (proporción gravada; 100 = todo)
Civaint 0 | 5 | 10 (tasa)
ObasGravIVA / liqIVAItemla API los recalcula (N5); lo que mandes se ignora

C = obligatorio salvo en la Nota de Remisión (tipoDocumento 7), que describe la mercadería sin precio ni IVA: ahí no enviar precioUnitario / descuento* / anticipo* / totalItem / ivaTipo / ivaBase / iva. Para el resto de los tipos son obligatorios.

totales, notaCreditoDebito

CampoTipo / valores
Ctotaleslos 8 campos de N6, todos (0 si no hay) — no se envía si tipoDocumento = 7
OnotaCreditoDebito.motivoint 1–8 (default 1) — si tipoDocumento 5 o 6

documentoAsociado — obligatorio si tipoDocumento 5 o 6 (N9); opcional para el resto

Referencia libre a otro comprobante. El campo formato decide qué otros campos van:

CampoTipo / valores
Rformatoint 1 Electrónico, 2 Impreso, 3 Constancia Electrónica
Ccdc44 dígitos — si formato = 1
Ctimbrado / establecimiento / punto / numero / fechastring(8) / (3) / (3) / (7) / YYYY-MM-DD — si formato = 2
CtipoDocumentoImpresoint 1 Factura, 2 NC, 3 ND, 4 Nota de remisión, 5 Comprobante de retención — si formato = 2
CtipoConstanciaint 1 No ser contribuyente, 2 Microproductores — si formato = 3 (típico en Autofactura)
CnumeroConstancia / numeroControlstring(11) / string(8) — si tipoConstancia = 2

remision — obligatorio solo si tipoDocumento = 7 (N12)

CampoTipo / valores
Rmotivoint 1–14 | 99 — motivo del traslado
Rresponsableint 1–5 — responsable de emitir la NRE
OkmRecorridonumérico
OfechaEmisionFacturaYYYY-MM-DD — factura que respalda el traslado

transporte — obligatorio solo si tipoDocumento = 7 (N12)

CampoTipo / valores
RtipoTransporteint 1 Propio, 2 Tercero
Rmodalidadint 1 Terrestre, 2 Fluvial, 3 Aéreo, 4 Multimodal
RresponsableFleteint 1–5
RfechaInicioTraslado / fechaFinTrasladoYYYY-MM-DD (fin ≥ inicio)
RlocalSalida / localEntregaobjeto: direccion, numeroCasa, departamento, ciudad [R] · distrito, telefono [O]
Rvehiculoobjeto: tipo ≤10 (ej. «CAMION»), marca ≤10, tipoIdentificacion (1 Nro. identificación, 2 Nro. matrícula/chapa) + numeroIdentificacion o numeroMatricula según corresponda; numeroVuelo si modalidad = 3
Otransportistaobjeto: naturaleza (1 Contribuyente, 2 No contrib.), nombre, ruc o tipoDocumentoIdentidad/numeroDocumentoIdentidad según naturaleza, choferDocumentoIdentidad [R], choferNombre [R], direccionChofer [O]

05 Ejemplos

Factura electrónica al contado — el caso más común

POST {BASE_URL}/api/v1/documentos
// Headers: Content-Type: application/json · Accept: application/json
//          Authorization: Bearer <TOKEN> · Idempotency-Key: FE-001-001-0000001
{
  "recordID": "5F-7111E5F9",
  "tipoDocumento": 1,
  "tipoEmision": 1,
  "establecimiento": "001",
  "punto": "001",
  "numero": "0000001",
  "fecha": "2026-05-27T10:15:00",
  "moneda": "PYG",
  "tipoImpuesto": 1,
  "tipoTransaccion": 1,
  "condicionAnticipo": 1,
  "descripcion": "Venta mostrador",
  "factura": { "presencia": 1 },
  "cliente": {
    "contribuyente": false,
    "tipoOperacion": 2,
    "pais": "PRY",
    "paisDescripcion": "PARAGUAY",
    "razonSocial": "DUARTE GONZALEZ, DERLIS ARIEL",
    "TipoDocumentoIdentidad": 1,
    "NumeroDocumentoIdentidad": "4829212"
  },
  "condicion": {
    "tipo": 1,
    "contado": [ { "tipo": 1, "monto": 45000, "moneda": "PYG" } ]
  },
  "items": [
    {
      "codigo": "1",
      "descripcion": "CARNAZA DE PRIMERA",
      "unidadMedida": 77, "unidadMedidaDesc": "UNI",
      "cantidad": 1, "precioUnitario": 45000,
      "pais": "PRY", "paisDescripcion": "PARAGUAY",
      "descuento": 0, "descuentoPorcentaje": 0, "descuentoGlobal": 0,
      "anticipo": 0, "anticipoGlobal": 0,
      "totalItem": 45000,
      "ivaTipo": 1, "ivaBase": 100, "iva": 10,
      "basGravIVA": 40910, "liqIVAItem": 4090
    }
  ],
  "totales": {
    "dTotDesc": 0, "dTotDescGlotem": 0, "dTotAntItem": 0, "dTotAnt": 0,
    "dPorcDescTotal": 0, "dDescTotal": 0, "dAnticipo": 0, "dRedon": 0
  }
}
Respuesta — HTTP 201
{
  "success": true,
  "cdc": "01042214610001001000000112026052717799105109",
  "record_id": "5F-7111E5F9",
  "numero_completo": "001-001-0000001",
  "estado": "enviado",
  "estado_sifen": "Pendiente",
  "mensaje_sifen": "Lote recibido por SIFEN. Pendiente de consulta automatica.",
  "nro_lote": "1234567890",
  "qr_url": "https://ekuatia.set.gov.py/consultas/qr?nVersion=150&Id=...",
  "links": {
    "xml":  "{BASE_URL}/api/v1/documentos/01042214.../xml",
    "json": "{BASE_URL}/api/v1/documentos/01042214.../json",
    "kude": "{BASE_URL}/api/v1/documentos/01042214.../kude?format=pdf",
    "qr":   "{BASE_URL}/api/v1/documentos/01042214.../qr"
  },
  "documento": { /* recurso completo */ }
}

Equivalente por la ruta legacy — siempre HTTP 200

POST {BASE_URL}/api-py/firmar-enviar.php — mismo JSON, sin el bloque links
{
  "respuesta_sifen": { "dCodRes": "0300", "dMsgRes": "Lote recibido con exito",
                       "dProtConsLote": "1234567890" },
  "cdc": "01042214610001001000000112026052717799105109",
  "nro_lote": "1234567890",
  "estado_sifen": "Pendiente",
  "mensaje_sifen": "Lote recibido por SIFEN. Pendiente de consulta automatica."
}

Cliente contribuyente (con RUC) y varios ítems, uno exento

Fragmentos
"cliente": {
  "contribuyente": true,
  "tipoOperacion": 1,
  "pais": "PRY", "paisDescripcion": "PARAGUAY",
  "ruc": "80012345-6",
  "tipoContribuyente": 2,
  "razonSocial": "CONSTRUCTORA DEL ESTE S.A.",
  "nombreFantasia": "CONESA",
  "email": "compras@conesa.com.py", "codigo": "CLI-000123"
},
"items": [
  { "codigo": "CEM-50", "descripcion": "CEMENTO PORTLAND 50KG",
    "cantidad": 10, "precioUnitario": 55000, "totalItem": 550000,
    "pais": "PRY", "paisDescripcion": "PARAGUAY",
    "descuento": 0, "descuentoPorcentaje": 0, "descuentoGlobal": 0,
    "anticipo": 0, "anticipoGlobal": 0,
    "ivaTipo": 1, "ivaBase": 100, "iva": 10,
    "basGravIVA": 500000, "liqIVAItem": 50000 },
  { "codigo": "LIB-01", "descripcion": "LIBRO TECNICO (EXENTO)",
    "cantidad": 1, "precioUnitario": 80000, "totalItem": 80000,
    "pais": "PRY", "paisDescripcion": "PARAGUAY",
    "descuento": 0, "descuentoPorcentaje": 0, "descuentoGlobal": 0,
    "anticipo": 0, "anticipoGlobal": 0,
    "ivaTipo": 3, "ivaBase": 0, "iva": 0,
    "basGravIVA": 0, "liqIVAItem": 0 }
]
// La API calcula: dSub10 = 550000  dSubExe = 80000  dTotGralOpe = 630000
//                dIVA10 = 50000   dTotIVA = 50000   dBaseGrav10 = 500000

Nota de crédito electrónica

POST {BASE_URL}/api/v1/documentos
{
  "recordID": "5F-7111E5F9",
  "tipoDocumento": 5,
  "tipoEmision": 1,
  "establecimiento": "001", "punto": "001", "numero": "0000045",
  "fecha": "2026-06-02T10:15:00",
  "moneda": "PYG", "tipoImpuesto": 1, "condicionAnticipo": 1,
  "notaCreditoDebito": { "motivo": 2 },
  "documentoAsociado": {
    "formato": 1,
    "cdc": "01042214610001001000000112026052717799105109"
  },
  "cliente": { /* igual que en la factura original */ },
  "condicion": { "tipo": 1,
                 "contado": [ { "tipo": 1, "monto": 45000, "moneda": "PYG" } ] },
  "items": [ /* los items que se devuelven, con su IVA */ ],
  "totales": { "dTotDesc": 0, "dTotDescGlotem": 0, "dTotAntItem": 0,
               "dTotAnt": 0, "dPorcDescTotal": 0, "dDescTotal": 0,
               "dAnticipo": 0, "dRedon": 0 }
}
// Para NOTA DE DEBITO: tipoDocumento = 6 (el resto idéntico). En NC/ND no se envía "factura".

Autofactura Electrónica (tipoDocumento 4)

Compra a un proveedor no contribuyente. El receptor (cliente) es el propio emisor; vendedor identifica a quién se le compró. No se envía factura.

POST {BASE_URL}/api/v1/documentos
{
  "recordID": "5F-7111E5F9",
  "tipoDocumento": 4,
  "tipoEmision": 1,
  "establecimiento": "001", "punto": "001", "numero": "0000010",
  "fecha": "2026-06-03T09:00:00",
  "moneda": "PYG", "tipoImpuesto": 1, "tipoTransaccion": 10,
  "condicionAnticipo": 1,
  "cliente": {
    "contribuyente": true,
    "tipoOperacion": 1,
    "pais": "PRY", "paisDescripcion": "PARAGUAY",
    "ruc": "3010353-3",
    "tipoContribuyente": 1,
    "razonSocial": "DANIA SOFIA CORONEL NOGUERA"
  },
  "vendedor": {
    "naturaleza": 1,
    "tipoDocumentoIdentidad": 1,
    "numeroDocumentoIdentidad": "2345678",
    "nombre": "JUAN PEREZ",
    "direccion": "RUTA 2 KM 45", "numeroCasa": "0",
    "departamento": 5, "departamentoDescripcion": "GUAIRA",
    "ciudad": 2657, "ciudadDescripcion": "VILLARRICA"
  },
  "condicion": { "tipo": 1,
                 "contado": [ { "tipo": 1, "monto": 150000, "moneda": "PYG" } ] },
  "items": [
    { "codigo": "MAIZ", "descripcion": "MAIZ A GRANEL",
      "unidadMedida": 79, "unidadMedidaDesc": "kg",
      "cantidad": 100, "precioUnitario": 1500,
      "pais": "PRY", "paisDescripcion": "PARAGUAY",
      "totalItem": 150000,
      "ivaTipo": 1, "ivaBase": 100, "iva": 10 }
  ],
  "totales": { "dTotDesc": 0, "dTotDescGlotem": 0, "dTotAntItem": 0, "dTotAnt": 0,
               "dPorcDescTotal": 0, "dDescTotal": 0, "dAnticipo": 0, "dRedon": 0 },
  "documentoAsociado": { "formato": 3, "tipoConstancia": 1 }
}
// "cliente.ruc" / "cliente.razonSocial" son los del PROPIO emisor. El CDC de una Autofactura empieza con "04".

Nota de Remisión Electrónica (tipoDocumento 7)

Ampara un traslado de mercadería. Sin factura, sin condicion, sin totales, sin tipoImpuesto/condicionAnticipo. Los ítems no llevan precio ni IVA.

POST {BASE_URL}/api/v1/documentos
{
  "recordID": "5F-7111E5F9",
  "tipoDocumento": 7,
  "tipoEmision": 1,
  "establecimiento": "001", "punto": "001", "numero": "0000011",
  "fecha": "2026-06-04T07:30:00",
  "moneda": "PYG",
  "cliente": {
    "contribuyente": true, "tipoOperacion": 1,
    "pais": "PRY", "paisDescripcion": "PARAGUAY",
    "ruc": "80012345-6", "tipoContribuyente": 2,
    "razonSocial": "CONSTRUCTORA DEL ESTE S.A."
  },
  "remision": { "motivo": 1, "responsable": 1, "kmRecorrido": 180,
                "fechaEmisionFactura": "2026-06-04" },
  "transporte": {
    "tipoTransporte": 1,
    "modalidad": 1,
    "responsableFlete": 5,
    "fechaInicioTraslado": "2026-06-04",
    "fechaFinTraslado": "2026-06-04",
    "localSalida": {
      "direccion": "DEPOSITO CENTRAL", "numeroCasa": "0",
      "departamento": 5, "departamentoDescripcion": "GUAIRA",
      "ciudad": 2657, "ciudadDescripcion": "VILLARRICA"
    },
    "localEntrega": {
      "direccion": "OBRA AVDA. MCAL. LOPEZ 1234", "numeroCasa": "1234",
      "departamento": 1, "departamentoDescripcion": "CAPITAL",
      "ciudad": 1, "ciudadDescripcion": "ASUNCION"
    },
    "vehiculo": {
      "tipo": "CAMION", "marca": "HINO",
      "tipoIdentificacion": 2, "numeroMatricula": "ABC123"
    },
    "transportista": {
      "naturaleza": 1, "nombre": "FLETES DEL SUR SRL", "ruc": "80099999-0",
      "choferDocumentoIdentidad": "1234567", "choferNombre": "PEDRO GOMEZ"
    }
  },
  "items": [
    { "codigo": "CEM-50", "descripcion": "CEMENTO PORTLAND 50KG",
      "unidadMedida": 77, "unidadMedidaDesc": "UNI",
      "cantidad": 200,
      "pais": "PRY", "paisDescripcion": "PARAGUAY" }
  ]
}
// El CDC de una Nota de Remision empieza con "07". Puede quedar "Pendiente" igual que una factura; el KUDE se imprime para acompañar la carga.

Venta al Estado / B2G — ej. un ministerio (N14)

Factura Electrónica normal (tipoDocumento 1), pero el receptor es una entidad de gobierno: cliente.tipoOperacion = 3, y es obligatorio el bloque compraPublica con los datos del código de contratación (DNCP).

POST {BASE_URL}/api/v1/documentos
{
  "recordID": "5F-7111E5F9",
  "tipoDocumento": 1,
  "tipoEmision": 1,
  "establecimiento": "001", "punto": "001", "numero": "0000012",
  "fecha": "2026-06-05T10:00:00",
  "moneda": "PYG", "tipoImpuesto": 1, "tipoTransaccion": 1,
  "condicionAnticipo": 1,
  "factura": { "presencia": 1 },
  "cliente": {
    "contribuyente": true,
    "tipoOperacion": 3,
    "pais": "PRY", "paisDescripcion": "PARAGUAY",
    "ruc": "80000000-2",
    "tipoContribuyente": 2,
    "razonSocial": "MINISTERIO DE EDUCACION Y CIENCIAS (EJEMPLO)"
  },
  "compraPublica": {
    "modalidad": "LC",
    "entidad": "00001",
    "anio": "26",
    "secuencia": "0000001",
    "fechaCodigo": "2026-05-20"
  },
  "condicion": { "tipo": 1,
                 "contado": [ { "tipo": 1, "monto": 550000, "moneda": "PYG" } ] },
  "items": [
    { "codigo": "SERV-01", "descripcion": "MATERIAL DIDACTICO",
      "unidadMedida": 77, "unidadMedidaDesc": "UNI",
      "cantidad": 1, "precioUnitario": 500000,
      "pais": "PRY", "paisDescripcion": "PARAGUAY",
      "totalItem": 500000,
      "ivaTipo": 1, "ivaBase": 100, "iva": 10 }
  ],
  "totales": { "dTotDesc": 0, "dTotDescGlotem": 0, "dTotAntItem": 0, "dTotAnt": 0,
               "dPorcDescTotal": 0, "dDescTotal": 0, "dAnticipo": 0, "dRedon": 0 }
}
// El RUC del ministerio y los datos de "compraPublica" son de EJEMPLO: usá el RUC real del organismo y el código de contratación que te entregó la DNCP.

06 Respuestas HTTP

API nueva — POST /api/v1/documentos

201Creadosuccess, cdc, estado, estado_sifen, nro_lote, qr_url, links, documento.
200Reintento idempotenteMismo Idempotency-Key: devuelve el documento ya emitido, mismo cuerpo que el 201.
422Validación{ "message": "...", "errors": { campo: [msgs] } } — mensajes en español. También si el tipoDocumento no está habilitado para tu empresa (N13), si en una Autofactura el cliente no es el propio emisor (N11), o si falta compraPublica en una venta al Estado (N14).
403recordID no corresponde{ "success": false, "message": "..." }
409Número ya emitidoSin Idempotency-Key. El cuerpo trae el documento existente (con su cdc).
502SIFEN no respondióEl documento queda firmado con su CDC (no se pierde). Cuerpo con cdc y warning.
401Sin token o inválidoFalta la cabecera Authorization o el token no es válido.
429Demasiadas solicitudesLímite 120/min por token. Reintentar luego.

API legacy — POST /api-py/firmar-enviar.php

Siempre HTTP 200. El resultado se lee en el cuerpo:

CasoCuerpo
OK{ respuesta_sifen, cdc, nro_lote, estado_sifen, mensaje_sifen }
Error de envío{ success:false, cdc, xml, warning:"Envio SIFEN fallido.", estado_sifen:"Rechazado", mensaje_sifen }
Error general{ success:false, estado_sifen:"ERROR", mensaje_sifen }
?modo=local{ success:true, cdc, xml, nro_lote:"", estado_sifen:"Pendiente", mensaje_sifen }

Estados posibles (estado_sifen): Pendiente · Aprobado · Aprobado con observacion · Rechazado · ERROR.

07 Idempotencia — cabecera Idempotency-Key

Recomendada siempre en la API nueva.

Header
Idempotency-Key: <clave-única-del-comprobante> (≤ 100 chars)
Valor sugerido
"FE-" + establecimiento + "-" + punto + "-" + numero — o el ID interno del comprobante en tu ERP
  • 1.er POST con esa clave → emite normal (201).
  • 2.º POST con la misma clave y el mismo JSON → no duplica: devuelve el documento ya emitido con HTTP 200 (mismo cdc).
  • Sin Idempotency-Key, repetir el número da 409.

Uso típico: ante un timeout de red, reintentás el mismo request con la misma clave y recuperás el CDC sin arriesgarte a emitir dos veces. La ruta legacy no usa la cabecera: repetir el mismo número devuelve igual (200) el documento ya emitido.

08 Consultar el estado

Al emitir casi siempre vuelve Pendiente: SIFEN procesa el lote de forma asíncrona. La API consulta sola el estado final con reintentos a 5 s, 15 s, 1 min, 5 min, 15 min y 1 h. El comprobante ya es válido para entregar al cliente (el KUDE se puede imprimir) aunque esté Pendiente.

El sistema emisor puede consultar cuando quiera:

MétodoRutaPara
GET/api/v1/documentos/{cdc}estado actualizado
GET/api/v1/lotes/{nroLote}estado del lote
GET/api-py/consultar.php?lote={n}versión legacy
POST/api/v1/documentos/{cdc}/consultarfuerza la consulta ya

09 Descargar XML / JSON / QR / KUDE

RutaDevuelve
/api/v1/documentos/{cdc}/xmltext/xml
/api/v1/documentos/{cdc}/jsonapplication/json
/api/v1/documentos/{cdc}/qr{ "success": true, "qr": "https://..." }
/api/v1/documentos/{cdc}/kude?format=pdfapplication/pdf
/api/v1/documentos/{cdc}/kude?format=htmltext/html

Legacy: get_xml.php?cdc= · get_json.php?cdc= · get_qr.php?cdc= · kude.php?cdc=&format=pdf.

El KUDE en PDF ya trae el QR embebido. Nunca reconstruir el QR por cuenta propia: usar el PDF de la API o el qr_url que devuelve la emisión.

10 Anular un documento

POST {BASE_URL}/api/v1/documentos/{cdc}/anular
// Header: Authorization: Bearer <TOKEN>
{ "motivo": "Error en los datos del cliente" }
Respuesta
{ "success": true, "estado_sifen": "Aprobado", "codigo_sifen": "0600",
  "mensaje_sifen": "Evento registrado con exito", "respuesta_sifen": { /* ... */ } }

Reglas SIFEN: el motivo debe tener entre 5 y 500 caracteres; la anulación se acepta dentro de las 48 horas de la emisión.

10.1 Reenviar (reintentar el envío de un documento ya firmado)

Se usa cuando el documento ya tiene cdc (quedó firmado) pero el envío a SIFEN falló o quedó en un estado no final — por ejemplo recibiste un 502, o el estado_sifen quedó en Rechazado/ERROR por un problema de red (no por un rechazo de negocio de SIFEN). Reenviar no genera un CDC nuevo ni cambia el número: reutiliza el XML ya firmado tal cual.

POST {BASE_URL}/api/v1/documentos/{cdc}/reenviar
// Header: Authorization: Bearer <TOKEN>
// (sin body)

Respuesta: mismo formato que POST /api/v1/documentos (success, cdc, estado, estado_sifen, nro_lote, qr_url, links, documento). 200 si SIFEN aceptó el lote, 502 si volvió a fallar (el documento sigue firmado; se puede reintentar más tarde o forzar una consulta).

Si el documento ya está aprobado o anulado el reenvío no aplica → 422 { "message": "El documento ya esta aprobado; no se puede reenviar." }

Diferencia con la Idempotencia: la cabecera Idempotency-Key es para cuando el POST /api/v1/documentos ORIGINAL no responde (timeout de red) — ahí todavía no sabés si la API llegó a procesar el JSON, así que reintentás el mismo POST con el mismo número. /reenviar es para cuando ya tenés confirmado el cdc (el documento SÍ se creó y firmó) pero el envío de ESE documento a SIFEN falló: no hace falta mandar el JSON de nuevo, solo el CDC en la URL.

API legacy: no tiene endpoint de reenvío. Usá el panel de administración (botón "Reenviar" en el detalle del documento) o el reintento con Idempotency-Key.

11 Manejo de errores en el sistema emisor

  1. Guardá siempre el cdc que devuelve la API, aunque estado_sifen sea Rechazado o ERROR: ese CDC ya quedó asignado a ese número y no se puede reutilizar.
  2. Si no hay respuesta (timeout): no generes número nuevo. Reintentá el mismo JSON con la misma Idempotency-Key.
  3. Si estado_sifen = "Rechazado": leé mensaje_sifen y codigo_sifen, corregí y emití un comprobante nuevo con número nuevo (un DE rechazado no se corrige, se reemplaza).
  4. Si estado_sifen = "Pendiente": es lo normal. Entregá el comprobante / imprimí el KUDE. Consultá el estado final más tarde.
  5. 429: esperá y reintentá.
  6. 502: el CDC ya existe. Guardalo. La API reintenta el envío sola cada 10 minutos (hasta 5 intentos); si no querés esperar, forzá el reenvío ya mismo con POST .../reenviar, o consultá el estado con POST .../consultar.

12 Código de ejemplo

Reemplazá {BASE_URL} y <TOKEN>.

curl -X POST {BASE_URL}/api/v1/documentos \
     -H "Content-Type: application/json" \
     -H "Accept: application/json" \
     -H "Authorization: Bearer <TOKEN>" \
     -H "Idempotency-Key: FE-001-001-0000001" \
     --data-binary "@factura.json"
# En Windows (cmd): cambiar \ por ^

13 Tablas de códigos SIFEN

Los textos van tal cual; respetar tildes.

CampoValores
tipoDocumento1 = Factura · 4 = Autofactura · 5 = Nota de crédito · 6 = Nota de débito · 7 = Nota de remisión
tipoEmision1 = Normal · 2 = Contingencia
tipoTransaccion1 Venta de mercadería · 2 Prestación de servicios · 3 Mixto · 4 Venta de activo fijo · 5 Venta de divisas · 6 Compra de divisas · 7 Promoción/muestras · 8 Donación · 9 Anticipo · 10 Compra de productos · 11 Compra de servicios · 12 Venta de crédito fiscal · 13 Muestras médicas
tipoImpuesto1 IVA · 2 ISC · 3 Renta · 4 Ninguno · 5 IVA-Renta
condicionAnticipo1 Anticipo Global · 2 Anticipo por Ítem
presencia1 Presencial · 2 Electrónica · 3 Telemarketing · 4 A domicilio · 5 Bancaria · 6 Cíclica
condicion.tipo1 Contado · 2 Crédito
contado.tipo (iTiPago)1 Efectivo · 2 Cheque · 3 Tarjeta crédito · 4 Tarjeta débito · 5 Transferencia · 6 Giro · 7 Billetera electrónica · 8 Tarjeta empresarial · 9 Vale · 10 Retención · 11 Pago por anticipo · 12 Valor fiscal · 13 Valor comercial · 14 Compensación · 15 Permuta · 16 Pago bancario
infoTarjeta.tipo1 Visa · 2 Mastercard · 3 American Express · 4 Maestro · 5 Panal · 6 Cabal · 99 Otra (mandar tipoDescripcion)
infoTarjeta.medioPago1 POS · 2 Pago Electrónico · 3 Pago Móvil · 4 Otro
item.ivaTipo1 Gravado IVA · 2 Exonerado · 3 Exento · 4 Gravado parcial
TipoDocumentoIdentidad1 Cédula paraguaya · 2 Pasaporte · 3 Cédula extranjera · 4 Carnet de residencia · 5 Innominado · 6 Tarjeta Diplomática de exoneración fiscal
cliente.tipoOperacion1 B2B · 2 B2C · 3 B2G · 4 B2F
cliente.tipoContribuyente1 Persona Física · 2 Persona Jurídica
notaCreditoDebito.motivo1 Devolución y ajuste de precios · 2 Devolución · 3 Descuento · 4 Bonificación · 5 Crédito incobrable · 6 Recupero de costo · 7 Recupero de gasto · 8 Ajuste de precio
credito.iCondCred1 Plazo · 2 Cuota
documentoAsociado.formato1 Electrónico · 2 Impreso · 3 Constancia Electrónica
documentoAsociado.tipoDocumentoImpreso (formato 2)1 Factura · 2 Nota de crédito · 3 Nota de débito · 4 Nota de remisión · 5 Comprobante de retención
documentoAsociado.tipoConstancia (formato 3)1 Constancia de no ser contribuyente · 2 Constancia de microproductores
unidadMedida77 UNI · 79 kg · 83 g · 86 LT · 87 ML · 89 m · 90 m² · 91 m³ · 101 Hora · 104 Día · 108 Mes · 110 Año
monedaPYG Guaraní · USD Dólar Americano · BRL Real · ARS Peso Argentino · EUR Euro (para PYG la API escribe «Guarani»)
pais (ISO alfa-3)PRY PARAGUAY · ARG ARGENTINA · BRA BRASIL · URY URUGUAY · CHL CHILE · BOL BOLIVIA · USA ESTADOS UNIDOS

Autofactura Electrónica — tipoDocumento 4

vendedor.naturaleza1 No contribuyente · 2 Extranjero
vendedor.tipoDocumentoIdentidad1 Cédula paraguaya · 2 Pasaporte · 3 Cédula extranjera · 4 Carnet de residencia

Nota de Remisión Electrónica — tipoDocumento 7

remision.motivo1 Traslado por venta · 2 Traslado por consignación · 3 Exportación · 4 Traslado por compra · 5 Importación · 6 Traslado por devolución · 7 Traslado entre locales de la empresa · 8 Traslado por transformación · 9 Traslado por reparación · 10 Traslado por emisor móvil · 11 Exhibición o demostración · 12 Participación en ferias · 13 Traslado de encomienda · 14 Decomiso · 99 Otro
remision.responsable1 Emisor de la factura · 2 Poseedor de la factura y bienes · 3 Empresa transportista · 4 Despachante de Aduanas · 5 Agente de transporte o intermediario
transporte.tipoTransporte1 Propio · 2 Tercero
transporte.modalidad1 Terrestre · 2 Fluvial · 3 Aéreo · 4 Multimodal
transporte.responsableFlete1 Emisor de la FE · 2 Receptor de la FE · 3 Tercero · 4 Agente intermediario del transporte · 5 Transporte propio
vehiculo.tipoIdentificacion1 Nro. de identificación del vehículo · 2 Nro. de matrícula/chapa del vehículo
transportista.naturaleza1 Contribuyente · 2 No contribuyente

Códigos de respuesta SIFEN más comunes

0300Lote recibido con éxito0301Lote en proceso
0302Lote procesado0362Consulta de lote exitosa
0420CDC ya existente0421CDC inexistente
0600Evento registrado0601Evento rechazado
2xxx / 3xxx — errores de validación de campos del DE

14 Checklist de integración

  • Tengo el {BASE_URL} y un token (API nueva) o mi IP está permitida (legacy).
  • El {BASE_URL} es una constante de configuración en mi sistema (puede cambiar sin recompilar).
  • Envío recordID en cada request.
  • establecimiento / punto / numero con 3 / 3 / 7 dígitos y ceros a la izquierda.
  • No repito números; uso Idempotency-Key.
  • fecha en YYYY-MM-DDTHH:MM:SS, hora de Paraguay.
  • Importes como número JSON (sin separador de miles, punto decimal).
  • Calculo basGravIVA y liqIVAItem por ítem (fórmula N5).
  • Mando el bloque totales con los 8 campos del emisor (0 si no hay).
  • Si contado: la suma de pagos = total del comprobante.
  • Guardo el cdc y el nro_lote de la respuesta siempre.
  • Manejo 201 / 200 / 409 / 422 / 403 / 502 / 429 (o, en legacy, leo el cuerpo).
  • Imprimo el KUDE desde la API (no reconstruyo el QR).
  • Probé en ambiente test antes de producción.
  • Si emito Autofactura (4): cliente = mi propio emisor + bloque vendedor.
  • Si emito Nota de Remisión (7): bloques remision y transporte; ítems sin precio/IVA; sin factura/condicion/totales.
  • Autofactura (4) / Nota de Remisión (7): el proveedor las habilitó para mi empresa.

15 Si tu proveedor activó el modo multiempresa (SaaS)

Todo lo de arriba sigue igual (URLs, JSON, Idempotency-Key, capa legacy). Lo que cambia:

El token ahora identifica a la empresa

Antes, el token identificaba solo a un usuario del panel y la empresa se resolvía por el recordID del JSON. Ahora el token en sí mismo identifica a la empresa, y el recordID se valida contra ella: si no coincide, 403 EMPRESA_NO_AUTORIZADA. Los tokens que ya tenías emitidos siguen funcionando sin cambios.

Códigos de error nuevos

Mismo formato de siempre, con un campo codigo además de error:

HTTPcodigoCuándo
401TOKEN_FALTANTEFalta la cabecera Authorization.
401TOKEN_INVALIDOToken inexistente o adulterado.
401TOKEN_EXPIRADORevocado o vencido.
401USUARIO_INACTIVOEl usuario dueño del token está desactivado.
403EMPRESA_NO_AUTORIZADAEl recordID no es el de la empresa del token.
403EMPRESA_NO_OPERATIVAEmpresa pendiente, cerrada o purgada.
403MODULO_NO_CONTRATADOTipo de documento o función no contratada (incluye api_rest: ver abajo).
402SUSCRIPCION_VENCIDAVencida la gracia: no se puede emitir.
402LIMITE_DOCUMENTOSCupo mensual agotado (trae detalle: {usado, limite, periodo}).
503EMPRESA_EN_MANTENIMIENTOMigración o purga en curso.

Cabeceras nuevas en la emisión

X-Empresa-Slug, X-Cupo-Usado, X-Cupo-Limite, X-Suscripcion-Vence.

Endpoint nuevo

GET {BASE_URL}/api/v1/cuenta (solo lectura, no consume cupo) → { empresa, ruc, estado, plan, modulos[], vence_at, ambiente, produccion_habilitada }.

El acceso por API es, a su vez, un módulo contratado (api_rest)

Emitir por /api/v1 es uno de los dos canales de emisión (el otro es el formulario del panel, módulo panel_facturacion) y cada uno se contrata por separado. Si tu empresa no tiene api_rest, POST /api/v1/documentos, .../anular y .../reenviar responden 403 MODULO_NO_CONTRATADO:

{
  "success": false,
  "error": "El modulo 'api_rest' no esta contratado.",
  "codigo": "MODULO_NO_CONTRATADO"
}

No es un error transitorio: no reintentes, avisale al usuario. Con el mismo token, esto sigue funcionando siempre, tenga o no el módulo: GET /api/v1/salud, GET /api/v1/cuenta, el listado y el detalle de documentos, POST .../consultar y las descargas de XML/JSON/QR/KUDE — lo ya emitido se consulta y se descarga siempre.

Guía completa para integraciones nuevas contra el SaaS: MANUAL_FOR_SAAS.md (en el repositorio de la API).

Novedad v1.5 — módulo de revendedores

Si tu proveedor además activó el módulo de revendedores, un revendedor puede dar de alta y administrar sus propias empresas clientes bajo marca propia, con panel y guard totalmente separados. Esto no cambia en nada el contrato de esta página: una empresa dada de alta por un revendedor que tenga el módulo api_rest integra exactamente igual que cualquier otra (mismo JSON, mismos endpoints /api/v1). Ver MANUAL_REVENDEDOR.md si vos mismo operás como revendedor.

Contrato v1.5 · Formato SIFEN rDE v150 · Este documento es el contrato público de integración.