Factuarea APIDevelopers

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} y GET /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 — siempre event.
  • 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 para invoice.paid). null para eventos sin agregado rellenado. Distinto de id, 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; null solo para eventos antiguos emitidos antes de sellar las versiones.
  • livemodetrue para eventos generados en producción (clave live, fact_live_); false para eventos generados en modo de prueba (empresa sandbox, clave fact_test_). Los eventos de modo de prueba se registran y se pueden consultar vía GET /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 siempre livemode: 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ún reversal_reason_text, que es una etiqueta en español para personas.
  • data.reversal.origingateway cuando fue la pasarela de pago la que informó de la devolución, disputa o retrocesión (ya hubo movimiento en el banco); manual cuando 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=50

Filtros 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 });
}

En esta página

¿Te echamos una mano?Contactar con soporte