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
- endpoints disponibles
- contratos de request y response
- códigos HTTP y códigos funcionales
- ruteo por punto de emisión
- reimpresión y PDF
URL base
Base URL por defecto:
http://127.0.0.1:18787
Notas:
- escucha por loopback
- el puerto puede configurarse
- si el canal REST está desactivado en el perfil, no responderá
Endpoints disponibles
| Método | Endpoint | Uso |
|---|---|---|
GET | /health | Estado rápido del daemon |
GET | /state | Estado local |
POST | /enqueue | Encolado asíncrono |
POST | /sign-cfe | Numeración y firma con respuesta inmediata |
POST | /reprint | Reimpresión |
POST | /pdf | Generación de PDF |
GET | /proximo-serie-nro | Próximo folio local |
POST | /validar-xml | Validación local |
POST | /existe-constancia | Verificación de existencia local |
Ruteo por punto de emisión
Hay dos modos:
- usar el perfil activo del daemon
- enviar
cod_comercioycod_terminalpara enrutar a un punto específico
Regla:
- si se envía uno, deben enviarse ambos
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:
- monitoreo local
- diagnóstico técnico
- soporte
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:
/enqueueconfirma aceptación local del trabajo- no implica que el comprobante ya haya quedado emitido
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_respuesta | Interpretación |
|---|---|
00 | Éxito |
31 | Rechazo de validación o XML rechazado |
96 | Error interno, de firma, permisos, rango, persistencia o SOAP |
Códigos HTTP
| HTTP | Interpretación |
|---|---|
200 | Operación procesada; revisar codigo_respuesta |
422 | Request inválido o XML rechazado tempranamente |
500 | Error interno del daemon |
Regla recomendada:
- considerar emitido solo si HTTP
200,codigo_respuesta = "00"yserie+numeroson válidos
POST /reprint
Encola la reimpresión de un comprobante emitido.
Se puede localizar por:
uuid- o
tipo_cfe + serie + numero
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:
202 Accepted
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:
HTTP 200Content-Type: application/pdf- body binario
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:
CajaFiscalCajaFiscal;COPIAS=2CajaFiscal;FORMATO=personalizado;COPIAS=2CajaFiscal;FORMATO=escpos;COPIAS=2CajaFiscal;FORMATO=rollo;COPIAS=2
Parámetros:
| Parámetro | Descripción |
|---|---|
| nombre base | Nombre o destino de impresora |
FORMATO=personalizado | Plantilla HTML/PDF |
FORMATO=escpos | Impresión térmica ESC/POS RAW |
FORMATO=roll, FORMATO=rollo, FORMATO=tml | PDF tipo ticket usando parser .tml |
COPIAS=2 | Cantidad de copias |
Errores frecuentes
uuid es obligatorioxml es obligatoriotipo_cfe debe ser mayor a cerocod_comercio es obligatorio para enrutar por punto de emisióncod_terminal es obligatorio para enrutar por punto de emisiónNo se encontró perfil para cod_comercio=X cod_terminal=Y- errores de firma
- errores de rango
- errores SOAP
Recomendaciones
- usar
uuidúnicos - no considerar éxito solo por HTTP
200 - en
/sign-cfe, revisar siemprecodigo_respuesta - usar
/enqueuesi el flujo es asíncrono - usar
/sign-cfesi el flujo es síncrono - registrar
uuid,tipo_cfe,serie,numero,codigo_respuestaymensaje_respuesta