Events
Read-only event objects with an opaque id. Historical query via the API and webhook delivery.
Every event published in Factuarea is persisted as a read-only
event object with an opaque id (a UUID v7, e.g.
01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0d), consistent with the id of
every other v1 resource. This lets you:
- Query it via API:
GET /v1/companies/{company}/events/{id}andGET /v1/companies/{company}/events?type=invoice.paid. - Deliver it to subscribed webhook endpoints, in a signed envelope with
the same
id,typeanddata(see Webhooks). - Replay a delivery from the dashboard
(
Developers > Webhooks > Deliveries).
Payload shape
GET /v1/companies/{company}/events/{id} returns the event under data.
The event looks like this, with the invoice under data.object abridged to
six of its fields:
{
"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
}Fields:
id— opaque identifier of the event (UUID v7). Use it to deduplicate on your side.object— alwaysevent.type— event name as<category>.<action>(e.g.invoice.paid,quote.approved).aggregate_id— UUID v7 of the resource that produced the event (e.g. the invoice forinvoice.paid).nullfor events without a backfilled aggregate. Distinct fromid, which identifies the event itself.correlation_id— UUID v7 that links the events caused by one operation, ornullwhen there is none. The key is always present.api_version— date-based version the payload was serialized under, sealed at emission. Always present on events emitted today;nullonly for legacy events emitted before versions were sealed.livemode—truefor events generated in production (live key,fact_live_);falsefor events generated in test mode (sandbox company,fact_test_key). Test-mode events are recorded and queryable viaGET /v1/companies/{company}/events, but not delivered to webhook endpoints (see Test mode & sandbox), so any event your endpoint actually receives is alwayslivemode: true.test—truefor a test delivery sent withtest-event,falsefor real events. It is orthogonal tolivemode.data—{ "type", "object" }.objectis the full snapshot of the affected resource as it was when the event happened, identical to what aGETof that resource returned at that moment. It is frozen: later changes to the resource don't rewrite past events, so fetch the resource from its own endpoint when you need its current state. The keys that are specific to the event sit next toobject, such asamountandpayment_dateininvoice.paid.created— Unix timestamp, in seconds, of when the event was created.
A webhook delivers the same event in a signed envelope: the same id,
type, api_version, created, livemode, test, correlation_id and
data, without object and aggregate_id. See its
delivery body.
Idempotency
Each event has a unique id. Webhooks redeliver the same id to the
same endpoint on every retry, and an account endpoint that admits the same
event of a tax ID receives it with the same id too. In your handler,
store the ids you have processed and answer 2xx without acting if you
see one again. Deduplicate webhook deliveries
has the whole recipe and how long to keep the ids.
Event catalog
The full, authoritative catalog of subscribable event types is returned
by GET /v1/event-catalog. Each entry carries a name, a category, a
human-readable description, and a status (available or
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
}This is the catalog of the events of a tax ID. The account.* events
of the account itself are not in it: see Account events.
Representative event types by category (query the catalog for the complete, up-to-date list):
Invoices
invoice.created, invoice.auto_created,
invoice.corrective_auto_created, invoice.subscription_auto_created,
invoice.updated, invoice.issued, invoice.marked_sent,
invoice.unsent, invoice.sent (deprecated), 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 are emitted by the
payment-gateway auto-invoicing flows when a
charge, refund or subscription cycle produces an invoice automatically.
invoice.issued is emitted when an invoice is issued: definitive number,
VeriFactu record and stock movements. invoice.marked_sent is emitted when it
reaches the customer (the mail server accepted its delivery email, or someone
marked it by hand) and invoice.unsent when that mark is cleared. A payment
never marks an invoice as sent. invoice.sent is a deprecated alias of
invoice.issued, emitted at the same instant with the same data.object; new
integrations should subscribe to invoice.issued, and the removal of the alias
will be announced with a Sunset date. Automation rules no longer accept
invoice.sent as a trigger.
Quotes
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.
Pro-forma invoices
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.
Delivery notes
delivery_note.created, delivery_note.updated,
delivery_note.status_changed, delivery_note.signed,
delivery_note.converted, delivery_note.email_sent,
delivery_note.email_failed.
Transport control documents
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.
Each delivery carries the full v1 transport_document resource under
data.object. They are emitted whatever the origin of the change — the app, the
REST API, MCP or the daily automatic close. transport_document.updated also fires
when a draft copies again a party whose contact or company data changed (see
Transport control document (DeCA)). transport_document.closed tells a manual
close from an automatic one with data.object.close_mode (manual or automatic).
transport_document.email_sent (the mail server accepted the email) and
transport_document.email_failed (it could not be delivered) work like those of delivery
notes: next to data.object, data carries recipient_email (the first to address),
the to, cc and bcc lists and the version of the PDF attached;
email_sent adds transport_document_number and email_failed adds error_message
and error_class. Deleting a draft is not published as an event. The transport_document prefix belongs
to the transport_documents module. See
Transport control documents.
Expenses
purchase_invoice.created, purchase_invoice.updated,
purchase_invoice.paid, purchase_invoice.payment_registered,
purchase_invoice.cancelled, purchase_invoice.metadata_changed.
Recurring invoices
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 & products
client.created, client.updated, client.deleted,
client.metadata_changed, product.created, product.updated.
Series & taxes
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.
The tax.* events are delivered for the taxes owned by your company. Taxes of the
Factuarea catalog do not emit events.
FacturaE (FACe)
facturae.face_submitted, facturae.face_status_changed,
facturae.face_cancellation_requested.
Payments & gateways
payment.received, payment.reversed, payout.reconciled.
payment.received and payment.reversed are the two halves of one
cycle: the first fires when a payment is registered against an invoice,
the second when that payment is voided and the invoice goes back into the
collection circuit. Subscribe to both — an invoice you recorded as
collected can stop being collected, and reacting only to the first half
means trusting a figure that expired. See
payment.reversed below.
payout.reconciled fires when a Stripe payout is reconciled against your bank
statement (see Payouts & reconciliation).
Automations
automation_rule.activated, automation_rule.paused,
automation_rule.auto_paused, automation_run.started,
automation_run.completed, automation_run.failed,
automation_run.step_dead_lettered.
The engine reports its own life cycle. The three automation_rule.* events
carry the rule in the delivery body, under data.object: activated when a
rule goes live and starts listening to its trigger, paused when a person stops
it, and auto_paused when the platform stops it after a streak of failed runs.
The four automation_run.* events carry the run in the delivery body, under
data.object: started when a matched trigger clears the engine limits and the
run is admitted,
completed when every step applied its effect, failed when the run finished
without producing its effect and cannot be reprocessed, and
step_dead_lettered when a single step is parked awaiting a manual replay. As
everywhere else, data.object is the snapshot taken when the event was
emitted, not the current state of the resource. See the
run reference.
Two of them carry extra keys beside the snapshot.
automation_rule.auto_paused adds consecutive_failures, the number of
consecutive failed runs that tripped the automatic pause — the platform paused
the rule, and automation_rule.paused is its human counterpart.
automation_run.step_dead_lettered adds step_index and discard_reason:
step_index is the zero-based position of the parked step, resolved against
the snapshot itself (the element of data.object.steps whose step_index
matches, because a step is not a public resource of its own), and
discard_reason is a typed value from a closed catalog, never free-form text.
In practice it is always a replayable reason: an outcome that does not admit
reprocessing closes the run as failed instead of parking the step.
These seven names live in the same closed catalog as every other event, so they
are valid rule triggers too: an automation can react to
automation_run.failed exactly as it reacts to invoice.paid, and no
exclusion list hides them from the trigger catalog. Like the rest of the
engine, they are gated by the automations module.
Chaining them is bounded, not forbidden. Every hop "action → event → rule"
consumes the engine's chain-depth cap — three hops by default — so a rule that
reacts to automation_run.failed and fails again cannot loop forever: once the
cap is spent the run is not executed, it is recorded as blocked. An event
produced by a person or by an integration enters at depth zero, so only what an
automation itself caused spends that budget.
Tasks & projects
The task module publishes 21 events in four families. They live in the same
closed catalog as every other event, so a webhook endpoint can subscribe to them
(or to "*"), and they are valid automation triggers
for companies with the tasks module — a company without it neither sees them in
the trigger catalog nor can save a rule that uses one.
| Family | Events |
|---|---|
| Tasks | task.created, task.updated, task.deleted, task.status_changed, task.completed, task.assigned, task.unassigned, task.moved, task.due_soon, task.overdue |
| Comments | task_comment.created, task_comment.updated, task_comment.deleted |
| Logged time | task_time_entry.created, task_time_entry.updated, task_time_entry.deleted, task_time_entry.invoiced |
| Projects | project.created, project.updated, project.archived, project.deleted |
Every event is emitted by the operation that causes it, from any surface — the app, the API, MCP, the employee portal, an automation, an integration or a scheduled process — and is delivered once per fact, even if the event is redelivered internally.
| Event | Emitted when | Extra keys beside object |
|---|---|---|
task.created | A task is created, also by duplicating, importing or an automation | — |
task.updated | The title, description, priority, start_on or due_on change | changed_fields |
task.deleted | A task is deleted, also in bulk | project_id |
task.status_changed | The column or the virtual status (planned, active, archived) changes | previous_status, previous_column_id |
task.completed | The task enters a final column | — |
task.assigned | The task gets an assignee or changes it | previous_assignee_id |
task.unassigned | The task loses its assignee | — |
task.moved | The task moves to another project | from_project_id |
task.due_soon | The task enters its due-date warning window, once per task and date | — |
task.overdue | The task passes its due date without being completed, once per task and date | — |
task_comment.created, .updated, .deleted | A comment is created (also one synchronized from a code forge), edited or deleted | project_id, and task_id on .deleted |
task_time_entry.created, .updated, .deleted | A time entry is created (by hand or by starting a timer), changed (also when a timer stops) or deleted | project_id, and task_id on .deleted |
task_time_entry.invoiced | A time entry is invoiced: one event for each entry of the batch | project_id |
project.created, .updated, .archived, .deleted | A project is created, changed (also when it is unarchived), archived or deleted | — |
What to know when you consume them:
data.objectis the v1 resource as it was when the event was emitted — atask,task_comment,task_time_entryorproject, exactly as the API serializes it (see Projects and tasks) — not the current state. The extra keys of the table travel beside it, underdata.task.completedis a subset oftask.status_changed. Moving a task into a final column emits both. Subscribe totask.status_changedto follow every move between columns and states, and totask.completedonly if completions are all you care about; subscribing to both delivers two events for one completion.- Deletions degrade.
task.deleted,task_comment.deleted,task_time_entry.deletedandproject.deletedcarrydeleted: trueindata.objectand, when the resource can no longer be read, nothing but itsid. Their siblingproject_id(andtask_id) still tells you where it was. - Route by project. Every task, comment and time event carries the id of its
project — in
data.object.project_id, or indata.project_idwhen the object has none or the event is a deletion. Forproject.*events the project isdata.object.id. See the webhooks guide for a handler. - Unarchiving is an update. There is no
project.unarchived: unarchiving a project emitsproject.updated. task.due_soonandtask.overduefire once per task and due date. Changing the due date arms both again for the new date.- Logged time is not the working-day register. The prefix is
task_time_entry, nevertime_entry, which belongs to the clock-ins of Time tracking; a company without that module still receivestask_time_entry.*. See Time logged on tasks.
Account events
Besides the events of a tax ID above, there are seventeen account events, with
names that start with account.. They tell you what happens to the account
itself: its members and owner (account.member_added,
account.owner_transferred…), the access it gives to other accounts
(account.access_granted…), the accounts it manages
(account.managed_account_provisioned…), its tax IDs coming and going
(account.nif_added, account.nif_transferred, account.nif_archived), its bulk imports (account.import_completed), its
contracted seats (account.seats_updated) and the end of an offer package
(account.offer_package_ended). Their audience is the
account, not a tax ID, so they live apart from everything else on this page:
- They are not in the company event catalog.
GET /v1/event-catalogdoesn't list them, and a company endpoint can't subscribe to them: anaccount.*name in itsenabled_eventsanswers422and nothing is created. They are not in the event log ofGET /v1/companies/{company}/eventseither, because that log belongs to one tax ID. - They don't trigger company automations. The catalog of triggers of
the automations is built from the company events, so an
account.*event is never the trigger of a rule. - They only reach account endpoints. Only an
account webhook endpoint can subscribe to
them, together with the company events if you want. Its
account_relationshipfilter and the family of each event decide who hears it.
Account webhooks lists the seventeen names
with the data.object of each, the envelope an account endpoint receives
and who hears each event. An event of
a tax ID, such as invoice.paid, can reach an account endpoint too, and it
keeps the same id it has at a company endpoint: see
Deduplicate webhook deliveries.
Payload examples
These are the bodies that a webhook delivers, with data.object abridged to a
few fields: the real one is the whole resource, as in
Payload shape.
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
The delivery body carries the full invoice under data.object; the example
keeps only the fields of the issuance and delivery axes. An endpoint whose
api_version is 2026-05-22 receives the same snapshot in the previous
vocabulary: "status": "sent", sent_at equal to the issuance instant and no
issued_at, sent_via or is_sent. See
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
Emitted when a transport control document is closed. The daily process closes it
automatically 7 days after the end of its last transport date (Europe/Madrid); the
example is that automatic close. The delivery body carries the full resource under
data.object; the example keeps only the lifecycle fields.
{
"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"
}
}The snapshot under data.object is the quote as it was when it was
converted, and target and target_id point to the invoice that it
produced. Fetch that invoice from its own endpoint (e.g.
GET /v1/companies/{company}/invoices/{id}) to read its current state.
payment.reversed
Emitted when a payment registered against an invoice is voided. Until it
existed, an integration that had heard payment.received had no way
of finding out that the same payment had come undone.
Like every event, it carries the affected resource in full under
data.object — the payment as the v1 API serialises it, already flagged as
reverted — and adds a data.reversal block describing the operation
itself:
{
"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— one of the five values of the closed catalog:direct_debit_return,card_dispute,misapplied_payment,bounced_effect,recording_error; a sixth,issued_in_error, appears on the payments reverted by annulling an invoice issued by mistake withrevert_collections. Branch on this, never onreversal_reason_text, which is a Spanish label for humans.data.reversal.origin—gatewaywhen the payment provider reported a return, dispute or chargeback (money already moved at the bank);manualwhen a person recorded it. Useful to decide whether to chase the customer or wait for the bank file.
What to do when it arrives: the invoice is back in the collection circuit
(issued, sent before API version 2026-10-01, or overdue if its due
date has passed) and its paid_amount
no longer includes this entry, so refresh whatever you cached about that
invoice. Do not issue a corrective invoice as a reaction — a
reversal is not a reduction of revenue. See
Reversal or corrective invoice?.
task.status_changed
The delivery body carries the task under data.object, as it was after the
move, and the two extra keys of this event: the status and the column the task
came from. The example keeps only the fields of the board axis.
{
"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,activeorarchived: the board status before the change.data.previous_column_id— the column the task left, ornullwhen it came from the backlog or from the archive.
The other events of the module keep the same envelope: task.assigned adds
previous_assignee_id, task.moved adds from_project_id and task.updated
adds changed_fields, the list of fields of the public task resource that
changed.
Subscribe to events
Via 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 takes event names from the catalog, at least one. A wildcard
such as * or invoice.* is not a valid name: it answers 422 and nothing
is created. To react to a whole family, list its events (the catalog groups
them by category):
{ "enabled_events": ["invoice.created", "invoice.sent", "invoice.paid"] }An account webhook endpoint takes these same
names and also the account.* events, mixed in the same
list.
List events via API
GET /v1/companies/{company}/events?type=invoice.paid&limit=50Available filters: type, type[in], created[gte], created[lte],
created[gt], created[lt]. Standard cursor pagination
(limit, starting_after, ending_before) — see
Pagination.
Events are kept for 30 days: older ones no longer appear in the list. The deliveries of a webhook keep their own copy of the payload for 90 days.
The event log belongs to the account that owns the tax ID. On a tax
ID that your account reaches through a relation with another account —
one that was granted to you, or one that belongs to an account you
manage — GET /v1/companies/{company}/events and
GET /v1/companies/{company}/events/{id} answer 403 forbidden_action,
and so do the MCP tools list_events and get_event. On your own tax IDs
they work as described. To follow the events of the accounts you manage,
use an account webhook endpoint.
Order events
Subscribe to order.invoiced and order.refunded to receive full invoice or corrective-invoice snapshots under data.object. Both include data.store.uuid, data.store.provider and data.order.external_id; refunds also include data.refund.scope and data.refund.reason_code. Use the event id for delivery deduplication and correlation_id for related operations. See store processing and the n8n trigger.
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 });
}