> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fire.rest/llms.txt
> Use this file to discover all available pages before exploring further.

# order.completed

> An injected order has been fully received and paid. The most common Fire event — carries the full V4 order snapshot and the store's fiscal configuration.

<Tabs>
  <Tab title="v1.2 · current">
    You are reading the **current (v1.2)** contract for `order.completed`. **v1.2 adds** `data.fiscalRepresentation`: the fiscal numbering the point of sale obtained before injecting the order. It **always** travels: `null` when numbering was not attempted, and populated when it was — `numberingStatus` tells you how it ended. Carrying content does **not** mean the document is authorized. Additive only — nothing you already read changed.

    The block carries the order's **current** fiscal document: the fields that mean the same in every country at the top, the authority identifiers inside `countryData` in that country's own vocabulary, and the previous documents in `history`. When a cancellation numbers, the credit note moves to the top and the invoice moves down into history — with `compensates` pointing at it.
  </Tab>

  <Tab title="v1.1 · previous">
    **v1.1 added** `data.policy.deferredPayment` (can this order be worked before payment?) and `data.lastKnown` (advisory kitchen/fiscal state), plus the new [`order.opened`](/en/events/order-opened) event. Still valid: v1.2 only adds one block.
  </Tab>

  <Tab title="v1 · deprecated">
    <Warning>The **v1** contract is **deprecated** — kept as a historical reference. Open it here: [`order.completed` — v1](/en/events-v1/order-completed).</Warning>
  </Tab>

  <Tab title="v0 · deprecated">
    <Warning>The **v0** contract is **deprecated** — kept only as a historical reference. Open it here: [order.completed — v0](/en/events-v0/order-completed).</Warning>
  </Tab>
</Tabs>

`order.completed` fires when an order is successfully injected and paid. It carries the **V4 order snapshot** as `trigger.data` — every field your flow needs to act on the order without calling back into Fire.

## Trigger condition

Fire emits `order.completed` exactly **once** per order, the first time both of these are true at injection time:

* `order.status === "COMPLETED"`
* `order.paymentStatus === "SUCCEEDED"`

Orders that are still `PENDING` payment, or that fail payment, **never** produce `order.completed`. Cancellations after completion produce a separate [`order.cancelled`](/en/events/order-cancelled) event — they do not retract `order.completed`.

|                      |                                                                        |
| -------------------- | ---------------------------------------------------------------------- |
| Coverage             | Global (every country, every channel)                                  |
| Idempotency key      | `event.id` (= `flow_executions.id`)                                    |
| Fires more than once | No, unless retried — use `event.id` to dedup                           |
| Ordering             | Not guaranteed across orders — sort by `data.createdAt` if you need it |
| Retries              | Up to 5 attempts with exponential backoff                              |

## What's in `trigger.data`

`trigger.data` is the **V4 order snapshot** — the same object that's persisted in `flow_queue.trigger_data` and exposed to your flow's templates.

The top-level keys, in the order they appear:

| Key                | Type                            | Always present |
| ------------------ | ------------------------------- | -------------- |
| `orderId`          | `string` (UUID)                 | yes            |
| `orderCode`        | `string \| null`                | yes            |
| `businessDayDate`  | `string` (`YYYY-MM-DD`)         | yes            |
| `externalOrderId`  | `string`                        | yes            |
| `redeemPoints`     | `boolean`                       | yes            |
| `accumulatePoints` | `boolean`                       | yes            |
| `discount`         | `boolean`                       | yes            |
| `createdAt`        | `string \| null` (ISO 8601 UTC) | yes            |
| `orderComment`     | `string` (may be `""`)          | yes            |
| `paymentStatus`    | `string` (always `"SUCCEEDED"`) | yes            |
| `status`           | `string` (always `"COMPLETED"`) | yes            |
| `marketing`        | `object \| null`                | yes            |
| `store`            | `object`                        | yes            |
| `device`           | `object`                        | yes            |
| `channel`          | `object`                        | yes            |
| `operator`         | `object`                        | yes            |
| `client`           | `object \| null`                | yes            |
| `payments`         | `object`                        | yes            |
| `kds`              | `object`                        | yes            |
| `metadata`         | `object` (often `{}`)           | yes            |
| `orderLines`       | `object[]`                      | yes            |
| `fulfillment`      | `object`                        | yes            |

## Example — real production payload (BR, sanitized)

The example below is taken from a real `flow_queue.trigger_data` row (Brazilian sandbox tenant, `KIOSK` channel, dine-in service). PII fields are replaced with placeholders; all other fields and shapes are verbatim.

```json theme={null}
{
  "orderId": "21ec1f6c-c301-4528-b999-7836c1d21c6c",
  "orderCode": "OC-br-001",
  "businessDayDate": "2026-03-31",
  "externalOrderId": "7805610b-97cf-461f-a2d6-d86f63a80833",
  "redeemPoints": false,
  "accumulatePoints": false,
  "discount": false,
  "createdAt": "2026-05-06T01:22:59.028Z",
  "orderComment": "Comentario de prueba orden",
  "paymentStatus": "SUCCEEDED",
  "status": "COMPLETED",
  "marketing": null,
  "store": {
    "uid": "a4019cad-bbac-4269-9f8d-f29654e92c45",
    "code": "BR-SP-001",
    "name": "Loja Centro - SP",
    "phone": "1132094347",
    "address": "Av. Paulista 1578, Bela Vista, São Paulo - SP",
    "externalId": "a4019cad-bbac-4269-9f8d-f29654e92c45",
    "vendor": {
      "uid": "100.2.1",
      "name": "Sandbox Brand",
      "description": "Sandbox Brand",
      "loyaltyPlan": true
    },
    "account": {
      "uid": "100",
      "name": "Sandbox",
      "description": "Sandbox"
    },
    "locationInfo": {
      "city":     { "uid": "1", "code": "SAO", "name": "São Paulo" },
      "country":  { "uid": "6", "code": "BR",  "name": "Brasil" },
      "location": { "lat": "-23.5952979", "lon": "-46.6866818" },
      "timezone": "America/Sao_Paulo",
      "currencyCode": "BRL"
    },
    "storeFiscalConfig": {
      "enabled": true,
      "company": {
        "govIdType": "CNPJ",
        "govIdNumber": "00000000000000",
        "legalName": "Sandbox LTDA",
        "tradeName": "Sandbox"
      },
      "govIdType": "CNPJ",
      "govIdNumber": "00000000000000",
      "secondaryGovIdType": "INSCRICAO_ESTADUAL",
      "secondaryGovIdNumber": "000000000000",
      "metadata": {
        "neverstop":   { "url": "", "enabled": false },
        "storeCode3S": "50000001",
        "serialNumber": 1
      }
    }
  },
  "device": {
    "uid": "device_kiosk_001",
    "name": "KIOSK",
    "platform": "android",
    "metadata": { "ip": "10.0.0.0" }
  },
  "channel": {
    "uid": "c784d4ba-23c7-4929-b2f0-1a1960d9cdc2",
    "code": "KIOSK",
    "metadata": {}
  },
  "operator": {
    "uid": "op_001",
    "name": "Operator Name",
    "session": { "uid": "sess_001" }
  },
  "client": {
    "uid": "usr_consumidorfinal_001",
    "name": "CONSUMIDOR",
    "lastName": "FINAL",
    "email": "consumidor@example.com",
    "phone": "0000000000",
    "govIdType": "FINAL_CONSUMER",
    "govIdNumber": "00000000000",
    "externalId": null,
    "metadata": {
      "fiscal": null,
      "gender": "",
      "birthdate": ""
    },
    "billingInformation": {
      "email": "",
      "phone": "0000000000",
      "address": "",
      "govIdType": "FINAL_CONSUMER",
      "externalId": "",
      "govIdNumber": "00000000000",
      "businessName": ""
    }
  },
  "payments": {
    "totals": [
      {
        "taxes": [
          { "base": "229000", "name": "ICMS",   "rate": "0.04",   "amount": "9200",
            "metadata": { "cst": "90", "cBenef": "SP040100" } },
          { "base": "229000", "name": "PIS",    "rate": "0.0165", "amount": "3800",
            "metadata": { "cst": "01" } },
          { "base": "229000", "name": "COFINS", "rate": "0.076",  "amount": "17400",
            "metadata": { "cst": "01" } },
          { "base": "198700", "name": "IBS_UF",  "rate": "0.0006", "amount": "100",
            "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0.001, "rateEffective": 0.0006 } },
          { "base": "198700", "name": "IBS_MUN", "rate": "0",      "amount": "0",
            "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0, "rateEffective": 0 } },
          { "base": "198700", "name": "CBS",     "rate": "0.0054", "amount": "1100",
            "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0.009, "rateEffective": 0.0054 } }
        ],
        "total": "229000",
        "subtotal": "197400",
        "discounts": [
          { "priority": "1", "type": "FIXED", "value": "20000", "netPrice": "229000",
            "discountValue": "20000", "netPriceAfterDiscount": "209000" }
        ],
        "taxesValue": "31600",
        "currencyCode": "BRL",
        "discountValue": "20000",
        "subtotalBeforeTaxes": "197400"
      }
    ],
    "shippingCost": [
      { "total": "50000", "taxValue": "0", "currencyCode": "BRL",
        "subtotalWithoutTaxes": "50000", "subtotalIncludeDiscounts": "50000" }
    ],
    "extraCharges": [
      { "total": "15000", "taxValue": "0", "description": "Taxa de serviço", "currencyCode": "BRL",
        "subtotalWithoutTaxes": "15000", "subtotalIncludeDiscounts": "15000" }
    ],
    "discounts": [
      { "priority": "1", "type": "FIXED", "value": "20000", "netPrice": "229000",
        "discountValue": "20000", "netPriceAfterDiscount": "209000" }
    ],
    "paymentMethods": [
      {
        "mid": "",
        "tid": "",
        "processor": "CREDIT_CARD",
        "card": {
          "bin": "MASTERCARD",
          "mask": "",
          "brand": "MASTERCARD",
          "holder": "",
          "cardCountry": "",
          "lastFourDigits": "0000"
        },
        "acquirer": { "code": "00000000000000", "name": "ACQUIRER NAME", "cnpj": "01027058000191" },
        "voucher": "",
        "metadata": {},
        "totalBill": 22.9,
        "currencyCode": "BRL",
        "exactPayment": false,
        "transactionId": "tx_a1b2c3d4",
        "referenceNumber": null,
        "transactionDate": {
          "date": "2026-04-17T15:41:55.000Z",
          "timeZoneName": "America/Sao_Paulo"
        },
        "transactionType": "",
        "authorizationCode": "000000000000",
        "paymentMethodCode": "",
        "transactionStatus": "APPROVED",
        "customerCashAmount": "0",
        "idAuth": "952001",
        "receiptCustomer": "CUSTOMER RECEIPT\n---------------------------\nMASTERCARD ****0000\nAPPROVED\nAuth: 952001",
        "receiptMerchant": "MERCHANT RECEIPT\n---------------------------\nMASTERCARD ****0000\nAPPROVED\nAuth: 952001"
      }
    ],
    "metadata": {
      "fiscal": {
        "vBC":      "229000",
        "vNF":      "229000",
        "vCBS":     "1100",
        "vIBS":     "100",
        "vPIS":     "3800",
        "vDesc":    "0",
        "vICMS":    "9200",
        "vProd":    "229000",
        "vIBSUF":   "100",
        "vCOFINS":  "17400",
        "vIBSMun":  "0",
        "vTotTrib": "31600",
        "vBCIBSCBS":"198700"
      }
    }
  },
  "kds": {
    "metadata": {},
    "orderCode": "OC-br-001",
    "buzzerName": "Leonardo",
    "invoiceEmail": "",
    "invoicePrint": true
  },
  "metadata": {},
  "orderLines": [
    {
      "uid": "b9912637-eb44-4533-a1e5-f5bf2cdd07e8",
      "hash": "0d86fae2b5bc6198",
      "itemId": "39d1bd7fcd45c52f0c824364c2c0cfc402bd72b046cfaaec276a0131908dbf20",
      "itemType": "COMBO",
      "itemDescription": "Crunch Salad + Batata Pequena + 1 Tira + Refri",
      "quantity": "1",
      "selectedCurrency": "BRL",
      "updatedAt": "2026-05-06T01:22:59.663Z",
      "price": {
        "unitPrice": [
          {
            "taxes": [],
            "netPrice": "229000",
            "grossPrice": "229000",
            "currencyCode": "BRL",
            "discounts": [
              { "priority": "1", "type": "FIXED", "value": "15000", "netPrice": "229000",
                "discountValue": "15000", "netPriceAfterDiscount": "214000" }
            ],
            "discountValue": "15000",
            "taxesValue": "0",
            "subtotalBeforeTaxes": "229000"
          }
        ],
        "totalPrice": [
          {
            "taxes": [
              { "base": "229000", "name": "ICMS",   "rate": "0.04",   "amount": "9200",
                "metadata": { "cst": "90", "cBenef": "SP040100" } },
              { "base": "229000", "name": "PIS",    "rate": "0.0165", "amount": "3800",
                "metadata": { "cst": "01" } },
              { "base": "229000", "name": "COFINS", "rate": "0.076",  "amount": "17400",
                "metadata": { "cst": "01" } },
              { "base": "198700", "name": "IBS_UF",  "rate": "0.0006", "amount": "100",
                "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0.001, "rateEffective": 0.0006 } },
              { "base": "198700", "name": "IBS_MUN", "rate": "0",      "amount": "0",
                "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0, "rateEffective": 0 } },
              { "base": "198700", "name": "CBS",     "rate": "0.0054", "amount": "1100",
                "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0.009, "rateEffective": 0.0054 } }
            ],
            "netPrice": "197400",
            "grossPrice": "229000",
            "currencyCode": "BRL",
            "discounts": [
              { "priority": "1", "type": "FIXED", "value": "15000", "netPrice": "229000",
                "discountValue": "15000", "netPriceAfterDiscount": "214000" }
            ],
            "discountValue": "15000",
            "taxesValue": "31600",
            "subtotalBeforeTaxes": "197400"
          }
        ]
      },
      "lineTotals": [
        {
          "taxes": [
            { "base": "229000", "name": "ICMS",   "rate": "0.04",   "amount": "9200",  "metadata": { "cst": "90", "cBenef": "SP040100" } },
            { "base": "229000", "name": "PIS",    "rate": "0.0165", "amount": "3800",  "metadata": { "cst": "01" } },
            { "base": "229000", "name": "COFINS", "rate": "0.076",  "amount": "17400", "metadata": { "cst": "01" } },
            { "base": "198700", "name": "IBS_UF",  "rate": "0.0006", "amount": "100",  "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0.001, "rateEffective": 0.0006 } },
            { "base": "198700", "name": "IBS_MUN", "rate": "0",      "amount": "0",    "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0, "rateEffective": 0 } },
            { "base": "198700", "name": "CBS",     "rate": "0.0054", "amount": "1100", "metadata": { "cst": "200", "reducao": 0.4, "cClassTrib": "200047", "rateNominal": 0.009, "rateEffective": 0.0054 } }
          ],
          "total": "229000",
          "subtotal": "197400",
          "currencyCode": "BRL",
          "discounts": [
            { "priority": "1", "type": "FIXED", "value": "15000", "netPrice": "229000", "discountValue": "15000", "netPriceAfterDiscount": "214000" }
          ],
          "discountValue": "15000",
          "taxesValue": "31600",
          "subtotalBeforeTaxes": "197400"
        }
      ],
      "modifierGroups": [
        {
          "uid": "e247256ad628b0fd9c45453370e247fef1ad173829cc809c9c6930698d62e56b",
          "description": "Selecione: Escolha seus sanduíches!",
          "selectedModifiers": [
            {
              "itemId": "0104fdb2010be9ac14750a950f81c026b35a49a3c32b36281f41ef650d278b72",
              "itemType": "MODIFIER",
              "itemDescription": "CRUNCH SALAD",
              "quantity": "1",
              "selectedCurrency": "BRL",
              "price": { /* unitPrice / totalPrice arrays — same shape */ },
              "modifierGroups": [],
              "metadata": {
                "redeemed": false,
                "externalCode": "80229#900002186#91198"
              }
            }
          ]
        }
      ],
      "metadata": {
        "fiscal": {
          "ncm": "21069090",
          "cfop": "5101",
          "csosn": "500",
          "vTotTrib": 3.16,
          "fiscalCategoryCode": "2106.90.90"
        },
        "redeemed": false,
        "externalCode": "80229",
        "referenceUnitPrice": null,
        "referenceTotalPrice": null
      }
    }
  ],
  "fulfillment": {
    "service": { "uid": "726c4892-48b9-45da-b066-2a8e83d2cb78", "code": "DINE_IN", "metadata": {} },
    "pickup": {
      "prepDate": "2026-05-06T01:22:59.028Z",
      "prepTime": "",
      "pickupDate": "2026-05-06T01:22:59.028Z",
      "propertyId": "a4019cad-bbac-4269-9f8d-f29654e92c45",
      "prepTimeUnit": "minute"
    },
    "delivery": {
      "city": "São Paulo",
      "country": "Brasil",
      "zipCode": "",
      "latitude": "0",
      "nickName": "HOME",
      "longitude": "0",
      "reference": "",
      "mainStreet": "",
      "propertyId": 1,
      "deliveryDate": null,
      "secondaryStreet": "",
      "deliveryConfirmationCode": "IFOOD-7H3K9"
    }
  }
}
```

<Note>
  Money values are **strings holding the amount as an integer scaled ×10,000** — four fixed decimals. `"229000"` is **22.9 BRL**, not 229,000. To read it, divide by 10,000.

  It is the scale FIRE stores with: it avoids floating-point drift when summing taxes across several integrations. Parse with a decimal library, never `parseFloat`.

  The exception is `paymentMethods[].totalBill`, which the source sometimes ships as a JSON number — handle both cases.

  <Warning>
    **It is not the scale on every path.** The
    [fiscal numbering](/en/api-reference/fiscal-documents) request carries amounts **unscaled**, exactly as they were charged. If you take an amount from this event to declare it to the authority, divide first.
  </Warning>
</Note>

## Field reference

### Top-level identifiers

<ResponseField name="orderId" type="string">
  Fire's internal order UUID. Stable across deliveries; use together with `event.id` for traceability.
</ResponseField>

<ResponseField name="orderCode" type="string | null">
  Short, human-readable code shown on receipts and KDS displays (e.g. `95K`, `OC-br-001`). `null` when the channel doesn't assign one.
</ResponseField>

<ResponseField name="businessDayDate" type="string">
  Business day this order belongs to, in `YYYY-MM-DD`. Computed in store-local time, so an order placed at 01:00 may belong to the previous business day depending on the store's day-end cutoff.
</ResponseField>

<ResponseField name="externalOrderId" type="string">
  The order ID as provided by the channel/aggregator on injection. Use it when reconciling with upstream systems (POS, aggregator dashboards).
</ResponseField>

<ResponseField name="createdAt" type="string | null">
  ISO 8601 UTC timestamp of when the order was originally placed. Distinct from `event.createdAt`, which is when the flow execution started.
</ResponseField>

<ResponseField name="status" type="string">
  Always `"COMPLETED"` for this event.
</ResponseField>

<ResponseField name="paymentStatus" type="string">
  Always `"SUCCEEDED"` for this event.
</ResponseField>

<ResponseField name="redeemPoints" type="boolean">
  `true` if loyalty points were redeemed on this order.
</ResponseField>

<ResponseField name="accumulatePoints" type="boolean">
  `true` if the customer accumulated loyalty points.
</ResponseField>

<ResponseField name="discount" type="boolean">
  `true` if any discount was applied.
</ResponseField>

<ResponseField name="orderComment" type="string">
  Free-text customer note for the whole order. Empty string when not set.
</ResponseField>

### `data.store`

<ResponseField name="store" type="object">
  Snapshot of the store at the moment the order was completed.

  <Expandable title="store">
    <ResponseField name="uid" type="string | null">Store UUID in Fire.</ResponseField>
    <ResponseField name="externalId" type="string | null">Store ID in your external system, when mapped.</ResponseField>
    <ResponseField name="code" type="string | null">Store code (e.g. `BR-SP-001`). Use this to scope flows to specific stores.</ResponseField>
    <ResponseField name="name" type="string | null">Store display name.</ResponseField>
    <ResponseField name="phone" type="string | null">Store phone number.</ResponseField>
    <ResponseField name="address" type="string | null">Store street address.</ResponseField>

    <ResponseField name="locationInfo" type="object">
      Geographic context.

      <Expandable title="locationInfo">
        <ResponseField name="city" type="object">`{ uid, code, name }` — city identifiers.</ResponseField>
        <ResponseField name="country" type="object">`{ uid, code, name }` — `code` is ISO 3166-1 alpha-2 (`BR`, `EC`, `CO`, …).</ResponseField>
        <ResponseField name="location" type="object">`{ lat, lon }` as decimal-degree strings.</ResponseField>
        <ResponseField name="timezone" type="string | null">IANA timezone (e.g. `America/Sao_Paulo`).</ResponseField>
        <ResponseField name="currencyCode" type="string | null">ISO 4217 currency code (`BRL`, `USD`, …).</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="vendor" type="object">`{ uid, name, description, loyaltyPlan }` — brand metadata.</ResponseField>
    <ResponseField name="account" type="object">`{ uid, name, description }` — top-level account that owns the brand.</ResponseField>

    <ResponseField name="storeFiscalConfig" type="object | null">
      Fiscal configuration snapshot. **Only included when fiscal emission is enabled for the store.** See [Fiscal data](#fiscal-data) below.
    </ResponseField>
  </Expandable>
</ResponseField>

### `data.client`

<ResponseField name="client" type="object | null">
  Customer who placed the order. `null` for fully anonymous channel orders. When the sale **does not identify the buyer** —in any country— `client` travels populated with the final-consumer marker: `govIdType: "FINAL_CONSUMER"` and `govIdNumber` in zeros. **It does not arrive translated into each regime’s rule** — the DIAN’s generic NIT, for instance, is resolved by the fiscal provider.

  <Expandable title="client">
    <ResponseField name="uid" type="string | null">Customer ID from the authentication provider.</ResponseField>
    <ResponseField name="name" type="string | null">First name.</ResponseField>
    <ResponseField name="lastName" type="string | null">Last name.</ResponseField>
    <ResponseField name="email" type="string | null">Email address.</ResponseField>
    <ResponseField name="phone" type="string | null">Phone number.</ResponseField>
    <ResponseField name="govIdType" type="string | null">Customer tax/government ID type (`CPF`, `CNPJ`, `FINAL_CONSUMER`, …).</ResponseField>
    <ResponseField name="govIdNumber" type="string | null">Customer tax/government ID number.</ResponseField>
    <ResponseField name="externalId" type="string | null">Customer ID in an external system, when mapped.</ResponseField>

    <ResponseField name="metadata" type="object">
      <Expandable title="metadata">
        <ResponseField name="gender" type="string | null">Customer gender, when captured (often `""`).</ResponseField>
        <ResponseField name="birthdate" type="string | null">ISO date.</ResponseField>
        <ResponseField name="fiscal" type="object | null">**Brazil only.** Populated when `client.govIdType === "CNPJ"`. Contains `cep`, `tipoLogradouro`, `logradouro`, `numero`, `bairro`, `codigoCidade`, `descricaoCidade`, `estado`.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="billingInformation" type="object">Billing-specific overrides for invoicing. All fields optional; may be empty strings rather than `null`.</ResponseField>
  </Expandable>
</ResponseField>

### `data.payments`

<ResponseField name="payments" type="object">
  Money breakdown.

  <Expandable title="payments">
    <ResponseField name="totals" type="object[]">
      Order-level totals — usually one entry. All keys are camelCase (`total`, `subtotal`, `taxesValue`, `currencyCode`, `discountValue`, `subtotalBeforeTaxes`, plus the `taxes[]` and `discounts[]` arrays).

      Each entry has: `total`, `subtotal`, `taxes[]`, `discounts[]`, `taxesValue`, `currencyCode`, `discountValue`, `subtotalBeforeTaxes`.

      `taxes[n]` shape: `{ base, name, rate, amount, metadata }`. `name` values: legacy `ICMS`, `PIS`, `COFINS` **plus the BR tax-reform taxes** `IBS_UF`, `IBS_MUN`, `CBS`. `metadata` carries country-specific tax codes (`cst`, `cBenef`, and for IBS/CBS: `cClassTrib`, `reducao`, `rateNominal`, `rateEffective`).
    </ResponseField>

    <ResponseField name="shippingCost" type="object[]">Shipping cost as PriceBlock rows (same shape as `totals[]`: `total`, `taxValue`, `currencyCode`, `subtotalWithoutTaxes`, `subtotalIncludeDiscounts`, …, ×10000 strings). Empty for in-store orders.</ResponseField>
    <ResponseField name="extraCharges" type="object[]">Service charge ("Taxa de serviço"), tips, packing fees and other add-ons — same PriceBlock shape, plus an optional `description`.</ResponseField>

    <ResponseField name="discounts" type="object[]">
      <Tip>Added in **v1**.</Tip>
      Order-level discount entries. Each entry is a **Discount** object:

      <Expandable title="Discount">
        <ResponseField name="priority" type="string">Application order when multiple discounts stack (e.g. `"1"`).</ResponseField>
        <ResponseField name="type" type="string">`FIXED` or `PERCENTAGE`.</ResponseField>
        <ResponseField name="value" type="string">Discount amount (spec-scale ×10000 string).</ResponseField>
        <ResponseField name="netPrice" type="string">Net price before this discount (×10000).</ResponseField>
        <ResponseField name="discountValue" type="string">Resolved discount amount applied (×10000).</ResponseField>
        <ResponseField name="netPriceAfterDiscount" type="string">Net price after the discount (×10000).</ResponseField>
      </Expandable>

      The same **Discount** shape also appears in `payments.totals[].discounts` (order-level) and in `orderLines[].price.unitPrice/totalPrice[].discounts` + `orderLines[].lineTotals[].discounts` (per-product discounts).
    </ResponseField>

    <ResponseField name="paymentMethods" type="object[]">
      Methods used to pay. Most fields are camelCase (`totalBill`, `currencyCode`, `transactionId`, `transactionStatus`, `paymentMethodCode`, …) and the `card` sub-object is camelCase too (`card.cardCountry`, `card.lastFourDigits`, `card.externalCardBrandId`).

      Each entry: `processor`, `currencyCode`, `paymentMethodCode`, `transactionType`, `transactionId`, `transactionStatus`, `exactPayment`, `totalBill`, `acquirer`, `card`, `transactionDate`, `metadata`, `mid`, `tid`, `voucher`, `referenceNumber`, `authorizationCode`, `customerCashAmount`, `idAuth`, `receiptCustomer`, `receiptMerchant`.

      New fields (all nullable):

      * **`idAuth`** (`string | null`) — Authorization ID from the payment processor (e.g. SiTef `IdAuth`). Distinct from `authorizationCode`.
      * **`receiptCustomer`** (`string | null`) — Full customer-facing receipt text; may be multi-line (newline-separated).
      * **`receiptMerchant`** (`string | null`) — Full merchant-facing receipt text; may be multi-line.
      * **`acquirer.cnpj`** (`string | null`) — Tax ID (CNPJ) of the payment acquirer. Populated for Brazil only; `null` otherwise.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      <Expandable title="metadata">
        <ResponseField name="fiscal" type="object | null">Aggregate fiscal totals. See [Fiscal data](#fiscal-data) below.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

### `data.fulfillment`

<ResponseField name="fulfillment" type="object">
  How the order is being delivered.

  <Expandable title="fulfillment">
    <ResponseField name="service" type="object">`{ uid, code, metadata }` — `code` is `DELIVERY`, `TAKEAWAY`, `PICKUP`, or `DINE_IN`.</ResponseField>

    <ResponseField name="pickup" type="object | null">
      Populated for `PICKUP`/`TAKEAWAY`/`DINE_IN`. Contains `prepDate`, `pickupDate` (both ISO 8601 UTC), `prepTime`, `prepTimeUnit`, `propertyId`.
    </ResponseField>

    <ResponseField name="delivery" type="object | null">
      Populated for `DELIVERY`. Address fields plus `deliveryDate`. **Note:** the `delivery` object may also be present (with placeholder values like `latitude: "0"`) on non-delivery services — branch on `service.code`, not on `delivery !== null`.

      <ResponseField name="deliveryConfirmationCode" type="string | null">
        <Tip>Added in **v1**.</Tip> Aggregator delivery/pickup confirmation code (e.g. iFood / Rappi). Sourced from the inbound `shippingMethod.delivery.metadata.deliveryConfirmationCode`.
      </ResponseField>
    </ResponseField>
  </Expandable>
</ResponseField>

### `data.kds`

<ResponseField name="kds" type="object">
  Kitchen-display context.

  <Expandable title="kds">
    <ResponseField name="buzzerName" type="string">Buzzer or pager identifier. Empty string when not set.</ResponseField>
    <ResponseField name="invoiceEmail" type="string">Customer email for invoice copy. Empty string when not captured.</ResponseField>
    <ResponseField name="invoicePrint" type="boolean | null">Whether the kitchen should print the invoice copy.</ResponseField>
    <ResponseField name="orderCode" type="string">Mirrors top-level `orderCode`.</ResponseField>
    <ResponseField name="metadata" type="object">Channel-specific KDS extras.</ResponseField>
  </Expandable>
</ResponseField>

### `data.device` and `data.operator`

<ResponseField name="device" type="object">`{ uid, name, platform, metadata.ip }` — originating device. Fields may be `null` for non-physical channels.</ResponseField>

<ResponseField name="operator" type="object">`{ uid, name, session.uid }` — staff/cashier who processed the order. All fields `null` for self-service channels (kiosk, web).</ResponseField>

### `data.orderLines`

<ResponseField name="orderLines" type="object[]">
  Ordered products. Fully camelCase (transformed by the V4 builder).

  <Expandable title="orderLines[n]">
    <ResponseField name="uid" type="string">Line UUID.</ResponseField>
    <ResponseField name="hash" type="string">Stable hash for this line — useful for dedup if you fan out lines downstream.</ResponseField>
    <ResponseField name="itemId" type="string">Product identifier.</ResponseField>

    <ResponseField name="itemType" type="string">
      Item classification — one of `PRODUCT`, `COMBO`, `MODIFIER`, `PACKAGING`. <Tip>Full enum documented in **v1**.</Tip> Passthrough from the source; falls back to `PRODUCT` when the channel doesn't send a type.

      <Expandable title="itemType values">
        <ResponseField name="PRODUCT" type="enum">A standalone sellable item — the line **is** the product (e.g. a burger sold on its own, a bottled drink). Default fallback when no type is sent.</ResponseField>
        <ResponseField name="COMBO" type="enum">A bundle/container. Its priced components live inside `modifierGroups[].selectedModifiers[]` (e.g. "Combo - Kentucky Onion" = sandwich + fries + drink). The combo line's `total` is the bundle price; the components carry the per-item detail.</ResponseField>
        <ResponseField name="MODIFIER" type="enum">An add-on or option chosen within a product/combo (e.g. extra cheese, choice of side, drink upgrade, "remove bacon"). Appears nested under a parent line's `modifierGroups`.</ResponseField>
        <ResponseField name="PACKAGING" type="enum">A packaging line (bag, box, cup, container). Itemized separately for markets that bill/track packaging for fiscal or inventory purposes.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="itemDescription" type="string">Display name.</ResponseField>
    <ResponseField name="quantity" type="string">String integer (e.g. `"1"`, `"2"`).</ResponseField>
    <ResponseField name="selectedCurrency" type="string">ISO 4217 (e.g. `BRL`).</ResponseField>
    <ResponseField name="updatedAt" type="string">ISO 8601 UTC.</ResponseField>

    <ResponseField name="price" type="object">
      `{ unitPrice: PriceEntry[], totalPrice: PriceEntry[] }`. Both are **arrays** to support multi-currency totals (today usually one entry).

      `PriceEntry` keys: `currencyCode`, `grossPrice`, `netPrice`, `subtotalBeforeTaxes`, `discountValue`, `discounts[]`, `taxesValue`, `taxes[]`. Tax entries have `{ base, name, rate, amount, metadata }`.

      <Note>**Taxes** live on **`totalPrice`** / `lineTotals` only — `unitPrice.taxes[]` is normally empty (`taxesValue: "0"`), because taxes are computed on the line total, not per unit. **Discounts** behave differently: they appear on **both** `unitPrice` and `totalPrice` (`discounts[]` + `discountValue`). So a `unitPrice` entry with a populated `discounts[]` **and** an empty `taxes[]` is expected — not a bug. Read the tax breakdown from `totalPrice[].taxes[]` / `lineTotals[].taxes[]`.</Note>
    </ResponseField>

    <ResponseField name="lineTotals" type="object[]">Same shape as `price.totalPrice[]`.</ResponseField>

    <ResponseField name="modifierGroups" type="object[]">
      Selected modifier groups. Each: `{ uid, description, selectedModifiers[] }`. `selectedModifiers[n]` is recursively shaped like an order line (price, modifierGroups, itemDescription, …) up to a few levels deep.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Per-line metadata. May contain `fiscal: { ncm, cfop, csosn, vTotTrib, fiscalCategoryCode }` for BR fiscal classification, plus `redeemed`, `externalCode`, `referenceUnitPrice`, `referenceTotalPrice`.
    </ResponseField>
  </Expandable>
</ResponseField>

### `data.marketing`, `data.metadata`, `data.channel`

<ResponseField name="marketing" type="object | null">Loyalty + coupons. `null` in most countries today; reserved for future use.</ResponseField>

<ResponseField name="metadata" type="object">Free-form bag for order-level extras. Often `{}`.</ResponseField>

<ResponseField name="channel" type="object">`{ uid, code, metadata }`. `code` examples: `KIOSK`, `APP`, `IFOOD`, `RAPPI`.</ResponseField>

## Fiscal data

<Note>
  Fiscal data is included **only when the store has fiscal emission enabled** (`store.storeFiscalConfig.enabled === true`). For non-fiscal countries or stores without configuration, all three locations below are absent or `null`.
</Note>

`order.completed` carries fiscal information in **three** distinct locations. Each serves a different purpose:

### 1. `data.store.storeFiscalConfig` — emitter identity & provider config

Identifies the legal entity emitting the document and how to authenticate with the fiscal provider. **Credentials are intentionally NOT here** — the fiscal node fetches them per provider/account.

```json theme={null}
"storeFiscalConfig": {
  "enabled": true,
  "company": {
    "govIdType":   "CNPJ",
    "govIdNumber": "00000000000000",
    "legalName":   "Sandbox LTDA",
    "tradeName":   "Sandbox"
  },
  "govIdType":            "CNPJ",
  "govIdNumber":          "00000000000000",
  "secondaryGovIdType":   "INSCRICAO_ESTADUAL",
  "secondaryGovIdNumber": "000000000000",
  "metadata": {
    "neverstop":    { "url": "", "enabled": false },
    "storeCode3S":  "50000001",
    "serialNumber": 1
  }
}
```

### 2. `data.payments.metadata.fiscal` — order-level fiscal aggregates

SEFAZ-style aggregate totals, ready to be forwarded to a fiscal provider (your fiscal provider in Brazil). Values are strings scaled ×10,000, same as the rest of the event.

```json theme={null}
"metadata": {
  "fiscal": {
    "vBC":      "229000",
    "vNF":      "229000",
    "vICMS":    "9200",
    "vPIS":     "3800",
    "vCOFINS":  "17400",
    "vCBS":     "1100",
    "vIBS":     "100",
    "vIBSUF":   "100",
    "vIBSMun":  "0",
    "vTotTrib": "31600",
    "vBCIBSCBS":"198700",
    "vDesc":    "0",
    "vProd":    "229000"
  }
}
```

### 3. `data.orderLines[n].metadata.fiscal` — per-line fiscal classification

Per-product fiscal codes. Used by the fiscal provider to classify each line on the document.

```json theme={null}
"metadata": {
  "fiscal": {
    "ncm":               "21069090",
    "cfop":              "5101",
    "csosn":             "500",
    "vTotTrib":          3.16,
    "fiscalCategoryCode":"2106.90.90"
  }
}
```

In addition, **per-tax metadata** lives inside each `taxes[n].metadata` (in `payments.totals[].taxes[]`, `orderLines[].price.totalPrice[].taxes[]`, and `orderLines[].lineTotals[].taxes[]`) with codes like `cst`, `cBenef`, `cClassTrib`, `reducao`, `rateNominal`, `rateEffective`.

## Country variations

The example above is from a Brazilian store — the most complex case. The V4 shape is identical across countries, **including the granular `taxes[]` breakdown**: every country populates `payments.totals[].taxes[]`, `orderLines[].price.totalPrice[].taxes[]` and `lineTotals[].taxes[]` with its **own local taxes** in the same `{ base, name, rate, amount, metadata }` shape. What differs per country is:

* **Tax names** — BR uses `ICMS`, `PIS`, `COFINS`, `IBS_UF`, `IBS_MUN`, `CBS`; other countries carry their local taxes (e.g. `IVA`) under the same structure.
* **`metadata` codes** inside each tax — BR carries SEFAZ codes (`cst`, `cBenef`, `cClassTrib`, `reducao`, `rateNominal`, `rateEffective`); other countries carry their own jurisdiction's codes.
* **SEFAZ fiscal-document emission — Brazil only.** The NF-e aggregate `payments.metadata.fiscal` (vBC / vNF / vICMS …), the per-line `orderLines[].metadata.fiscal` (ncm / cfop / csosn), and the `order.invoiced` / `order.reversed` events fire **only for BR**. Non-BR countries still carry their `taxes[]` breakdown, but these SEFAZ-specific blocks are absent.

<Note>
  The BR sample above is a real (anonymized) capture. The LATAM samples below are **illustrative**: `<...>` are example IDs, and fields shown as `null` are **genuinely not-applicable** for that country (e.g. `secondaryGovIdType` — only BR has the Inscrição Estadual; `metadata.fiscal` — only BR emits SEFAZ documents).
</Note>

<Tabs>
  <Tab title="Brazil (BR)">
    Brazilian stores with `storeFiscalConfig.enabled === true` carry the full fiscal payload — see the [Fiscal data](#fiscal-data) section above. Country markers:

    * `store.locationInfo.country.code: "BR"` · `name: "Brasil"` · `timezone: "America/Sao_Paulo"`
    * `store.locationInfo.currencyCode: "BRL"`
    * `store.storeFiscalConfig.govIdType: "CNPJ"` (14 digits)
    * `store.storeFiscalConfig.secondaryGovIdType: "INSCRICAO_ESTADUAL"`
    * `payments.totals[].currencyCode: "BRL"`, `paymentMethods[].currencyCode: "BRL"`, `orderLines[].selectedCurrency: "BRL"`
    * **Populated:** `payments.metadata.fiscal` (vBC / vNF / vICMS / vPIS / vCOFINS / vTotTrib …), `orderLines[].metadata.fiscal` (ncm / cfop / csosn), `lineTotals[].taxes[]` (ICMS, PIS, COFINS, IBS\_\*)
  </Tab>

  <Tab title="Argentina (AR)">
    Argentine stores carry their **`IVA` in `taxes[]`** (granular, same `{ base, name, rate, amount }` shape as BR) but **no Brazilian SEFAZ emission** — `metadata.fiscal` is `null` and no `fiscal.*` event fires. Compact sample of the country-specific fields:

    ```json theme={null}
    {
      "store": {
        "code": "AR-BUE-001",
        "locationInfo": {
          "city":     { "uid": "<uid>", "code": "<code>", "name": "Buenos Aires" },
          "country":  { "uid": "<uid>", "code": "AR",      "name": "Argentina" },
          "currencyCode": "ARS",
          "timezone": "America/Argentina/Buenos_Aires"
        },
        "storeFiscalConfig": {
          "enabled": true,
          "govIdType": "CUIT",
          "govIdNumber": "30-12345678-9",
          "secondaryGovIdType": null,
          "secondaryGovIdNumber": null,
          "company": {
            "govIdType": "CUIT",
            "govIdNumber": "30-12345678-9",
            "legalName": "Your Company SRL",
            "tradeName": "Your Brand"
          },
          "metadata": {}
        }
      },
      "payments": {
        "totals": [
          {
            "currencyCode": "ARS",
            "total": "100000",
            "subtotal": "82645",
            "taxes": [
              { "base": "82645", "name": "IVA", "rate": "0.21", "amount": "17355" }
            ],
            "taxesValue": "17355",
            "discounts": [],
            "discountValue": "0",
            "subtotalBeforeTaxes": "82645"
          }
        ],
        "metadata": { "fiscal": null }
      },
      "orderLines": [
        {
          "selectedCurrency": "ARS",
          "metadata": { "fiscal": null },
          "lineTotals": [{ "currencyCode": "ARS", "total": "100000", "taxes": [
            { "base": "82645", "name": "IVA", "rate": "0.21", "amount": "17355" }
          ] }]
        }
      ]
    }
    ```

    `store.locationInfo.currencyCode` is populated (`ARS`) — same as BR's behavior. You can also read it from `payments.totals[0].currencyCode` or `orderLines[0].selectedCurrency` if needed; they all match.
  </Tab>

  <Tab title="Chile (CL)">
    Same shape as Argentina with `RUT` as the gov ID type and `CLP` as currency:

    ```json theme={null}
    {
      "store": {
        "code": "CL-SCL-001",
        "locationInfo": {
          "country": { "code": "CL", "name": "Chile" },
          "currencyCode": "CLP",
          "timezone": "America/Santiago"
        },
        "storeFiscalConfig": {
          "enabled": true,
          "govIdType": "RUT",
          "govIdNumber": "76123456-7",
          "company": {
            "govIdType": "RUT",
            "govIdNumber": "76123456-7",
            "legalName": "Your Company SpA",
            "tradeName": "Your Brand"
          }
        }
      },
      "payments": {
        "totals": [{ "currencyCode": "CLP", "total": "10000", "taxes": [{ "base": "8403", "name": "IVA", "rate": "0.19", "amount": "1597" }] }],
        "metadata": { "fiscal": null }
      },
      "orderLines": [{ "selectedCurrency": "CLP", "metadata": { "fiscal": null } }]
    }
    ```
  </Tab>

  <Tab title="Colombia (CO)">
    Colombian stores with `NIT` as the gov ID type and `COP` as currency. Legal entity suffix typically `SAS`. No fiscal aggregates today (DIAN integration is at schema level only — see [`POST /v1/webhooks/fiscal/callback`](/en/api-reference/fiscal-callback)):

    ```json theme={null}
    {
      "store": {
        "code": "CO-BOG-001",
        "locationInfo": {
          "country": { "code": "CO", "name": "Colombia" },
          "currencyCode": "COP",
          "timezone": "America/Bogota"
        },
        "storeFiscalConfig": {
          "enabled": true,
          "govIdType": "NIT",
          "govIdNumber": "900123456-7",
          "company": {
            "govIdType": "NIT",
            "govIdNumber": "900123456-7",
            "legalName": "Your Company SAS",
            "tradeName": "Your Brand"
          }
        }
      },
      "payments": {
        "totals": [{ "currencyCode": "COP", "total": "10000", "taxes": [{ "base": "8403", "name": "IVA", "rate": "0.19", "amount": "1597" }] }],
        "metadata": { "fiscal": null }
      },
      "orderLines": [{ "selectedCurrency": "COP", "metadata": { "fiscal": null } }]
    }
    ```
  </Tab>

  <Tab title="Ecuador (EC)">
    Ecuadorian stores with `RUC` (13 digits) as the gov ID type. **Currency is `USD`** (Ecuador's official currency, no local tender). Legal entity suffix typically `Cia. Ltda.` or `S.A.`:

    ```json theme={null}
    {
      "store": {
        "code": "EC-UIO-001",
        "locationInfo": {
          "country": { "code": "EC", "name": "Ecuador" },
          "currencyCode": "USD",
          "timezone": "America/Guayaquil"
        },
        "storeFiscalConfig": {
          "enabled": true,
          "govIdType": "RUC",
          "govIdNumber": "1790012345001",
          "company": {
            "govIdType": "RUC",
            "govIdNumber": "1790012345001",
            "legalName": "Your Company Cia. Ltda.",
            "tradeName": "Your Brand"
          }
        }
      },
      "payments": {
        "totals": [{ "currencyCode": "USD", "total": "10000", "taxes": [{ "base": "8696", "name": "IVA", "rate": "0.15", "amount": "1304" }] }],
        "metadata": { "fiscal": null }
      },
      "orderLines": [{ "selectedCurrency": "USD", "metadata": { "fiscal": null } }]
    }
    ```
  </Tab>

  <Tab title="Venezuela (VE)">
    Same shape with `RIF` as the gov ID type and `VES` as currency:

    ```json theme={null}
    {
      "store": {
        "code": "VE-CCS-001",
        "locationInfo": {
          "country": { "code": "VE", "name": "Venezuela" },
          "currencyCode": "VES",
          "timezone": "America/Caracas"
        },
        "storeFiscalConfig": {
          "enabled": true,
          "govIdType": "RIF",
          "govIdNumber": "J-12345678-9",
          "company": {
            "govIdType": "RIF",
            "govIdNumber": "J-12345678-9",
            "legalName": "Your Company CA",
            "tradeName": "Your Brand"
          }
        }
      },
      "payments": {
        "totals": [{ "currencyCode": "VES", "total": "1000", "taxes": [{ "base": "862", "name": "IVA", "rate": "0.16", "amount": "138" }] }],
        "metadata": { "fiscal": null }
      },
      "orderLines": [{ "selectedCurrency": "VES", "metadata": { "fiscal": null } }]
    }
    ```
  </Tab>
</Tabs>

### Quick reference table

| Country         | `country.code` | Currency (effective)                | `govIdType` (format)     | Fiscal aggregates           |
| --------------- | -------------- | ----------------------------------- | ------------------------ | --------------------------- |
| Brazil          | `BR`           | `BRL`                               | `CNPJ` (14 digits)       | Yes — full SEFAZ aggregates |
| Argentina       | `AR`           | `ARS`                               | `CUIT` (`XX-XXXXXXXX-X`) | No — `null` / empty         |
| Chile           | `CL`           | `CLP`                               | `RUT` (`XXXXXXXX-X`)     | No                          |
| Colombia        | `CO`           | `COP`                               | `NIT` (`XXXXXXXXX-X`)    | No                          |
| Ecuador         | `EC`           | `USD` (Ecuador's official currency) | `RUC` (13 digits)        | No                          |
| Venezuela       | `VE`           | `VES`                               | `RIF` (`J-XXXXXXXX-X`)   | No                          |
| Other countries | varies         | varies                              | varies                   | No                          |

<Note>
  As more countries get a dedicated fiscal pipeline, their fiscal events will land as `fiscal.*.{cc}` (e.g. `fiscal.authorized.co`, `fiscal.authorized.ec`). Until then, only `order.completed` and `order.cancelled` fire for non-BR stores — fiscal blocks remain `null` / empty.
</Note>

## `data.policy` and `data.lastKnown`

Every order event carries these two blocks — not just this one. They were added
together with the deferred-payment cycle and are **added in v1.1**, additive: existing
consumers keep working unchanged.

| Block                    | What it is                                                                                                                                        | Trust it?                                        |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| `policy.deferredPayment` | Whether the order may be acted on **before** payment. Resolved once at injection and stamped immutably — every later event echoes the same value. | Yes. It is a decision, not a state.              |
| `lastKnown`              | Advisory snapshot of kitchen (`kds`) and fiscal state when the event was emitted. May be `null` or stale.                                         | **No.** Never gate an irreversible action on it. |

```json theme={null}
"policy": { "deferredPayment": { "eligible": true, "resolvedAt": "2026-08-02T15:55:42.407Z",
    "configVersion": "fnv1a:3144c6fb",
    "resolvedFrom": { "channelCode": "APP", "fulfillmentCode": "DELIVERY", "paymentMethod": "CASH" } } },
"lastKnown": { "kds": null, "fiscal": { "status": "processing", "sourceEvent": "fiscal.callback" } }
```

Field-by-field detail lives in [`order.opened`](/en/events/order-opened#deferred-payment-policy),
the event where these blocks matter most.

## Handler example

```js theme={null}
async function onOrderCompleted(data) {
  const {
    orderId,
    externalOrderId,
    store,
    payments,
    orderLines,
    fulfillment,
    createdAt,
  } = data;

  // 1. Persist for accounting / analytics
  await db.orders.upsert({
    where: { fireOrderId: orderId },
    create: {
      fireOrderId: orderId,
      externalOrderId,
      storeCode: store.code,
      country: store.locationInfo.country.code,
      currency: store.locationInfo.currencyCode,
      // payments.totals[0].total is "229000" is scaled ×10,000 → 22.9
      totalMinorUnits: BigInt(payments.totals[0]?.total ?? "0"),
      completedAt: new Date(createdAt ?? Date.now()),
      service: fulfillment.service.code,
    },
    update: {},
  });

  // 2. If fiscal-enabled, dispatch to fiscal pipeline
  if (store.storeFiscalConfig?.enabled) {
    await fiscalPipeline.enqueue({
      orderId,
      country: store.locationInfo.country.code,
      emitter: store.storeFiscalConfig.company,
      aggregates: payments.metadata?.fiscal,
      lines: orderLines.map((l) => ({
        itemId: l.itemId,
        ncm: l.metadata?.fiscal?.ncm,
        cfop: l.metadata?.fiscal?.cfop,
      })),
    });
  }

  // 3. If delivery, dispatch to logistics
  if (fulfillment.service.code === "DELIVERY" && fulfillment.delivery) {
    await dispatcher.send({
      orderId,
      address: fulfillment.delivery,
      items: orderLines,
    });
  }
}
```

## Common pitfalls

* **Decimals as strings × 10000.** `payments.totals[0].total === "229000"` means 22.9 BRL. Use a decimal library; never `parseFloat`.
* **Casing is mixed in `payments.totals[]` and parts of `paymentMethods[]`.** Read both `currencyCode` and `currencyCode` defensively. The V4 builder transforms most of the snapshot but passes payment objects through.
* **`fulfillment.delivery` may be present even for non-delivery services** with placeholder zeroes. Always branch on `fulfillment.service.code`.
* **`client` may be a populated "FINAL\_CONSUMER" placeholder** in any country — it is not `null`. Treat `govIdType === "FINAL_CONSUMER"` as anonymous for analytics.
* **`event.id` is the flow execution ID, not the order ID.** Use `event.id` for idempotency (it changes per delivery), and `orderId` for business key.
* **Multi-tenant routing.** Use `store.account.uid`, `store.vendor.uid`, and `store.code` to route to the right tenant in your system, even though Fire already scopes the flow on its side.

## Related events

<CardGroup cols={2}>
  <Card title="order.cancelled" icon="ban" href="/en/events/order-cancelled">
    Fires when this order is later cancelled.
  </Card>

  <Card title="order.invoiced" icon="file-invoice" href="/en/events/order-invoiced">
    Brazil only — fires once SEFAZ authorizes the order's fiscal document.
  </Card>
</CardGroup>

## `data.fiscalRepresentation`

The **fiscal numbering** the point of sale obtained *before* injecting the order:
it charges, requests the identifiers, prints the receipt, and only then injects.
That is why it travels on the order and not in a separate fiscal event — by the
time the order is born, this already happened.

<Warning>
  **The presence of this block does NOT mean the document is authorized.** These
  are the numbers printed at the till; the tax authority's verdict is in
  `lastKnown.fiscal.status`. A ticket that says "authorized" just because the
  block is present states something that may never have happened.
</Warning>

**The key always travels.** It arrives as `null` when numbering was not
attempted — aggregators, countries without fiscal representation, or merchants
with numbering turned off — and carries the block when it was.

Carrying the block means **numbering was attempted, not that it succeeded**:
`numberingStatus` tells you how the attempt ended, and `failure` why, when it did
not end well.

Branch on the value, not on the key's presence:

```js theme={null}
if (data.fiscalRepresentation) {
  // numbering was attempted — read numberingStatus to see how it went
}
```

| Field               | What it is                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `numberingStatus`   | How the **numbering act** ended: `GENERATED`, `PENDING`, `FAILED_RETRYABLE`, `FAILED_FINAL`, `UNAVAILABLE`. **Not the authority's verdict** — that lives in `lastKnown.fiscal.status`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `documentNumber`    | The receipt's visible number, composed per country (`005-004-000000042`). It is presentation and **Fire builds it**, not the authority: reconcile with `countryData`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `issuedAt`          | When it was **numbered**. Not the authorization date.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `authorizationMode` | `ONLINE`, `OFFLINE` or `BATCH`. A provider concept, not universal.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `providerCode`      | Identifier of the adapter that numbered.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `countryData`       | The authority identifiers, in the vocabulary of the **country that numbered** — and only that country's. Ecuador: `numeroComprobante` (the human-readable document number, already assembled by the provider), `claveAcceso`, `establecimiento`, `puntoEmision`, `secuencial`, `ambiente`. Venezuela: `numeroControl`, `numeroFactura`, `serie`. **Iterate it; do not index blindly** — a new key here is not a breaking change. It is the same block the numbering endpoint returns and the authority callback carries. The per-country reference, with each regime's keys, is in [`countryData` by country](/en/api-reference/fiscal-documents#countrydata-by-country). |
| `graphic`           | The printable artifact the provider returned (QR and the like), verbatim. `null` if it returned none.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `failure`           | Why there is **no** receipt. `null` when numbering succeeded.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `providerIdentity`  | **Who numbered, on the provider's side**: `{ "name": "hio.fiscalization", "version": "2026.08.1", "reference": "HIO-91f3c2" }`. Unlike the bag below, **it has a shape**: all three fields are part of the contract and always come through, with `null` when they do not apply. `reference` is **the provider's own support reference** — the identifier you quote back to them so they can find the operation in their records; it is not the `Idempotency-Key` the channel sent. It does not carry `providerCode`: that one is ours and travels at the top.                                                                                                            |
| `providerMetadata`  | **The provider's diagnostic bag**, exactly as it returned it: in Ecuador with HIO you get `{ "deviceUid": "4B8E…", "externalStoreCode": "K000" }`. It is **opaque** — the provider owns the keys and may change them without notice, so do not program against them; it is for pasting into a ticket, not for branching. **It is exactly the same field the numbering endpoint returns**, same name and same content: all three provider fields read the same at both ends.                                                                                                                                                                                               |
| `environment`       | Which environment **Fire** numbered in: `SANDBOX` or `PRODUCTION`. It is ours, not the authority's — the authority's travels inside `countryData` with the country's own code.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `compensates`       | Which document this one voids. Present **only** when `documentType` is `CREDIT_NOTE`. It is a **pointer**, not a copy: look its `documentNumber` up in `history` for the whole document. `reason` is the canonical code — the printed wording is authored per company and resolved in the numbering endpoint's response.                                                                                                                                                                                                                                                                                                                                                  |
| `history`           | The order's **previous** documents, oldest first. Empty while there was only one; when a cancellation numbers, the invoice moves down here and the credit note sits on top. Every entry has **the same shape** as the block above, so they read alike. Documents only: a failed attempt does not appear.                                                                                                                                                                                                                                                                                                                                                                  |

```json theme={null}
"fiscalRepresentation": {
  "numberingStatus": "GENERATED",
  "documentNumber": "005-004-000000042",
  "countryData": {
    "numeroComprobante": "005-004-000000042",
    "claveAcceso": "1208202601000000000000110050040000000421234567810",
    "establecimiento": "005",
    "puntoEmision": "004",
    "secuencial": "000000042",
    "ambiente": "2"
  },
  "authorizationMode": "ONLINE",
  "issuedAt": "2026-08-13T08:11:29.744Z",
  "providerCode": "hio",
  "graphic": { "qr": "1208202601000000000000110050040000000421234567810" },
  "failure": null,
  "providerIdentity": { "name": "hio.fiscalization", "version": "2026.08.1", "reference": "HIO-91f3c2" },
  "providerMetadata": { "deviceUid": "4B8E21F9A0D35C7A", "externalStoreCode": "K004" },
  "environment": "PRODUCTION",
  "compensates": null,
  "history": []
}
```

**The authority's verdict does not alter it.** What the customer took home
printed does not change because the authority later authorizes or rejects — that
is what `lastKnown.fiscal` is for, and that is what does move.

**What does replace it is a new document.** The block carries the order's
**current** fiscal document. While there was only one, it was always the invoice;
when a cancellation produces a credit note, the note is what sits on top —
`documentType` says which one — and the invoice **moves down into `history`**,
whole and with its own authority identifiers. It is not lost: it moves.
`compensates` points at it by number, so the relationship stays explicit.

### When numbering fails

A sale can be charged and end up **with no fiscal receipt**. That case travels
too, and you must handle it: the identifiers come back `null` and the reason is
in `failure`.

```json theme={null}
"fiscalRepresentation": {
  "numberingStatus": "FAILED_FINAL",
  "documentNumber": null,
  "issuedAt": null,
  "providerCode": "hio",
  "graphic": null,
  "failure": { "code": "RUC_INVALIDO", "scope": "FUNCTIONAL", "message": "Tax ID not enabled" }
}
```

Branch on `failure.scope`:

* **`TECHNICAL`** — print "pending" and carry on. It may resolve on its own.
* **`FUNCTIONAL`** — some data is wrong and retrying will not fix it. Needs correction.

<Note>
  **`lastKnown.fiscal.sourceEvent` now reports real provenance.** It used to be
  derived from the status, so a `processing` seeded at injection was reported as
  `fiscal.callback` even though no callback had occurred. That case now says
  `order.injected`. If you branch on this field, account for the new value.
</Note>
