Webhooks
Webhooks
Webhooks allow you to receive real-time notifications about events in your e-invoice.be account. This guide explains how to set up and use webhooks effectively.
Overview
Webhooks are HTTP callbacks that notify your application when specific events occur, such as:
- Document received
- Document sent
- Document send failed
- Document receive failed
Setting Up Webhooks
1. Create a Webhook
curl -X POST "https://api.e-invoice.be/api/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.com/webhook",
"events": ["document.received", "document.sent", "document.sent.failed"],
"enabled": true
}'2. Configure Your Endpoint
Your webhook endpoint should:
- Accept POST requests
- Return a 200 OK response quickly
- Handle retries gracefully
- Verify webhook signatures
Webhook Security
Signature Verification
Webhook requests are signed using HMAC-SHA256 to ensure authenticity and integrity. The signature is included in the X-Signature header of each request.
How the Signature is Computed
- The payload is sorted by keys and converted to a JSON string
- The JSON string is encoded to UTF-8 bytes
- An HMAC is created using your webhook secret and the SHA-256 algorithm
- The resulting signature is formatted as
sha256={hexadecimal_signature}
Example
Given this webhook payload:
{
"document": {
"id": "doc-1",
"name": "test.xml",
"type": "application/xml",
"size": 100,
"url": "https://example.com/test.xml"
}
}This translates to the string:
{"document": {"id": "doc-1", "name": "test.xml", "size": 100, "type": "application/xml", "url": "https://example.com/test.xml"}}With the webhook secret of "secret", the signature would be:
sha256=6722b498bf28ce7ca5a6f21c0fca9166e24dea480978b276725ff46e503dd70fVerifying the Signature
To verify the signature in your webhook handler:
- Extract the signature from the
X-Signatureheader - Compute the HMAC-SHA256 of the request body using your webhook secret
- Compare the computed signature with the one in the header
If the signatures match, the webhook request is authentic and hasn’t been tampered with.
Best Practices
Handle Retries
- Webhooks are automatically retried up to 3 times with exponential backoff (2s, 4s, 8s)
- Implement idempotency to handle duplicate events
- Return 200 OK quickly, process asynchronously
- All 2xx status codes are considered successful
Security
- Always verify webhook signatures
- Use HTTPS for your webhook endpoint
- Keep your webhook secret secure
- The signature is computed on the entire JSON payload
Error Handling
- Log failed webhook deliveries
- Monitor webhook success rates
- Set up alerts for repeated failures
- Failed webhooks are logged with details about the error
Testing
- Use the webhook testing tool in the dashboard (
POST /webhooks/{webhook_id}/test) - Test with different event types
- Verify signature verification is working correctly
- Use the webhook testing tool in the dashboard (
Performance
- Webhook requests timeout after 10 seconds
- Respond quickly (< 5 seconds recommended)
- Process complex logic asynchronously after responding
- Use a queue system for handling webhook events internally
Available Events
The following webhook events are supported:
document.received: A new document is successfully received via PEPPOL or other channelsdocument.received.failed: A document failed to be received/processeddocument.sent: A document is successfully sent via PEPPOL or other channelsdocument.sent.failed: A document failed to send (e.g., validation error, network error, PEPPOL transmission failure)
Webhook Payload
When a webhook is triggered, it sends a POST request to your configured URL with the following structure:
{
"id": "evt_3k8d9f2h4j6m8n0p",
"tenant_id": "ten_5x7y9z1a3b5c7d9e",
"created_at": 1729468923,
"type": "document.sent",
"data": {
"document_id": "doc_2f4h6j8k0m2n4p6q"
},
"text": "⚡️ New webhook event: document.sent\n\n{\n \"document_id\": \"doc_2f4h6j8k0m2n4p6q\"\n}"
}Note: Currently, the data object only contains the document_id. You can use this ID to fetch additional document details via the API (GET /api/documents/{document_id}).
Headers
Each webhook request includes the following headers:
X-Signature: HMAC-SHA256 signature for verifying authenticity (format:sha256=...)X-Event-Type: The event type (e.g.,document.sent)Content-Type:application/jsonUser-Agent:e-invoice-be-webhook-service
Event Data Structure
The data object contains event-specific information:
- For all document events (
document.received,document.sent,document.sent.failed,document.received.failed):{ "document_id": "doc_2f4h6j8k0m2n4p6q" }
The document_id can be used to retrieve full document details:
curl -X GET "https://api.e-invoice.be/api/documents/{document_id}" \
-H "Authorization: Bearer YOUR_API_KEY"Complete Example Requests
Success Event Example
Here’s what a successful document.sent webhook HTTP request looks like:
POST /webhook HTTP/1.1
Host: your-domain.com
Content-Type: application/json
User-Agent: e-invoice-be-webhook-service
X-Signature: sha256=a3f8d9e2c1b5a7f9e3d2c1b5a7f9e3d2c1b5a7f9e3d2c1b5a7f9e3d2c1b5
X-Event-Type: document.sent
{
"id": "evt_3k8d9f2h4j6m8n0p",
"tenant_id": "ten_5x7y9z1a3b5c7d9e",
"created_at": 1729468923,
"type": "document.sent",
"data": {
"document_id": "doc_2f4h6j8k0m2n4p6q"
},
"text": "⚡️ New webhook event: document.sent\n\n{\n \"document_id\": \"doc_2f4h6j8k0m2n4p6q\"\n}"
}Failure Event Example
Here’s what a failed document.sent.failed webhook HTTP request looks like:
POST /webhook HTTP/1.1
Host: your-domain.com
Content-Type: application/json
User-Agent: e-invoice-be-webhook-service
X-Signature: sha256=7e9c3a1d5f8b2e6a4c9d7f3b1e8a6c2d9f7e3a1c5b8d6f2a4e9c7b3d1f8a5c
X-Event-Type: document.sent.failed
{
"id": "evt_9m2p4r6t8v0x2z4b",
"tenant_id": "ten_5x7y9z1a3b5c7d9e",
"created_at": 1729469845,
"type": "document.sent.failed",
"data": {
"document_id": "doc_8h3j5k7m9n1p3q5r"
},
"text": "⚡️ New webhook event: document.sent.failed\n\n{\n \"document_id\": \"doc_8h3j5k7m9n1p3q5r\"\n}"
}Note: For failure events, you’ll need to retrieve the document details via the API to understand what went wrong. The document state will typically be set to FAILED and may contain error information.
Webhook Management
List Webhooks
curl -X GET "https://api.e-invoice.be/api/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY"Update Webhook
curl -X PUT "https://api.e-invoice.be/api/webhooks/{webhook_id}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": false
}'Delete Webhook
curl -X DELETE "https://api.e-invoice.be/api/webhooks/{webhook_id}" \
-H "Authorization: Bearer YOUR_API_KEY"Test Webhook
Send a test event to verify your webhook is working correctly:
curl -X POST "https://api.e-invoice.be/api/webhooks/{webhook_id}/test" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_type": "document.sent",
"data": {
"document_id": "test_doc_123"
}
}'