Webhooks

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": { ... }
}
FieldTypeDescription
idstring (UUID)Unique identifier for this webhook event.
typestringEvent type (see below).
created_atstring (ISO 8601)Timestamp when the event was created.
api_versionstringAPI version used to generate the payload.
livemodebooleantrue for production, false for sandbox.
dataobjectEvent-specific payload (see below).

Test payloads include an additional "test": true field and always have "livemode": false.


Available Events

Event typeDescription
invoice.emittedAn invoice was emitted (created and finalized)
invoice.email.sentAn invoice was successfully sent by email
invoice.cancelledAn invoice was cancelled (anulada)
verifactu.status.updatedAEAT 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

FieldTypeDescription
invoice_idstring (UUID)The emitted invoice.
invoice_numberstringHuman-readable invoice number (e.g. A-2026-0026).
customer_emailstringCustomer's email address.
customer_namestringCustomer'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

FieldTypeDescription
invoice_idstring (UUID)The invoice that was sent.
invoice_numberstringHuman-readable invoice number.
all_recipientsstring[]All email addresses the invoice was sent to.
sent_atstring (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

FieldTypeDescription
invoice_idstring (UUID)The cancelled invoice.
invoice_numberstringHuman-readable invoice number.
cancellation_reasonstringReason 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

FieldTypeDescription
invoice_idstring (UUID)The invoice that was registered with VeriFactu.
invoice_numberstring | nullHuman-readable invoice number (e.g. 2025-001).
verifactu_registration_idstring (UUID)The VeriFactu registration record in BeeL.
previous_statusstring | nullStatus before this update. null on first submission.
new_statusstringStatus after this update.
qr_urlstring | nullAEAT verification URL. Available from PENDING status onwards.
qr_base64string | nullQR code as base64-encoded PNG. Embed in invoice PDFs.
invoice_hashstring | nullSHA-256 hash of the VeriFactu record. Present only when ACCEPTED.
error_codestring | nullAEAT error code when new_status is REJECTED or ACCEPTED_WITH_ERRORS.
error_messagestring | nullHuman-readable error description from AEAT.

Null fields are omitted from the JSON payload.

Status values

StatusMeaning
PENDINGBeeL. has submitted to AEAT and is waiting for a response.
ACCEPTEDAEAT accepted the registration. qr_url, qr_base64, and invoice_hash are populated.
ACCEPTED_WITH_ERRORSAEAT accepted with warnings. Check error_code and error_message.
REJECTEDAEAT rejected the registration. Check error_code and error_message.
AEAT_SERVER_ERRORAEAT'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:

HeaderDescription
Content-Typeapplication/json
BeeL-EventEvent type (e.g. invoice.emitted)
BeeL-Event-IdUnique event ID (same as id in payload)
BeeL-Delivery-IdUnique delivery attempt ID
BeeL-SignatureHMAC-SHA256 signature: t=timestamp,v1=hash
Idempotency-KeySame 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.