Factuarea APIDevelopers

Esdeveniments

Objectes event de només lectura amb un id opac. Consulta històrica via l'API i entrega per webhook.

Cada esdeveniment publicat a Factuarea es persisteix com un objecte event de només lectura amb un id opac (un UUID v7, p. ex. 01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d), coherent amb l'id de qualsevol altre recurs v1. Això et permet:

  • Consultar-lo via API: GET /v1/events/{id} i GET /v1/events?type=invoice.paid.
  • Entregar-lo als webhook endpoints subscrits (el mateix objecte s'envia al body de l'entrega — vegeu Webhooks).
  • Reenviar una entrega des del dashboard (Developers > Webhooks > Deliveries).

Forma del payload

Cada esdeveniment comparteix aquesta 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"
}

Camps:

  • id — identificador opac de l'esdeveniment (UUID v7). Fes-lo servir com a idempotency key al teu costat.
  • object — sempre event.
  • type — nom de l'esdeveniment com a <category>.<action> (p. ex. invoice.paid, quote.approved).
  • aggregate_id — UUID v7 del recurs que va produir l'esdeveniment (p. ex. la factura per a invoice.paid). null per a esdeveniments sense agregat reomplert. Diferent d'id, que identifica el propi esdeveniment.
  • api_version — versió per data sota la qual es va serialitzar el payload, segellada en l'emissió. Sempre present en els esdeveniments emesos avui; null només per a esdeveniments antics emesos abans de segellar les versions.
  • livemodetrue per a esdeveniments generats en producció (clau live, fact_live_); false per a esdeveniments generats en mode de prova (empresa sandbox, clau fact_test_). Els esdeveniments de mode de prova es registren i es poden consultar via GET /v1/events, però no s'entreguen als webhook endpoints (vegeu Mode de prova i sandbox), de manera que qualsevol esdeveniment que el teu endpoint rebi realment és sempre livemode: true.
  • data — una referència lleugera al recurs afectat, indexada pel seu tipus — p. ex. { "invoice": { "id": "..." } }. Obtén el recurs des del seu propi endpoint per aconseguir la representació completa i actual.
  • created — timestamp ISO 8601 UTC de quan es va crear l'esdeveniment.

Idempotència

Cada esdeveniment té un id únic. Els webhooks reentreguen el mateix id al mateix endpoint a cada reintent. Al teu handler:

event_id = event['id']
if seen_in_db(event_id):
    return '', 200
process(event)
mark_seen_in_db(event_id)

Catàleg d'esdeveniments

El catàleg complet i autoritatiu de tipus d'esdeveniment subscribibles el retorna GET /v1/event-catalog. Cada entrada porta un name, una category, una description llegible i 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
}

Tipus d'esdeveniment representatius per categoria (consulta el catàleg per a la llista completa i actualitzada):

Factures

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 els emeten els fluxos d' auto-facturació de passarel·les de pagament quan un cobrament, una devolució o un cicle de subscripció generen una factura de manera automàtica.

Pressupostos

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.

Factures 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.

Albarans

delivery_note.created, delivery_note.updated, delivery_note.status_changed, delivery_note.signed, delivery_note.converted, delivery_note.email_sent, delivery_note.email_failed.

Factures de compra

purchase_invoice.created, purchase_invoice.updated, purchase_invoice.paid, purchase_invoice.payment_registered, purchase_invoice.cancelled, purchase_invoice.metadata_changed.

Factures recurrents

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.

Clients i productes

client.created, client.updated, client.deleted, client.metadata_changed, product.created, product.updated.

Sèries i impostos

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.

Pagaments i passarel·les

payment.received, payment.reversed, payout.reconciled.

payment.received i payment.reversed són les dues meitats d'un mateix cicle: el primer es dispara quan es registra un pagament contra una factura, i el segon quan aquest pagament s'anul·la i la factura torna al circuit de cobrament. Subscriu-te als dos — una factura que vas donar per cobrada pot deixar d'estar-ho, i reaccionar només a la primera meitat és confiar en una xifra que ha caducat. Consulta payment.reversed més avall.

payout.reconciled es dispara quan un payout de Stripe es concilia amb el teu extracte bancari (consulta Payouts i conciliació).

Automatitzacions

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 del seu propi cicle de vida. Els tres esdeveniments automation_rule.* porten la regla al cos d'entrega, sota data.object: activated quan una regla entra en servei i comença a escoltar el seu activador, paused quan l'atura una persona i auto_paused quan l'atura la plataforma després d'una ratxa d'execucions fallides.

Els quatre esdeveniments automation_run.* porten l'execució al cos d'entrega, sota data.object: started quan un activador que ha coincidit supera els límits del motor i l'execució s'admet, completed quan tots els passos van aplicar el seu efecte, failed quan l'execució va acabar sense produir el seu efecte i no es pot reprocessar, i step_dead_lettered quan un pas concret queda aparcat a l'espera d'un rellançament manual. Com a la resta d'esdeveniments, data.object és el snapshot pres en emetre'l, no l'estat actual del recurs. Consulta la referència de l'execució.

Dos d'ells porten claus extra al costat del snapshot. automation_rule.auto_paused afegeix consecutive_failures, el nombre d'execucions fallides consecutives que van provocar la pausa automàtica — la regla la va pausar la plataforma, i automation_rule.paused és el seu equivalent humà. automation_run.step_dead_lettered afegeix step_index i discard_reason: step_index és la posició del pas aparcat començant per zero, i es resol contra el mateix snapshot (l'element de data.object.steps el step_index del qual coincideix, perquè un pas no és un recurs públic per si mateix), i discard_reason és un valor tipat d'un catàleg tancat, mai text lliure. A la pràctica sempre és un motiu de descart rellançable: un resultat que no admet reprocés tanca l'execució com a failed en comptes d'aparcar el pas.

Aquests set noms són al mateix catàleg tancat que la resta d'esdeveniments, així que també són activadors vàlids de regles: una automatització pot reaccionar a automation_run.failed igual que reacciona a invoice.paid, i cap llista d'exclusió no els amaga del catàleg d'activadors. Com la resta del motor, requereixen el mòdul automations.

Encadenar-los està acotat, no prohibit. Cada salt «acció → esdeveniment → regla» consumeix el límit de profunditat d'encadenament del motor —tres salts per defecte—, així que una regla que reacciona a automation_run.failed i torna a fallar no pot repetir-se sense fi: exhaurit el límit, l'execució no arriba a executar-se i queda registrada com a blocked. Un esdeveniment que produeix una persona o una integració entra amb profunditat zero, així que només consumeix aquest pressupost allò que va provocar una automatització.

Exemples 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"
}

L'esdeveniment només porta una referència lleugera al recurs afectat. Obtén el recurs des del seu propi endpoint (p. ex. GET /v1/quotes/{id}) per llegir la factura convertida a la qual enllaça.

payment.reversed

S'emet quan s'anul·la un pagament registrat contra una factura. Fins que va existir, una integració que havia sentit payment.received no tenia manera d'assabentar-se que aquell mateix pagament s'havia desfet.

El cos d'entrega d'aquest esdeveniment porta el recurs afectat complet sota data.object — el pagament tal com el serialitza l'API v1, ja marcat com a anul·lat — més un bloc data.reversal que descriu l'operació mateixa:

{
  "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 — un dels cinc valors del catàleg tancat: direct_debit_return, card_dispute, misapplied_payment, bounced_effect, recording_error. Ramifica segons aquest camp, mai segons reversal_reason_text, que és una etiqueta en castellà per a persones.
  • data.reversal.origingateway quan va ser la passarel·la de pagament la que va informar de la devolució, disputa o retrocessió (ja hi va haver moviment al banc); manual quan ho va registrar una persona. Útil per decidir si reclamar al client o esperar el fitxer bancari.

Què fer quan arriba: la factura ha tornat al circuit de cobrament (sent, o overdue si el seu venciment ja ha passat) i el seu paid_amount ja no inclou aquella entrada, així que refresca el que tinguessis desat a la memòria cau sobre aquella factura. No emetis una factura rectificativa com a reacció — una anul·lació no és una minoració d'ingressos. Consulta Anul·lació o rectificativa?.

Subscriure's a esdeveniments

Via 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"]
  }'

Per subscriure't a tots els esdeveniments (no recomanat en producció excepte per a dashboards interns):

{ "enabled_events": ["*"] }

Per subscriure't a famílies senceres (tots els invoice.*):

{ "enabled_events": ["invoice.*", "quote.*"] }

Llistar esdeveniments via API

GET /v1/events?type=invoice.paid&limit=50

Filtres disponibles: type, type[in], created[gte], created[lte], created[gt], created[lt]. Paginació per cursor estàndard (limit, starting_after, ending_before) — vegeu Paginació.

Esdeveniments de comandes

Subscriu-te a order.invoiced i order.refunded per rebre snapshots complets de la factura o rectificativa a data.object. Tots dos inclouen data.store.uuid, data.store.provider i data.order.external_id; les devolucions afegeixen data.refund.scope i data.refund.reason_code. Fes servir l’id de l’esdeveniment per deduplicar lliuraments i correlation_id per relacionar operacions. Consulta el processament de botigues i 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 aquesta pàgina

Et donem un cop de mà?Contactar amb suport