Outbound webhooks
Abaco can notify your system when business events occur (documents, products, partners, payments). Configure the URL under Settings → Integrations → Webhooks; Abaco sends a HMAC-SHA256 signed POST.
The payload is compact: use your API key to hydrate details (GET /documents/:id, etc.).
Setup
- Sign in to abaco.
- Go to Settings → Integrations → Webhooks.
- Create a webhook with a name, HTTPS URL, and subscribed events.
- Save the signing secret (shown once). Use it to verify
X-Abaco-Signature.
In non-production environments, http:// URLs are allowed for local testing.
Events
| Event | When |
|---|---|
document.created | Document created |
document.confirmed | Document confirmed (or auto-confirmed on create) |
document.dte_accepted | El Salvador DTE accepted by Hacienda |
document.cancelled | Document cancelled |
product.created / product.updated | Product created or updated |
business_partner.created / business_partner.updated | Business partner created or updated |
payment.created / payment.confirmed | Payment registered or confirmed |
webhook.test | Only via Test in the UI |
Payload
json
{
"event": "document.created",
"companyId": 42,
"resourceType": "document",
"resourceId": 1001,
"occurredAt": "2026-09-24T18:00:00.000Z",
"data": {
"IdFactura": 1001,
"type": "01",
"number": "00000123",
"total": 150.5,
"businessPartnerId": 77,
"isConfirmed": false,
"codigoGeneracion": null
}
}For documents, data.IdFactura is the same as Document.id / resourceId.
Headers
| Header | Description |
|---|---|
Content-Type | application/json |
User-Agent | Abaco-Webhooks/1.0 |
X-Abaco-Event | Event name |
X-Abaco-Delivery-Id | Delivery attempt id |
X-Abaco-Signature | sha256=<hex> HMAC of the exact body |
Verify the signature
Compute HMAC-SHA256 of the raw body (UTF-8 bytes of the JSON received) with the signing secret and compare to the value after sha256= in X-Abaco-Signature (constant-time compare).
js
const crypto = require('crypto');
function verifyAbacoSignature(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(String(signatureHeader || ''));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Delivery and retries
- Timeout: 10 seconds.
- Success: HTTP 2xx.
- Retries: up to 3 with exponential backoff (BullMQ).
- View history under Deliveries in the UI.
Security
- Always use HTTPS in production.
- Treat the secret like a password; rotate if leaked.
- Respond quickly (2xx) and process asynchronously if work is heavy.
- Idempotency: use
X-Abaco-Delivery-Idor(event, resourceId, occurredAt).