Saltar al contenido principal
🔗

Webhooks

Recibe notificaciones en tiempo real cuando ocurren eventos en Holded.

⚡ Tiempo real🔒 Payloads firmados🔄 Reintentos automáticos🎯 Filtrado de eventos

Descripción general

Los webhooks te permiten recibir notificaciones HTTP POST cuando ocurren eventos en tu cuenta de Holded, como la creación de una nueva factura o la recepción de un pago.

Configurar webhooks

Configura los webhooks en tu panel de Holded en Ajustes > Webhooks. Necesitarás proporcionar:

  • Una URL HTTPS accesible públicamente
  • Los eventos a los que quieres suscribirte

Cabeceras comunes

Cada petición de webhook incluye estas cabeceras:

x-holded-webhook-eventstring

Nombre del evento, p. ej. invoice.create

x-holded-webhook-datestring · ISO 8601

Momento del envío, p. ej. 2026-06-18T11:10:35Z

x-holded-webhook-signaturestring

Firma HMAC-SHA256 con prefijo sha256= (ver abajo)

x-holded-webhook-idstring

Identificador único del evento; úsalo como clave de idempotencia

x-holded-webhook-account-idstring

Identificador de la cuenta de Holded que origina el evento

x-holded-webhook-versionstring

Versión del sistema de webhooks (p. ej. v1)

Eventos disponibles

Los webhooks están disponibles para los siguientes grupos de eventos. Haz clic en un grupo para ver sus eventos y detalles del payload.

Verificar webhooks

Cada petición de webhook incluye una cabecera de firma (x-holded-webhook-signature) que deberías verificar para confirmar que la petición proviene de Holded. La firma es un resumen hexadecimal HMAC-SHA256 del cuerpo en bruto de la petición, firmado con tu secreto de webhook y con el prefijo sha256=.

javascript
const crypto = require('crypto');

// Use the raw request body, not the parsed JSON object
app.post('/holded-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const secret = process.env.HOLDED_WEBHOOK_SECRET; // whsec_...

  // The header arrives with a "sha256=" prefix; strip it before comparing
  const received = (req.header('x-holded-webhook-signature') || '').replace(/^sha256=/, '');

  const expected = crypto.createHmac('sha256', secret).update(req.body).digest('hex');

  const valid = received.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
  if (!valid) return res.status(401).send('Invalid signature');

  const event = req.header('x-holded-webhook-event');
  const data = JSON.parse(req.body.toString('utf8'));

  // ... process the event and acknowledge
  res.sendStatus(200);
});

Respuesta esperada

Tu endpoint debe devolver cualquier código de estado 2xx para confirmar la recepción. Si no recibimos una respuesta 2xx, reintentaremos la entrega con backoff exponencial.