Events
All webhook event types and their payload schemas.
BeeL. sends webhook events when key things happen in your account. Each event has a type field that identifies what occurred, and a data object with event-specific details.
All field names use snake_case — both in the envelope and in data payloads.
Envelope Structure
Every webhook delivery follows the same envelope format:
{
"id": "3f7a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"type": "invoice.emitted",
"created_at": "2026-03-17T22:30:20.085Z",
"api_version": "2025-01",
"livemode": true,
"data": { ... }
}| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique identifier for this webhook event. |
type | string | Event type (see below). |
created_at | string (ISO 8601) | Timestamp when the event was created. |
api_version | string | API version used to generate the payload. |
livemode | boolean | true for production, false for sandbox. |
data | object | Event-specific payload (see below). |
Test payloads include an additional "test": true field and always have "livemode": false.
Available Events
| Event type | Description |
|---|---|
invoice.emitted | An invoice was emitted (created and finalized) |
invoice.email.sent | An invoice was successfully sent by email |
invoice.cancelled | An invoice was cancelled (anulada) |
verifactu.status.updated | AEAT processed a VeriFactu registration — accepted or rejected |
invoice.emitted
Fired when an invoice is emitted (created and finalized).
Payload
{
"id": "3f7a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"type": "invoice.emitted",
"created_at": "2026-03-17T22:30:20.085Z",
"api_version": "2025-01",
"livemode": true,
"data": {
"invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "A-2026-0026",
"customer_email": "john@example.com",
"customer_name": "John Doe"
}
}data fields
| Field | Type | Description |
|---|---|---|
invoice_id | string (UUID) | The emitted invoice. |
invoice_number | string | Human-readable invoice number (e.g. A-2026-0026). |
customer_email | string | Customer's email address. |
customer_name | string | Customer's name. |
invoice.email.sent
Fired when an invoice has been successfully sent by email.
Payload
{
"id": "4a8b2c3d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"type": "invoice.email.sent",
"created_at": "2026-03-17T22:30:20.085Z",
"api_version": "2025-01",
"livemode": true,
"data": {
"invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "A-2026-0026",
"all_recipients": ["john@example.com", "accounting@example.com"],
"sent_at": "2026-03-17T22:30:20.050725Z"
}
}data fields
| Field | Type | Description |
|---|---|---|
invoice_id | string (UUID) | The invoice that was sent. |
invoice_number | string | Human-readable invoice number. |
all_recipients | string[] | All email addresses the invoice was sent to. |
sent_at | string (ISO 8601) | Timestamp when the email was sent. |
invoice.cancelled
Fired when an invoice is cancelled (anulada).
Payload
{
"id": "5b9c3d4e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"type": "invoice.cancelled",
"created_at": "2026-03-17T22:31:15.000Z",
"api_version": "2025-01",
"livemode": true,
"data": {
"invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "A-2026-0026",
"cancellation_reason": "Error en los datos del cliente"
}
}data fields
| Field | Type | Description |
|---|---|---|
invoice_id | string (UUID) | The cancelled invoice. |
invoice_number | string | Human-readable invoice number. |
cancellation_reason | string | Reason provided for the cancellation. |
verifactu.status.updated
Fired when the VeriFactu registration status changes. This includes:
- Initial submission (status:
PENDING) - Final acceptance by AEAT (status:
ACCEPTED) - Rejection by AEAT (status:
REJECTED)
Payload
{
"id": "6c0d4e5f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"type": "verifactu.status.updated",
"created_at": "2026-03-07T16:20:26Z",
"api_version": "2025-01",
"livemode": true,
"data": {
"invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "2025-001",
"verifactu_registration_id": "660e8400-e29b-41d4-a716-446655440001",
"previous_status": "PENDING",
"new_status": "ACCEPTED",
"qr_url": "https://sede.agenciatributaria.gob.es/Sede/verifactu?id=ABC123XYZ",
"qr_base64": "iVBORw0KGgoAAAANSUhEUgAAAMg...",
"invoice_hash": "B11F3A015173AD99075E2720F61E2DE1FF08CBFEDD85C6F73C77AD835301B2A3",
"error_code": null,
"error_message": null
}
}data fields
| Field | Type | Description |
|---|---|---|
invoice_id | string (UUID) | The invoice that was registered with VeriFactu. |
invoice_number | string | null | Human-readable invoice number (e.g. 2025-001). |
verifactu_registration_id | string (UUID) | The VeriFactu registration record in BeeL. |
previous_status | string | null | Status before this update. null on first submission. |
new_status | string | Status after this update. |
qr_url | string | null | AEAT verification URL. Available from PENDING status onwards. |
qr_base64 | string | null | QR code as base64-encoded PNG. Embed in invoice PDFs. |
invoice_hash | string | null | SHA-256 hash of the VeriFactu record. Present only when ACCEPTED. |
error_code | string | null | AEAT error code when new_status is REJECTED or ACCEPTED_WITH_ERRORS. |
error_message | string | null | Human-readable error description from AEAT. |
Null fields are omitted from the JSON payload.
Status values
| Status | Meaning |
|---|---|
PENDING | BeeL. has submitted to AEAT and is waiting for a response. |
ACCEPTED | AEAT accepted the registration. qr_url, qr_base64, and invoice_hash are populated. |
ACCEPTED_WITH_ERRORS | AEAT accepted with warnings. Check error_code and error_message. |
REJECTED | AEAT rejected the registration. Check error_code and error_message. |
AEAT_SERVER_ERROR | AEAT's server failed. BeeL. will retry automatically. |
Accepted example
{
"data": {
"invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "2025-001",
"verifactu_registration_id": "660e8400-e29b-41d4-a716-446655440001",
"previous_status": "PENDING",
"new_status": "ACCEPTED",
"qr_url": "https://sede.agenciatributaria.gob.es/Sede/verifactu?id=ABC123XYZ",
"qr_base64": "iVBORw0KGgoAAAANSUhEUgAAAMg...",
"invoice_hash": "B11F3A015173AD99075E2720F61E2DE1FF08CBFEDD85C6F73C77AD835301B2A3"
}
}Rejected example
{
"data": {
"invoice_id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "2025-001",
"verifactu_registration_id": "660e8400-e29b-41d4-a716-446655440001",
"previous_status": "PENDING",
"new_status": "REJECTED",
"error_code": "1105",
"error_message": "NIF del emisor no registrado en VeriFactu"
}
}Headers
Every webhook delivery includes these HTTP headers:
| Header | Description |
|---|---|
Content-Type | application/json |
BeeL-Event | Event type (e.g. invoice.emitted) |
BeeL-Event-Id | Unique event ID (same as id in payload) |
BeeL-Delivery-Id | Unique delivery attempt ID |
BeeL-Signature | HMAC-SHA256 signature: t=timestamp,v1=hash |
Idempotency-Key | Same as event ID, for idempotent processing |
Environment Isolation
Webhook subscriptions are isolated per environment:
- Production subscriptions only receive events from production invoices (
livemode: true) - Sandbox subscriptions only receive events from sandbox invoices (
livemode: false)
Test Events
When you click Send test event from the dashboard, BeeL. fires a synthetic payload with the same structure but with an extra field:
{
"id": "...",
"type": "verifactu.status.updated",
"livemode": false,
"test": true,
"data": {
"message": "This is a test webhook from BeeL.. Your endpoint is configured correctly."
}
}Test events are not retried if your endpoint fails to respond.