Integración por REST local

Referencia técnica para integración por rest local dentro del cliente local.

Objetivo

Esta guía describe cómo integrar un sistema externo con el cliente local usando HTTP por loopback.

Si estás empezando la integración, primero lee Bandeja REST del cliente local. Esa guía funciona como punto de entrada y esta página queda como referencia operativa endpoint por endpoint.

Está pensada para integradores. Cubre:

URL base

Base URL por defecto:

http://127.0.0.1:18787

Notas:

Endpoints disponibles

MétodoEndpointUso
GET/healthEstado rápido del daemon
GET/stateEstado local
POST/enqueueEncolado asíncrono
POST/sign-cfeNumeración y firma con respuesta inmediata
POST/reprintReimpresión
POST/pdfGeneración de PDF
GET/proximo-serie-nroPróximo folio local
POST/validar-xmlValidación local
POST/existe-constanciaVerificación de existencia local

Ruteo por punto de emisión

Hay dos modos:

Regla:

GET /health

Ejemplo:

curl http://127.0.0.1:18787/health

Respuesta esperada:

{
  "ok": true,
  "service": "modulo_local_daemon",
  "rest_base_url": "http://127.0.0.1:18787",
  "state": {
    "running": true
  }
}

GET /state

Devuelve el estado operativo local del daemon.

Uso recomendado:

POST /enqueue

Encola un comprobante para procesamiento local asíncrono.

Ejemplo:

{
  "tipo_cfe": 111,
  "uuid": "externo-123",
  "cod_comercio": "1",
  "cod_terminal": "1",
  "xml": "<CFE xmlns=\"http://cfe.dgi.gub.uy\" version=\"1.0\">...</CFE>",
  "adenda": "Texto opcional",
  "emails": ["cliente@example.com"],
  "impresora": "CajaFiscal;FORMATO=personalizado;COPIAS=2",
  "send_now": true
}

Respuesta:

{
  "ok": true,
  "stored_path": "/ruta/local/inbox/20260318121000123-externo-123.json",
  "uuid": "externo-123",
  "send_now": true
}

Importante:

POST /sign-cfe

Numerar, firmar y responder en el acto.

Ejemplo:

{
  "tipo_cfe": 111,
  "uuid": "externo-123",
  "cod_comercio": "1",
  "cod_terminal": "1",
  "xml": "<CFE xmlns=\"http://cfe.dgi.gub.uy\" version=\"1.0\">...</CFE>",
  "adenda": "Texto opcional",
  "emails": ["cliente@example.com"],
  "impresora": "CajaFiscal;FORMATO=personalizado;COPIAS=2",
  "send_now": false
}

Respuesta de éxito:

{
  "uuid": "externo-123",
  "tipo_cfe": "111",
  "serie": "A",
  "numero": "301",
  "codigo_respuesta": "00",
  "mensaje_respuesta": "CFE firmado localmente",
  "codigo_terminal": "1",
  "codigo_comercio": "1",
  "numero_inicial_cae": "301",
  "numero_final_cae": "400",
  "vencimiento_cae": "2028-01-01",
  "cfe_firmado": "<CFE>...</CFE>",
  "datos_codigo_qr": "https://...",
  "codigo_seguridad": "ZmCpqT",
  "fecha_firma_cfe": "2026-03-18T12:10:00Z",
  "imagen_qr": null
}

Respuesta de error:

{
  "uuid": "externo-123",
  "tipo_cfe": "111",
  "serie": null,
  "numero": null,
  "codigo_respuesta": "31",
  "mensaje_respuesta": "validation error: ...",
  "codigo_terminal": "1",
  "codigo_comercio": "1",
  "numero_inicial_cae": null,
  "numero_final_cae": null,
  "vencimiento_cae": null,
  "cfe_firmado": null,
  "datos_codigo_qr": null,
  "codigo_seguridad": null,
  "fecha_firma_cfe": null,
  "imagen_qr": null
}

Códigos funcionales

codigo_respuestaInterpretación
00Éxito
31Rechazo de validación o XML rechazado
96Error interno, de firma, permisos, rango, persistencia o SOAP

Códigos HTTP

HTTPInterpretación
200Operación procesada; revisar codigo_respuesta
422Request inválido o XML rechazado tempranamente
500Error interno del daemon

Regla recomendada:

POST /reprint

Encola la reimpresión de un comprobante emitido.

Se puede localizar por:

Ejemplo:

{
  "uuid": "externo-123",
  "impresora": "CajaFiscal;FORMATO=personalizado;COPIAS=2",
  "variant": "personalizado",
  "fallback_copies": 2,
  "cod_comercio": "1",
  "cod_terminal": "1"
}

Respuesta:

{
  "ok": true,
  "queued": true
}

HTTP esperado:

POST /pdf

Genera el PDF de un comprobante ya emitido y devuelve el binario.

Ejemplo:

{
  "uuid": "externo-123",
  "impresora": "pdf",
  "variant": "personalizado",
  "fallback_copies": 1,
  "cod_comercio": "1",
  "cod_terminal": "1"
}

Respuesta:

GET /proximo-serie-nro

Ejemplo:

curl "http://127.0.0.1:18787/proximo-serie-nro?tipo_cfe=111&cod_comercio=1&cod_terminal=1"

Respuesta con rango activo:

{
  "ok": true,
  "tipo_cfe": 111,
  "serie": "A",
  "numero_siguiente": 301,
  "numero_desde": 301,
  "numero_hasta": 400,
  "disponibles": 100,
  "vencimiento_cae": "2028-01-01"
}

POST /validar-xml

Request:

{
  "xml": "<CFE xmlns=\"http://cfe.dgi.gub.uy\" version=\"1.0\">...</CFE>"
}

Respuesta:

{
  "ok": true,
  "valido": false,
  "issues": []
}

POST /existe-constancia

Request:

{
  "tipo_cfe": 111,
  "serie": "A",
  "numero": 301,
  "cod_comercio": "1",
  "cod_terminal": "1"
}

Respuesta cuando existe:

{
  "ok": true,
  "existe": true,
  "codigo_respuesta": "00",
  "estado": "Accepted",
  "uuid": "externo-123",
  "tipo_cfe": 111,
  "serie": "A",
  "numero": 301
}

Impresoras

Los endpoints que usan impresora aceptan una especificación textual.

Ejemplos:

Parámetros:

ParámetroDescripción
nombre baseNombre o destino de impresora
FORMATO=personalizadoPlantilla HTML/PDF
FORMATO=escposImpresión térmica ESC/POS RAW
FORMATO=roll, FORMATO=rollo, FORMATO=tmlPDF tipo ticket usando parser .tml
COPIAS=2Cantidad de copias

Errores frecuentes

Recomendaciones