Overview
Receive real-time notifications in your application when events happen in BeeL.
Webhooks let your application receive HTTP notifications the moment something happens in BeeL. — no polling required. When an event occurs (e.g. AEAT processes a VeriFactu submission), BeeL. sends an HTTP POST to the URL you registered with a signed JSON payload.
Developer Plan exclusive: Webhooks are available only with the Developer Plan. See Pricing for details.
Quick Start
1. Create a webhook subscription
curl -X POST "https://app.beel.es/api/v1/webhooks" \
-H "Authorization: Bearer beel_sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/beel",
"events": ["invoice.emitted", "invoice.email.sent", "invoice.cancelled", "verifactu.status.updated"]
}'The response contains a secret field — copy it now. It will not be shown again.
{
"success": true,
"data": {
"id": "3f7a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"url": "https://yourapp.com/webhooks/beel",
"events": ["invoice.emitted", "invoice.email.sent", "invoice.cancelled", "verifactu.status.updated"],
"active": true,
"secret": "whsec_a3f5b2e1c9d8f7e6b5a4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2",
"created_at": "2026-03-08T10:00:00Z"
}
}Store the secret securely! It's only shown once and required to verify webhook signatures.
2. Handle incoming requests
Your endpoint must:
- Accept
POSTrequests withContent-Type: application/json - Verify the signature using the
BeeL-Signatureheader - Return
HTTP 2xxwithin 10 seconds
// Express.js example
app.post('/webhooks/beel', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['beel-signature'];
if (!verifySignature(req.body, signature, process.env.BEEL_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
switch (event.type) {
case 'invoice.emitted':
handleNewInvoice(event.data);
break;
case 'invoice.email.sent':
handleEmailSent(event.data);
break;
case 'invoice.cancelled':
handleCancellation(event.data);
break;
case 'verifactu.status.updated':
handleVeriFactuUpdate(event.data);
break;
}
res.status(200).send('OK');
});3. Test your endpoint
Use the Send test event button in the BeeL. dashboard (Developers → Webhooks → your webhook) to fire a synthetic payload to your endpoint immediately.
Don't have an endpoint yet? Use webhook.site to get a free temporary URL that captures and displays incoming requests. It's a great way to inspect webhook payloads and verify that events are being delivered correctly before building your handler.
Payload Structure
Every webhook event shares the same envelope:
{
"id": "3f7a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"type": "verifactu.status.updated",
"created_at": "2026-03-07T16:20:26Z",
"api_version": "2025-01",
"livemode": true,
"test": null,
"data": { ... }
}| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique event ID. Stays the same across all retry attempts. |
type | string | Event type identifier (e.g. invoice.emitted). |
created_at | string (ISO 8601) | When the event was generated. |
api_version | string | API version used when the event was created (2025-01). |
livemode | boolean | false for Sandbox API keys. |
test | boolean? | true only for test deliveries triggered from the dashboard. |
data | object | Event-specific payload. See Events. |
Limits
| Parameter | Value |
|---|---|
| Max subscriptions per account | 10 |
| Max active subscriptions | 10 |
| Required URL scheme | https:// |
| Timeout per delivery attempt | 10 seconds |
| Max delivery attempts | 5 (1 original + 4 retries) |
| Delivery log history | Last 50 per subscription |
Headers Sent on Every Delivery
| Header | Description |
|---|---|
Content-Type | application/json |
BeeL-Signature | HMAC-SHA256 signature — see Signatures |
BeeL-Event | Event type (e.g. invoice.emitted) |
BeeL-Event-Id | UUID identifying this logical event. Identical across all retry attempts. Matches the id field in the payload. |
BeeL-Delivery-Id | UUID unique to this specific delivery attempt. Matches the delivery log id in the dashboard. |
Idempotency-Key | Same value as BeeL-Event-Id — for automatic deduplication by frameworks |
Using Official SDKs (Coming Soon)
Our official SDKs will include built-in webhook verification:
Node.js
import { WebhookVerifier } from '@beel_es/sdk';
const verifier = new WebhookVerifier(process.env.BEEL_WEBHOOK_SECRET);
app.post('/webhooks/beel', express.raw({ type: 'application/json' }), (req, res) => {
try {
const event = verifier.verify(
req.body.toString('utf8'),
req.headers['beel-signature']
);
// Event is verified and typed
if (event.type === 'verifactu.status.updated') {
console.log('Invoice:', event.data.invoice_number);
console.log('Status:', event.data.new_status);
}
res.status(200).send('OK');
} catch (error) {
res.status(400).send('Invalid signature');
}
});Java
import es.beel.sdk.webhook.WebhookVerifier;
WebhookVerifier verifier = new WebhookVerifier(System.getenv("BEEL_WEBHOOK_SECRET"));
@PostMapping("/webhooks/beel")
public ResponseEntity<String> handleWebhook(
@RequestBody String rawBody,
@RequestHeader("BeeL-Signature") String signature
) {
try {
var event = verifier.verify(rawBody, signature);
// Event is verified
return ResponseEntity.ok("OK");
} catch (WebhookVerificationException e) {
return ResponseEntity.status(400).body("Invalid signature");
}
}See the SDKs documentation for more details.
What's Next
- Events — Available event types and their data payloads
- Signatures — Verify that requests come from BeeL.
- Retries — How failed deliveries are retried
- Deduplication — Safely handle duplicate deliveries
Questions? Email us at it@beel.es.