Eventos
Objetos event de solo lectura con un id opaco. Consulta histórica vía la API y entrega por webhook.
Cada evento publicado en Factuarea se persiste como un objeto
event de solo lectura con un id opaco (un UUID v7, p. ej.
01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d), coherente con el id de
cualquier otro recurso v1. Esto te permite:
- Consultarlo vía API:
GET /v1/events/{id}yGET /v1/events?type=invoice.paid. - Entregarlo a los webhook endpoints suscritos (el mismo objeto se envía en el body de la entrega — ver Webhooks).
- Reenviar una entrega desde el dashboard
(
Developers > Webhooks > Deliveries).
Forma del payload
Cada evento comparte esta estructura:
{
"id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d",
"object": "event",
"type": "invoice.paid",
"aggregate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03",
"api_version": "2026-05-22",
"livemode": true,
"data": {
"invoice": { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03" }
},
"created": "2026-05-15T10:23:18Z"
}Campos:
id— identificador opaco del evento (UUID v7). Úsalo como la idempotency key en tu lado.object— siempreevent.type— nombre del evento como<category>.<action>(p. ej.invoice.paid,quote.approved).aggregate_id— UUID v7 del recurso que produjo el evento (p. ej. la factura parainvoice.paid).nullpara eventos sin agregado rellenado. Distinto deid, que identifica el propio evento.api_version— versión por fecha bajo la que se serializó el payload, sellada en la emisión. Siempre presente en los eventos emitidos hoy;nullsolo para eventos antiguos emitidos antes de sellar las versiones.livemode—truepara eventos generados en producción (clave live,fact_live_);falsepara eventos generados en modo de prueba (empresa sandbox, clavefact_test_). Los eventos de modo de prueba se registran y se pueden consultar víaGET /v1/events, pero no se entregan a los webhook endpoints (ver Modo de prueba y sandbox), así que cualquier evento que tu endpoint reciba realmente es siemprelivemode: true.data— una referencia ligera al recurso afectado, indexada por su tipo — p. ej.{ "invoice": { "id": "..." } }. Obtén el recurso desde su propio endpoint para conseguir la representación completa y actual.created— timestamp ISO 8601 UTC de cuándo se creó el evento.
Idempotencia
Cada evento tiene un id único. Los webhooks reentregan el mismo id al
mismo endpoint en cada reintento. En tu handler:
event_id = event['id']
if seen_in_db(event_id):
return '', 200
process(event)
mark_seen_in_db(event_id)Catálogo de eventos
El catálogo completo y autoritativo de tipos de evento suscribibles lo devuelve
GET /v1/event-catalog. Cada entrada lleva un name, una category, una
description legible y un status (available o
coming_soon):
curl https://api.factuarea.com/v1/event-catalog \
-H "Authorization: Bearer $FACTUAREA_API_KEY"{
"data": [
{
"name": "invoice.paid",
"category": "invoice",
"description": "Factura pagada",
"status": "available"
}
],
"has_more": false,
"next_cursor": null
}Tipos de evento representativos por categoría (consulta el catálogo para la lista completa y actualizada):
Facturas
invoice.created, invoice.auto_created,
invoice.corrective_auto_created, invoice.subscription_auto_created,
invoice.updated, invoice.sent, invoice.paid,
invoice.cancelled, invoice.annulled, invoice.overdue,
invoice.deleted, invoice.number_assigned, invoice.rectified,
invoice.email_sent, invoice.email_failed,
invoice.payment_reminder_sent, invoice.simplified_created,
invoice.simplified_substituted, invoice.substituted_by_complete,
invoice.verifactu_submitted, invoice.verifactu_failed,
invoice.metadata_changed.
invoice.auto_created / invoice.corrective_auto_created /
invoice.subscription_auto_created los emiten los flujos de
auto-facturación de pasarelas de pago cuando un
cobro, una devolución o un ciclo de suscripción generan una factura de forma
automática.
Presupuestos
quote.created, quote.updated, quote.deleted, quote.approved,
quote.rejected, quote.converted, quote.expired,
quote.marked_as_pending, quote.cancelled, quote.number_assigned,
quote.metadata_changed, quote.email_sent, quote.email_failed.
Facturas proforma
proforma.created, proforma.updated, proforma.deleted,
proforma.accepted, proforma.rejected, proforma.cancelled,
proforma.expired, proforma.converted_to_invoice,
proforma.number_assigned, proforma.metadata_changed,
proforma.email_sent, proforma.email_failed.
Albaranes
delivery_note.created, delivery_note.updated,
delivery_note.status_changed, delivery_note.signed,
delivery_note.converted, delivery_note.email_sent,
delivery_note.email_failed.
Facturas de compra
purchase_invoice.created, purchase_invoice.updated,
purchase_invoice.paid, purchase_invoice.payment_registered,
purchase_invoice.cancelled, purchase_invoice.metadata_changed.
Facturas recurrentes
recurring_invoice.created, recurring_invoice.activated,
recurring_invoice.paused, recurring_invoice.updated,
recurring_invoice.deleted, recurring_invoice.completed,
recurring_invoice.executed, recurring_invoice.failed,
recurring_invoice.cancelled, recurring_invoice.metadata_changed.
Clientes y productos
client.created, client.updated, client.deleted,
client.metadata_changed, product.created, product.updated.
Series e impuestos
series.created, series.updated, series.deleted,
series.archived, series.unarchived, series.marked_as_default,
series.demoted_from_default, series.number_consumed,
series.year_reset, series.month_reset, tax.metadata_changed,
tax.validity_changed, tax.external_reference_changed.
FacturaE (FACe)
facturae.face_submitted, facturae.face_status_changed,
facturae.face_cancellation_requested.
Pagos y pasarelas
payment.received, payment.reversed, payout.reconciled.
payment.received y payment.reversed son las dos mitades de un mismo
ciclo: el primero se dispara cuando se registra un pago contra una
factura, y el segundo cuando ese pago se anula y la factura vuelve al
circuito de cobro. Suscríbete a los dos — una factura que diste por
cobrada puede dejar de estarlo, y reaccionar solo a la primera mitad es
confiar en una cifra que ha caducado. Ver
payment.reversed más abajo.
payout.reconciled se dispara cuando un payout de Stripe se concilia con tu
extracto bancario (consulta Payouts y conciliación).
Automatizaciones
automation_rule.activated, automation_rule.paused,
automation_rule.auto_paused, automation_run.started,
automation_run.completed, automation_run.failed,
automation_run.step_dead_lettered.
El motor informa de su propio ciclo de vida. Los tres eventos
automation_rule.* llevan la regla en el cuerpo de entrega, bajo data.object:
activated cuando una regla entra en servicio y empieza a escuchar su
disparador, paused cuando la detiene una persona y auto_paused cuando la
detiene la plataforma tras una racha de ejecuciones fallidas.
Los cuatro eventos automation_run.* llevan la ejecución en el cuerpo de
entrega, bajo data.object: started cuando un disparador que ha casado supera
los límites del motor y la
ejecución se admite, completed cuando todos los pasos aplicaron su efecto,
failed cuando la ejecución terminó sin producir su efecto y no es
reprocesable, y step_dead_lettered cuando un paso concreto queda aparcado a
la espera de un relanzamiento manual. Como en el resto de eventos,
data.object es el snapshot tomado al emitir, no el estado actual del recurso.
Consulta la
referencia de la ejecución.
Dos de ellos llevan claves extra junto al snapshot.
automation_rule.auto_paused añade consecutive_failures, el número de
ejecuciones fallidas consecutivas que provocaron la pausa automática — la regla
la pausó la plataforma, y automation_rule.paused es su equivalente humano.
automation_run.step_dead_lettered añade step_index y discard_reason:
step_index es la posición del paso aparcado empezando en cero, y se resuelve
contra el propio snapshot (el elemento de data.object.steps cuyo step_index
coincide, porque un paso no es un recurso público por sí mismo), y
discard_reason es un valor tipado de un catálogo cerrado, nunca texto libre.
En la práctica siempre es un motivo de descarte relanzable: un resultado que no
admite reproceso cierra la ejecución como failed en vez de aparcar el paso.
Estos siete nombres están en el mismo catálogo cerrado que los demás eventos,
así que también son disparadores válidos de reglas: una automatización puede
reaccionar a automation_run.failed igual que reacciona a invoice.paid, y
ninguna lista de exclusión los oculta del catálogo de disparadores. Como el
resto del motor, requieren el módulo automations.
Encadenarlos está acotado, no prohibido. Cada salto «acción → evento → regla»
consume el tope de profundidad de encadenamiento del motor —tres saltos por
defecto—, así que una regla que reacciona a automation_run.failed y vuelve a
fallar no puede repetirse sin fin: agotado el tope, la ejecución no llega a
ejecutarse y queda registrada como blocked. Un evento que produce una persona o una
integración entra con profundidad cero, así que solo consume ese presupuesto lo
que provocó una automatización.
Ejemplos de payload
invoice.paid
{
"id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d",
"object": "event",
"type": "invoice.paid",
"aggregate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03",
"api_version": "2026-05-22",
"livemode": true,
"data": {
"invoice": { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03" }
},
"created": "2026-05-15T11:42:08Z"
}client.updated
{
"id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a1a",
"object": "event",
"type": "client.updated",
"aggregate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a2b",
"api_version": "2026-05-22",
"livemode": true,
"data": {
"client": { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a2b" }
},
"created": "2026-05-15T11:50:12Z"
}quote.converted
{
"id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a3c",
"object": "event",
"type": "quote.converted",
"aggregate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a4d",
"api_version": "2026-05-22",
"livemode": true,
"data": {
"quote": { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a4d" }
},
"created": "2026-05-15T12:01:55Z"
}El evento solo lleva una referencia ligera al recurso afectado. Obtén
el recurso desde su propio endpoint (p. ej. GET /v1/quotes/{id}) para leer
la factura convertida a la que enlaza.
payment.reversed
Se emite cuando se anula un pago registrado contra una factura. Hasta que
existió, una integración que había oído payment.received no tenía
forma de enterarse de que ese mismo pago se había deshecho.
El cuerpo de entrega de este evento lleva el recurso afectado completo
bajo data.object — el pago tal y como lo serializa la API v1, ya marcado
como anulado — más un bloque data.reversal que describe la operación en
sí:
{
"id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a5e",
"type": "payment.reversed",
"api_version": "2026-05-22",
"created": 1780646100,
"livemode": true,
"test": false,
"correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a6f",
"data": {
"type": "payment.reversed",
"object": {
"id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b",
"object": "payment",
"invoice_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
"amount": 500.00,
"payment_date": "2026-05-20",
"payment_method": "direct_debit",
"payment_method_text": "Domiciliación bancaria",
"reference": "TRF-2026-0042",
"notes": null,
"is_reversed": true,
"reversed_at": "2026-06-02T08:15:00Z",
"reversal_reason": "direct_debit_return",
"reversal_reason_text": "Devolución de adeudo SEPA",
"reversal_note": "Devuelto por el banco con motivo MD01.",
"created_at": "2026-05-20T10:30:00Z",
"updated_at": "2026-06-02T08:15:00Z"
},
"reversal": {
"reason": "direct_debit_return",
"origin": "gateway"
}
}
}data.reversal.reason— uno de los cinco valores del catálogo cerrado:direct_debit_return,card_dispute,misapplied_payment,bounced_effect,recording_error. Ramifica según este campo, nunca segúnreversal_reason_text, que es una etiqueta en español para personas.data.reversal.origin—gatewaycuando fue la pasarela de pago la que informó de la devolución, disputa o retrocesión (ya hubo movimiento en el banco);manualcuando lo registró una persona. Útil para decidir si reclamar al cliente o esperar al fichero bancario.
Qué hacer cuando llega: la factura ha vuelto al circuito de cobro
(sent, u overdue si su vencimiento ya pasó) y su paid_amount ya no
incluye esa entrada, así que refresca lo que tuvieras cacheado sobre esa
factura. No emitas una factura rectificativa como reacción — una
anulación no es una minoración de ingresos. Ver
¿Anulación o rectificativa?.
Suscribirse a eventos
Vía API:
curl -X POST https://api.factuarea.com/v1/webhook_endpoints \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.mycompany.com/factuarea/webhook",
"enabled_events": ["invoice.paid", "quote.approved"]
}'Para suscribirte a todos los eventos (no recomendado en producción salvo para dashboards internos):
{ "enabled_events": ["*"] }Para suscribirte a familias enteras (todos los invoice.*):
{ "enabled_events": ["invoice.*", "quote.*"] }Listar eventos vía API
GET /v1/events?type=invoice.paid&limit=50Filtros disponibles: type, type[in], created[gte], created[lte],
created[gt], created[lt]. Paginación por cursor estándar
(limit, starting_after, ending_before) — ver
Paginación.
Eventos de pedidos
Suscríbete a order.invoiced y order.refunded para recibir snapshots completos de la factura o rectificativa en data.object. Ambos incluyen data.store.uuid, data.store.provider y data.order.external_id; las devoluciones añaden data.refund.scope y data.refund.reason_code. Usa el id del evento para deduplicar entregas y correlation_id para relacionar operaciones. Consulta el procesamiento de tiendas y el trigger de n8n.
if (event.type === "order.invoiced" || event.type === "order.refunded") {
const invoice = event.data.object;
const storeId = event.data.store.uuid;
const orderId = event.data.order.external_id;
await saveOrderDocument({ eventId: event.id, storeId, orderId, invoice });
}