Skip to main content
You’re viewing the current (v1) contract. order.cancelled carries the same v1 order snapshot as order.completed — order/product discounts (Discount object), granular taxes, the full itemType enum, and deliveryConfirmationCode — plus the cancellation audit block.
order.cancelled fires when a previously injected order is cancelled — either from the Fire backoffice UI, an external adapter, or a cancellation API call. It does not retract a prior order.completed for the same order; both events are emitted independently.

Trigger condition

Fire emits order.cancelled once when an order’s status transitions to CANCELLED, regardless of the order’s previous payment state. The cancellation is recorded with full audit context (who, when, why, source).
CoverageGlobal (every country, every channel)
Idempotency keyevent.id
Fires more than onceNo, unless retried
OrderingNot guaranteed against order.completed for the same order — sort by event timestamps if you need it
RetriesUp to 5 attempts with exponential backoff (when retryOnFailure is enabled)
Brazilian fiscal contextIncludes original fiscal data in cancellation.metadata.fiscal if the order had been fiscally authorized

What’s in trigger.data

Same V4 order snapshot as order.completed — every field documented there is present here, with three differences:
  1. status is "CANCELLED" (not "COMPLETED").
  2. paymentStatus is unchanged from when the order was completed (typically "SUCCEEDED" if the order had been paid before cancellation).
  3. A new top-level cancellation block carries the audit metadata.

Example — real production payload (BR, sanitized)

{
  "event": {
    "id": "abcf3781-c327-4df1-84ef-5efbacc1d387",
    "type": "order.cancelled",
    "createdAt": "2026-05-05T23:06:08.883Z"
  },
  "data": {
    "orderId": "e98f5725-0d1e-4f93-ac18-40f1068cae89",
    "orderCode": "OC-br-001",
    "businessDayDate": "2026-03-31",
    "externalOrderId": "ac331b68-66fb-48ee-b110-a40181bfb379",
    "status": "CANCELLED",
    "paymentStatus": "SUCCEEDED",
    "redeemPoints": false,
    "accumulatePoints": false,
    "discount": false,
    "createdAt": "2026-05-05T23:05:00.438Z",
    "orderComment": "Comentario de prueba orden",
    "marketing": null,
    "store": { /* same as order.completed — see /en/events/order-completed */ },
    "device": { /* ... */ },
    "channel": { /* ... */ },
    "operator": { /* ... */ },
    "client": { /* ... */ },
    "payments": { /* ... */ },
    "kds": { /* ... */ },
    "metadata": {},
    "orderLines": [ /* ... */ ],
    "fulfillment": { /* ... */ },

    "cancellation": {
      "cancellationId": "abcf3781-c327-4df1-84ef-5efbacc1d387",
      "cancelledAt": "2026-05-05T23:06:08.883Z",
      "cancelledBy": "00000000-0000-0000-0000-000000000000",
      "cancellationReason": "Customer requested cancellation",
      "cancellationSource": "backoffice",
      "metadata": {
        "fiscal": {
          "serie": null,
          "numero": "1000013",
          "pdfUrl":   "https://api.fiscal-provider.example/nfce/<docId>/pdf",
          "xmlUrl":   "https://api.fiscal-provider.example/nfce/<docId>/xml",
          "protocolo": "141200000956123",
          "docSubtype": "nfce",
          "chaveAcesso": "41201008187168000160558050010000131609769080",
          "providerDocId": "69fa77aa2a48c20329be4604",
          "dataAutorizacao": "2026-05-05T23:05:15.590Z"
        }
      }
    }
  },
  "_meta": { "executionId": "...", "flowId": "...", "attempt": "1" }
}

data.cancellation reference

cancellation
object
Audit block describing how, when, and by whom the order was cancelled.

Lifecycle relative to other events

For a Brazilian fiscal-enabled order that gets cancelled, expect this sequence:
  • order.cancelled is emitted immediately when the cancellation happens, before any external fiscal authority is contacted.
  • order.reversed is emitted later — once SEFAZ confirms via your fiscal provider. It can arrive seconds or minutes after order.cancelled, depending on SEFAZ response time.
  • For non-Brazilian orders or stores without fiscal emission, only order.cancelled fires.

Country variations

order.cancelled is global — it fires for every country and every channel when an order is cancelled (Argentina, Brazil, Chile, Colombia, Ecuador, Venezuela, and any other country with active Integration Flows). The cancellation audit block (cancellation.{cancellationId, cancelledAt, cancelledBy, cancellationReason, cancellationSource}) is identical across countries. The only country-specific field is cancellation.metadata.fiscal, which is populated only for Brazilian stores that had a previously authorized fiscal document (i.e. a order.invoiced was emitted for this order earlier). For all other countries — and for BR orders cancelled before fiscal authorization — cancellation.metadata.fiscal is null and no order.reversed event will follow. For non-BR stores (Argentina, Chile, Colombia, Ecuador, Venezuela, others), the cancellation block looks like:
Non-BR cancellation
{
  "cancellation": {
    "cancellationId": "abcf3781-c327-4df1-84ef-5efbacc1d387",
    "cancelledAt": "2026-05-05T23:06:08.883Z",
    "cancelledBy": "00000000-0000-0000-0000-000000000000",
    "cancellationReason": "Customer requested cancellation",
    "cancellationSource": "backoffice",
    "metadata": { "fiscal": null }
  }
}
Store-level identifiers in data.store still vary by country — see order.completed → Country variations for country.code, currencyCode, and storeFiscalConfig.govIdType (CNPJ / CUIT / RUT / NIT / RUC / RIF) per country.

Handler example

async function onOrderCancelled(data) {
  const { orderId, store, cancellation } = data;

  // 1. Mark the order cancelled in your system (idempotent)
  await db.orders.update({
    where: { fireOrderId: orderId },
    data: {
      status: "CANCELLED",
      cancelledAt: new Date(cancellation.cancelledAt),
      cancellationReason: cancellation.cancellationReason,
      cancellationSource: cancellation.cancellationSource,
    },
  });

  // 2. If the store is fiscal-enabled and there was a fiscal doc,
  //    open a reconciliation ticket — the SEFAZ cancellation will
  //    follow in order.reversed.
  if (cancellation.metadata?.fiscal) {
    await reconciliation.open({
      orderId,
      country: store.locationInfo.country.code,
      originalDoc: cancellation.metadata.fiscal,
      pendingSefazCancel: true,
    });
  }

  // 3. Roll back downstream side-effects (release stock, refund, etc.)
  await downstream.rollback(orderId);
}

Common pitfalls

  • status === "CANCELLED", not paymentStatus. Cancelled paid orders keep paymentStatus === "SUCCEEDED"; the cancellation lives in the status field plus the cancellation block.
  • order.cancelled ≠ refund. Fire reports the cancellation; the refund (if any) is initiated by the source channel/processor and is not in this payload.
  • Don’t assume order.completed arrived first. Out-of-order delivery is possible — your handler should be tolerant to receiving order.cancelled for an orderId it doesn’t yet know about (e.g. log + create a placeholder; reconcile when order.completed arrives).
  • cancellation.metadata.fiscal is the original doc, not the cancellation result. For the SEFAZ confirmation, listen for order.reversed.

order.completed

The event you’ll see for the same order before cancellation.

order.reversed

Brazil only — fires when SEFAZ confirms the cancellation.