Webhooks - avisos automáticos a tus sistemas
Recibí en tu sistema un aviso cada vez que un documento se crea, se aprueba, se rechaza o falla en SIFEN: cómo crear el endpoint, qué eventos hay, cómo verificar la firma HMAC-SHA256, probarlo y qué pasa cuando falla.
Un webhook es un aviso que FacturaMax le manda a tu sistema (tu ERP, tu tienda, una planilla conectada) cada vez que pasa algo con tus documentos: se creó una factura, SIFEN la aprobó, la rechazó… Así tu sistema se entera solo, sin tener que preguntar a cada rato. Esta guía es un poco más técnica: si no tenés un sistema propio, probablemente no la necesites.
En el menú lateral del panel, sección Herramientas SIFEN → Webhooks. La dirección directa es
https://app.facturamax.app/bm-admin/webhooks.
Los eventos
| Evento | En el panel | Cuándo se envía |
|---|---|---|
de.created | DE Creado | Se emitió un documento (todavía no tiene respuesta de SIFEN). |
de.approved | DE Aprobado | SIFEN aprobó el documento. |
de.rejected | DE Rechazado | SIFEN rechazó el documento. |
de.error | DE Error | No se pudo enviar el documento o no hubo una respuesta confirmada de SIFEN. |
evento.accepted | Evento Aceptado | SIFEN aceptó un evento que enviaste vos como emisor (por ejemplo, una anulación o una inutilización). |
evento.rejected | Evento Rechazado | SIFEN rechazó uno de esos eventos. |
Crear un endpoint
Tocá Nuevo endpoint
Se abre el panel Nuevo webhook.
Cargá la URL
En URL del endpoint poné la dirección de tu sistema que va a recibir los avisos, por ejemplo
https://api.tuempresa.com/sifen/webhook. Usá HTTPS.
Descripción (opcional)
Un nombre para reconocerlo, por ejemplo «Producción · sistema ERP».
Elegí los eventos
Marcá al menos uno en Eventos a suscribir. Sólo vas a recibir los que marques.
Tocá Crear webhook y guardá el secret
FacturaMax te muestra el Webhook Secret: una clave de 64 caracteres con la que se firma cada aviso. Copialo con Copiar y guardalo en tu sistema. No se vuelve a mostrar. Después tocá Lo guardé.
No se puede volver a ver. Abrí el webhook y tocá Rotar secret: se genera uno nuevo (que se muestra una sola vez) y el anterior deja de servir en ese momento. Actualizalo en tu sistema enseguida.
Qué recibe tu sistema
Cada aviso es un POST con un cuerpo JSON y estos encabezados:
| Encabezado | Qué trae |
|---|---|
X-FacturaMax-Signature | La firma del cuerpo (ver abajo). |
X-FacturaMax-Event | El evento, por ejemplo de.approved. |
X-FacturaMax-Delivery-Id | El número de esa entrega. Te sirve para no procesar dos veces el mismo aviso. |
X-FacturaMax-Timestamp | La hora del envío, en segundos (formato Unix). |
User-Agent | FacturaMax-Webhook/1.0 |
Ejemplo de un de.approved:
{
"event": "de.approved",
"timestamp": "2026-10-16T10:32:05-03:00",
"data": {
"id": 1520,
"cdc": "01800123456001001000014322026101611234567890",
"tipo_de": 1,
"estado": "APPROVED",
"numero": "001-001-0000143",
"fecha_emision": "2026-10-16",
"receptor_ruc": "80099999-1",
"receptor_nombre": "Cliente Ejemplo S.A.",
"moneda": "PYG",
"total": "1765000.0000",
"sifen_codigo_respuesta": "0260",
"sifen_mensaje": "Aprobado",
"sifen_protocolo": "123456",
"sent_at": "2026-10-16T10:31:58-03:00",
"approved_at": "2026-10-16T10:32:05-03:00"
}
} Los eventos evento.accepted y evento.rejected traen en data el evento_id, el de_id y el cdc del documento
(vacíos si el evento no es sobre un documento, como una inutilización), el tipo_evento, el motivo, el estado, el
sifen_codigo y el sifen_mensaje.
Verificar la firma
Para estar seguro de que el aviso viene de FacturaMax, calculá un HMAC-SHA256 del cuerpo tal cual lo recibiste
(los bytes crudos, sin volver a armar el JSON) usando tu secret como clave. El resultado, en hexadecimal, tiene
que ser igual al encabezado X-FacturaMax-Signature.
const crypto = require('crypto');
app.post('/sifen/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const recibida = req.get('X-FacturaMax-Signature') || '';
const esperada = crypto
.createHmac('sha256', process.env.FACTURAMAX_WEBHOOK_SECRET)
.update(req.body) // el cuerpo crudo
.digest('hex');
const ok = recibida.length === esperada.length &&
crypto.timingSafeEqual(Buffer.from(recibida), Buffer.from(esperada));
if (!ok) return res.status(401).end();
const aviso = JSON.parse(req.body);
// ... procesá aviso.event y aviso.data
res.status(200).end();
}); $cuerpo = file_get_contents('php://input');
$recibida = $_SERVER['HTTP_X_FACTURAMAX_SIGNATURE'] ?? '';
$esperada = hash_hmac('sha256', $cuerpo, getenv('FACTURAMAX_WEBHOOK_SECRET'));
if (! hash_equals($esperada, $recibida)) {
http_response_code(401);
exit;
}
$aviso = json_decode($cuerpo, true);
// ... procesá $aviso['event'] y $aviso['data']
http_response_code(200); El encabezado de la firma se llama X-FacturaMax-Signature. Si en el panel ves mencionado otro nombre al crear el
webhook, guiate por este.
Respondé rápido y con 2xx
- Tu sistema tiene 10 segundos para contestar. Contestá con un código 2xx (por ejemplo
200) apenas recibas el aviso, y hacé el trabajo pesado después. - Cualquier respuesta fuera de 2xx cuenta como falla.
Reintentos y desactivación automática
| Qué pasa | Qué hace FacturaMax |
|---|---|
| Tu sistema contesta 2xx | Entrega exitosa. El contador de fallas vuelve a 0. |
| Contesta un error 4xx (por ejemplo 401 o 404) | Lo marca como fallido y no reintenta. |
| Contesta un error 5xx, no contesta a tiempo o no se puede conectar | Reintenta: hasta 3 intentos en total, esperando 1 minuto antes del segundo y 5 minutos antes del tercero. |
| Se acumulan 10 fallas seguidas | El webhook se desactiva solo. En su detalle ves «Deshabilitado automáticamente el…». |
En la tarjeta de cada webhook aparece una etiqueta amarilla con la cantidad de fallos cuando los hay. Para volver a activarlo, arreglá tu endpoint y tocá la etiqueta INACTIVO de la tarjeta: pasa a ACTIVO y el contador de fallas se pone en 0.
Mientras un webhook está inactivo no recibe avisos, y los que se generen en ese tiempo no se reenvían al reactivarlo. Si te perdiste alguno, revisá el estado de esos documentos en el panel.
Probar y revisar las entregas
Hacé clic en la tarjeta de un webhook para abrir su detalle. Ahí tenés:
- Probar ahora: manda un aviso de prueba con el evento
webhook.testy el mensaje «This is a test webhook delivery from FacturaMax.». Sirve para verificar la URL y la firma. - Actualizar entregas, Editar (URL, descripción y eventos), Rotar secret y Eliminar.
- Eventos suscriptos: los que elegiste.
- Entregas recientes (se actualiza cada 10 segundos): cada aviso enviado con el Evento, el Status (por
ejemplo
200 OK,500 ERR,PENDINGoFAILED), el número de Intento, cuánto Tiempo tardó tu sistema en contestar y hace cuánto se envió.
Podés crear varios endpoints, cada uno con sus eventos. Por ejemplo, uno para tu ERP con de.approved y
de.rejected, y otro para un sistema de alertas sólo con de.error.
Escribinos a soporte@facturamax.app y te ayudamos.
¿Te sirvió este artículo?
¡Gracias por tu opinión!