Webhooks
Recibe notificaciones en tiempo real cuando la DIAN procesa tus documentos.
Crear un webhook
Registra una URL donde recibirás eventos POST con el resultado de tus documentos.
curl -X POST https://api.mercalo.co/v1/webhooks \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://mi-app.com/api/webhooks/mercalo",
"events": [
"invoice.accepted",
"invoice.rejected",
"credit_note.accepted"
],
"secret": "whsec_mi_secreto_seguro"
}'Eventos disponibles
| Evento | Descripción |
|---|---|
invoice.accepted | Factura aprobada por la DIAN |
invoice.rejected | Factura rechazada por la DIAN |
credit_note.accepted | Nota crédito aceptada |
credit_note.rejected | Nota crédito rechazada |
debit_note.accepted | Nota débito aceptada |
debit_note.rejected | Nota débito rechazada |
payroll.accepted | Nómina aceptada |
payroll.rejected | Nómina rechazada |
support_document.accepted | Doc. soporte aceptado |
Payload de ejemplo
Cada webhook envía un POST con el siguiente formato JSON:
{
"id": "evt_abc123",
"type": "invoice.accepted",
"createdAt": "2026-03-12T10:30:05Z",
"data": {
"id": "inv_abc123",
"cufe": "a1b2c3d4...",
"status": "ACCEPTED",
"companyId": "uuid-empresa",
"total": 1785000
}
}Verificar firma
Cada request incluye el header X-Mercalo-Signature con un HMAC-SHA256. Siempre verifica la firma antes de procesar.
import crypto from 'crypto';
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// En tu handler
app.post('/api/webhooks/mercalo', (req, res) => {
const signature = req.headers['x-mercalo-signature'];
if (!verifyWebhookSignature(req.rawBody, signature, 'whsec_xxx')) {
return res.status(401).send('Invalid signature');
}
// Procesar evento...
res.status(200).send('OK');
});Reintentos
Si tu endpoint no responde con 2xx en 30 segundos, reintentamos automáticamente:
- • 1er reintento: 1 minuto después
- • 2do reintento: 5 minutos después
- • 3er reintento: 30 minutos después
- • 4to reintento: 2 horas después
- • 5to reintento: 24 horas después
Después de 5 intentos fallidos, el webhook se desactiva y recibes un email de alerta.