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/companies/{company}/events/{id} y GET /v1/companies/{company}/events?type=invoice.paid.
  • Entregarlo a los webhook endpoints suscritos, en un sobre firmado con el mismo id, type y data (ver Webhooks).
  • Reenviar una entrega desde el dashboard (Developers > Webhooks > Deliveries).

Forma del payload

GET /v1/companies/{company}/events/{id} devuelve el evento dentro de data. El evento tiene este aspecto, con la factura de data.object abreviada a seis de sus campos:

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d",
  "object": "event",
  "type": "invoice.paid",
  "aggregate_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a42",
  "correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a99",
  "api_version": "2026-09-23",
  "livemode": true,
  "test": false,
  "data": {
    "type": "invoice.paid",
    "object": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a42",
      "object": "invoice",
      "number": "FAC-2026-00042",
      "status": "paid",
      "total": "1210.00",
      "currency": "EUR"
    },
    "amount": "1210.00",
    "payment_date": "2026-03-20",
    "payment_method": "bank_transfer",
    "payment_reference": "TRF-2026-0042"
  },
  "created": 1774002600
}

Campos:

  • id — identificador opaco del evento (UUID v7). Úsalo para deduplicar 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.
  • correlation_id — UUID v7 que enlaza los eventos provocados por una misma operación, o null cuando no hay ninguno. La clave siempre está presente.
  • 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.
  • livemode — true 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/companies/{company}/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.
  • test — true para una entrega de prueba enviada con test-event, false para eventos reales. Es ortogonal a livemode.
  • data — { "type", "object" }. object es el snapshot completo del recurso afectado tal y como estaba cuando ocurrió el evento, idéntico a lo que devolvía un GET de ese recurso en ese momento. Está congelado: los cambios posteriores del recurso no reescriben los eventos pasados, así que obtén el recurso desde su propio endpoint cuando necesites su estado actual. Las claves propias del evento van junto a object, como amount y payment_date en invoice.paid.
  • created — timestamp Unix, en segundos, de cuándo se creó el evento.

Un webhook entrega el mismo evento en un sobre firmado: los mismos id, type, api_version, created, livemode, test, correlation_id y data, sin object ni aggregate_id. Consulta su body de la entrega.

Idempotencia

Cada evento tiene un id único. Los webhooks reentregan el mismo id al mismo endpoint en cada reintento, y un endpoint de cuenta que admite el mismo evento de un NIF lo recibe también con el mismo id. En tu handler, guarda los ids que hayas procesado y responde 2xx sin actuar si vuelves a ver uno. Deduplicar entregas de webhooks tiene la receta completa y cuánto tiempo conservar los ids.

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
}

Este es el catálogo de los eventos de un NIF. Los eventos account.* de la propia cuenta no están en él: consulta Eventos de cuenta.

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.issued, invoice.marked_sent, invoice.unsent, invoice.sent (deprecado), 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.

invoice.issued se emite cuando se emite una factura: número definitivo, registro VeriFactu y movimientos de stock. invoice.marked_sent se emite cuando llega al cliente (el servidor de correo aceptó su email de entrega o alguien la marcó a mano) e invoice.unsent cuando se borra esa marca. Un cobro nunca marca una factura como enviada. invoice.sent es un alias deprecado de invoice.issued, emitido en el mismo instante y con el mismo data.object; las integraciones nuevas deben suscribirse a invoice.issued, y la retirada del alias se anunciará con una fecha Sunset. Las reglas de automatización ya no aceptan invoice.sent como disparador.

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.

Documentos de control

transport_document.created, transport_document.updated, transport_document.issued, transport_document.modified, transport_document.closed, transport_document.reopened, transport_document.cancelled, transport_document.superseded, transport_document.email_sent, transport_document.email_failed.

Cada entrega lleva el recurso v1 transport_document completo en data.object. Se emiten sea cual sea el origen del cambio: la app, la REST API, MCP o el cierre automático diario. transport_document.updated se emite también cuando un borrador vuelve a copiar una parte cuyo contacto o datos de empresa cambiaron (consulta Documento de control (DeCA)). transport_document.closed distingue un cierre manual de uno automático con data.object.close_mode (manual o automatic). transport_document.email_sent (el servidor de correo aceptó el email) y transport_document.email_failed (no se pudo entregar) funcionan como los de los albaranes: junto a data.object, data lleva recipient_email (la primera dirección de to), las listas to, cc y bcc y la version del PDF adjunto; email_sent añade transport_document_number y email_failed añade error_message y error_class. Borrar un borrador no se publica como evento. El prefijo transport_document pertenece al módulo transport_documents. Consulta Documento de control (DeCA).

Gastos

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.

Los eventos tax.* se entregan para los impuestos propios de tu empresa. Los impuestos del catálogo de Factuarea no emiten eventos.

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.

Tareas y proyectos

El módulo de tareas publica 21 eventos en cuatro familias. Viven en el mismo catálogo cerrado que cualquier otro evento, así que un endpoint de webhook puede suscribirse a ellos (o a "*"), y son disparadores de automatización válidos para las empresas con el módulo tasks: una empresa que no lo tiene ni los ve en el catálogo de disparadores ni puede guardar una regla que use uno.

FamiliaEventos
Tareastask.created, task.updated, task.deleted, task.status_changed, task.completed, task.assigned, task.unassigned, task.moved, task.due_soon, task.overdue
Comentariostask_comment.created, task_comment.updated, task_comment.deleted
Tiempo imputadotask_time_entry.created, task_time_entry.updated, task_time_entry.deleted, task_time_entry.invoiced
Proyectosproject.created, project.updated, project.archived, project.deleted

Cada evento lo emite la operación que lo causa, desde cualquier superficie —la app, la API, MCP, el portal del empleado, una automatización, una integración o un proceso programado—, y se entrega una vez por hecho, aunque el evento se reentregue internamente.

EventoSe emite cuandoClaves extra junto a object
task.createdSe crea una tarea, también al duplicarla, importarla o por una automatización—
task.updatedCambian el título, la descripción, la prioridad, start_on o due_onchanged_fields
task.deletedSe borra una tarea, también en bloqueproject_id
task.status_changedCambia la columna o el estado virtual (planned, active, archived)previous_status, previous_column_id
task.completedLa tarea entra en una columna final—
task.assignedLa tarea recibe una persona asignada o la cambiaprevious_assignee_id
task.unassignedLa tarea se queda sin persona asignada—
task.movedLa tarea pasa a otro proyectofrom_project_id
task.due_soonLa tarea entra en su ventana de aviso de vencimiento, una vez por tarea y fecha—
task.overdueLa tarea supera su fecha de vencimiento sin estar completada, una vez por tarea y fecha—
task_comment.created, .updated, .deletedSe crea un comentario (también uno sincronizado desde una forja de código), se edita o se borraproject_id, y task_id en .deleted
task_time_entry.created, .updated, .deletedSe crea una imputación de tiempo (a mano o al arrancar un temporizador), se modifica (también al detener un temporizador) o se borraproject_id, y task_id en .deleted
task_time_entry.invoicedSe factura una imputación: un evento por cada imputación del loteproject_id
project.created, .updated, .archived, .deletedSe crea un proyecto, se modifica (también al desarchivarlo), se archiva o se borra—

Qué debes saber al consumirlos:

  • data.object es el recurso v1 tal como estaba cuando se emitió el evento —una task, un task_comment, un task_time_entry o un project, exactamente como lo serializa la API (consulta Proyectos y tareas)—, no el estado actual. Las claves extra de la tabla viajan a su lado, bajo data.
  • task.completed es un subconjunto de task.status_changed. Mover una tarea a una columna final emite los dos. Suscríbete a task.status_changed para seguir cada movimiento entre columnas y estados, y a task.completed solo si lo único que te importa son las tareas completadas; suscribirte a los dos entrega dos eventos por una misma tarea completada.
  • Los borrados se degradan. task.deleted, task_comment.deleted, task_time_entry.deleted y project.deleted llevan deleted: true en data.object y, cuando el recurso ya no se puede leer, nada más que su id. Su project_id hermano (y task_id) sigue diciéndote dónde estaba.
  • Enruta por proyecto. Cada evento de tarea, comentario y tiempo lleva el id de su proyecto —en data.object.project_id, o en data.project_id cuando el objeto no lo tiene o el evento es un borrado—. En los eventos project.* el proyecto es data.object.id. Consulta la guía de webhooks para ver un handler.
  • Desarchivar es una actualización. No existe project.unarchived: desarchivar un proyecto emite project.updated.
  • task.due_soon y task.overdue se emiten una vez por tarea y fecha de vencimiento. Cambiar la fecha de vencimiento rearma los dos para la fecha nueva.
  • El tiempo imputado no es el registro de jornada. El prefijo es task_time_entry, nunca time_entry, que pertenece a los fichajes del control horario; una empresa sin ese módulo sigue recibiendo task_time_entry.*. Consulta Tiempo imputado a tareas.

Eventos de cuenta

Además de los eventos de un NIF de arriba, hay diecisiete eventos de cuenta, con nombres que empiezan por account.. Te cuentan lo que le pasa a la propia cuenta: sus miembros y su titular (account.member_added, account.owner_transferred…), el acceso que da a otras cuentas (account.access_granted…), las cuentas que gestiona (account.managed_account_provisioned…), la llegada y la salida de sus NIF (account.nif_added, account.nif_transferred, account.nif_archived), sus importaciones masivas (account.import_completed), sus plazas contratadas (account.seats_updated) y el fin de un paquete de oferta (account.offer_package_ended). Su audiencia es la cuenta, no un NIF, así que viven aparte de todo lo demás de esta página:

  • No están en el catálogo de eventos de empresa. GET /v1/event-catalog no los lista, y un endpoint de empresa no puede suscribirse a ellos: un nombre account.* en su enabled_events responde 422 y no se crea nada. Tampoco están en el log de eventos de GET /v1/companies/{company}/events, porque ese log pertenece a un solo NIF.
  • No disparan automatizaciones de empresa. El catálogo de disparadores de las automatizaciones se construye a partir de los eventos de empresa, así que un evento account.* nunca es el disparador de una regla.
  • Solo llegan a endpoints de cuenta. Solo un endpoint de webhook de cuenta puede suscribirse a ellos, junto con los eventos de empresa si quieres. Su filtro account_relationship y la familia de cada evento deciden quién lo oye.

Webhooks de cuenta lista los diecisiete nombres con el data.object de cada uno, el sobre que recibe un endpoint de cuenta y quién oye cada evento. Un evento de un NIF, como invoice.paid, también puede llegar a un endpoint de cuenta y conserva el mismo id que tiene en un endpoint de empresa: consulta Deduplicar entregas de webhooks.

Ejemplos de payload

Estos son los cuerpos que entrega un webhook, con data.object abreviado a unos pocos campos: el real es el recurso completo, como en Forma del payload.

invoice.paid

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d",
  "type": "invoice.paid",
  "api_version": "2026-09-23",
  "created": 1774002600,
  "livemode": true,
  "test": false,
  "correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a99",
  "data": {
    "type": "invoice.paid",
    "object": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a42",
      "object": "invoice",
      "number": "FAC-2026-00042",
      "status": "paid",
      "total": "1210.00",
      "currency": "EUR"
    },
    "amount": "1210.00",
    "payment_date": "2026-03-20",
    "payment_method": "bank_transfer",
    "payment_reference": "TRF-2026-0042"
  }
}

invoice.issued

El body de la entrega lleva la factura completa en data.object; el ejemplo conserva solo los campos de los ejes de emisión y envío. Un endpoint cuyo api_version es 2026-05-22 recibe el mismo snapshot con el vocabulario anterior: "status": "sent", sent_at igual al instante de emisión y sin issued_at, sent_via ni is_sent. Consulta Webhooks.

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a7a",
  "type": "invoice.issued",
  "api_version": "2026-10-01",
  "created": 1773575100,
  "livemode": true,
  "test": false,
  "correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a7b",
  "data": {
    "type": "invoice.issued",
    "object": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a03",
      "object": "invoice",
      "number": "FAC-2026-00042",
      "status": "issued",
      "issued_at": "2026-03-15T11:45:00Z",
      "sent_at": null,
      "sent_via": null,
      "is_sent": false
    }
  }
}

transport_document.closed

Se emite cuando se cierra un documento de control. El proceso diario lo cierra automáticamente 7 días después del final de su última fecha de transporte (Europe/Madrid); el ejemplo es ese cierre automático. El cuerpo de la entrega lleva el recurso completo en data.object; el ejemplo conserva solo los campos del ciclo de vida.

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f9b01",
  "type": "transport_document.closed",
  "api_version": "2026-10-01",
  "created": 1791929700,
  "livemode": true,
  "test": false,
  "correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f9b02",
  "data": {
    "type": "transport_document.closed",
    "object": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f9a01",
      "object": "transport_document",
      "number": "DC-2026-042",
      "status": "closed",
      "public_url": "https://app.factuarea.com/api/public/deca/q3VfN2mX8yPbK1rT4wZs6LcH0dGjAe9uIoRtYvBnMkE",
      "current_version": 2,
      "closed_at": "2026-10-13T22:15:00+00:00",
      "close_mode": "automatic",
      "reopen_deadline": null,
      "retention_until": "2027-10-13T22:15:00+00:00"
    }
  }
}

client.updated

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a1a",
  "type": "client.updated",
  "api_version": "2026-09-23",
  "created": 1774003800,
  "livemode": true,
  "test": false,
  "correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a1b",
  "data": {
    "type": "client.updated",
    "object": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a2b",
      "object": "client",
      "name": "Acme Corporation",
      "tax_id": "B12345674",
      "email": "billing@acme.com"
    }
  }
}

quote.converted

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a3c",
  "type": "quote.converted",
  "api_version": "2026-09-23",
  "created": 1774003315,
  "livemode": true,
  "test": false,
  "correlation_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a3d",
  "data": {
    "type": "quote.converted",
    "object": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a04",
      "object": "quote",
      "number": "P-2026-00012",
      "status": "converted",
      "converted_to_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a42"
    },
    "target": "invoice",
    "target_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a42"
  }
}

El snapshot de data.object es el presupuesto tal y como estaba cuando se convirtió, y target y target_id apuntan a la factura que produjo. Obtén esa factura desde su propio endpoint (p. ej. GET /v1/companies/{company}/invoices/{id}) para leer su estado actual.

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.

Como todo evento, lleva el recurso afectado completo bajo data.object — el pago tal y como lo serializa la API v1, ya marcado como anulado — y añade un bloque data.reversal que describe la operación en sí:

{
  "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a5e",
  "type": "payment.reversed",
  "api_version": "2026-09-23",
  "created": 1780388100,
  "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; un sexto, issued_in_error, aparece en los pagos revertidos al anular con revert_collections una factura emitida por error. Ramifica según este campo, nunca según reversal_reason_text, que es una etiqueta en español para personas.
  • data.reversal.origin — gateway 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 (issued, sent antes de la versión de la API 2026-10-01, 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?.

task.status_changed

El cuerpo de la entrega lleva la tarea en data.object, tal como quedó tras el movimiento, y las dos claves extra de este evento: el estado y la columna de la que venía la tarea. El ejemplo conserva solo los campos del eje del tablero.

{
  "id": "0193a4f2-e1a0-7c10-9b21-3d5f7a9c1e01",
  "type": "task.status_changed",
  "api_version": "2026-10-01",
  "created": 1790673330,
  "livemode": true,
  "test": false,
  "correlation_id": "0193a4f2-e1a0-7c10-9b21-3d5f7a9c1e02",
  "data": {
    "type": "task.status_changed",
    "object": {
      "id": "0193a4f2-8f53-7d44-8e85-7a9b1c3d5f16",
      "object": "task",
      "key": "DEV-16",
      "project_id": "0193a4f2-7c20-7a11-8b52-4d6e8f0a2c01",
      "column_id": "0193a4f2-7d31-7b22-8c63-5e7f9a1b3d02",
      "status": "active",
      "title": "Call the customer about the checkout demo",
      "completed_at": null
    },
    "previous_status": "active",
    "previous_column_id": "0193a4f2-7d31-7b22-8c63-5e7f9a1b3d01"
  }
}
  • data.previous_status — planned, active o archived: el estado de tablero antes del cambio.
  • data.previous_column_id — la columna que dejó la tarea, o null cuando venía del backlog o del archivo.

Los demás eventos del módulo conservan el mismo envoltorio: task.assigned añade previous_assignee_id, task.moved añade from_project_id y task.updated añade changed_fields, la lista de campos del recurso público task que cambiaron.

Suscribirse a eventos

Vía API:

curl -X POST https://api.factuarea.com/v1/companies/{company}/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"]
  }'

enabled_events toma nombres de evento del catálogo, al menos uno. Un comodín como * o invoice.* no es un nombre válido: responde 422 y no se crea nada. Para reaccionar a una familia entera, enumera sus eventos (el catálogo los agrupa por categoría):

{ "enabled_events": ["invoice.created", "invoice.sent", "invoice.paid"] }

Un endpoint de webhook de cuenta acepta esos mismos nombres y también los eventos account.*, mezclados en la misma lista.

Listar eventos vía API

GET /v1/companies/{company}/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.

Los eventos se conservan 30 días: los más antiguos dejan de aparecer en el listado. Las entregas de un webhook conservan su propia copia del payload durante 90 días.

El log de eventos pertenece a la cuenta dueña del NIF. En un NIF que tu cuenta alcanza por una relación con otra cuenta —uno que te cedieron, o uno que pertenece a una cuenta que gestionas— GET /v1/companies/{company}/events y GET /v1/companies/{company}/events/{id} responden 403 forbidden_action, igual que las tools MCP list_events y get_event. En tus NIF propios funcionan como se describe. Para seguir los eventos de las cuentas que gestionas, usa un endpoint de webhook de cuenta.

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