> ## 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.opened

> Um pedido foi injetado e está ABERTO — ele existe, mas ninguém pagou ainda. A porta de entrada do pagamento diferido: cozinhar, faturar ou despachar antes do dinheiro chegar.

<Tabs>
  <Tab title="v1.1 · atual">
    Você está lendo o contrato **atual (v1.1)** de `order.opened`. **v1.1 adiciona** `data.fiscalRepresentation`: a numeração fiscal que o ponto de venda obteve antes de injetar o pedido. Viaja **sempre**: em `null` quando não se tentou numerar, e preenchido quando sim — `numberingStatus` diz como terminou. Trazer conteúdo **não** significa que o comprovante esteja autorizado. Apenas aditivo — nada do que você já lia mudou.

    O bloco carrega o documento fiscal **vigente** do pedido: os campos que significam o mesmo em qualquer país no topo, os identificadores do órgão dentro de `countryData` no vocabulário do seu país, e os documentos anteriores em `history`. Quando um cancelamento numera, a nota de crédito passa ao topo e a de venda desce para o histórico — com `compensates` apontando para ela.
  </Tab>

  <Tab title="v1 · anterior">
    O contrato **v1** continua válido: v1.1 apenas soma um bloco, nada do anterior mudou.
  </Tab>
</Tabs>

`order.opened` dispara quando um pedido é injetado **já aberto**: ele existe no Fire, a cozinha pode começar, mas nenhum pagamento foi confirmado. Carrega o mesmo **snapshot V4** que [`order.completed`](/pt/events/order-completed), então tudo o que você faz com um pedido completado também pode fazer aqui.

Este é o evento que torna o pagamento diferido possível. Sem ele, um pedido não pago seria invisível para suas integrações até o dinheiro chegar.

## Condição de disparo

O Fire emite `order.opened` **uma vez**, na injeção, quando:

* `order.status === "OPEN"`

Essa é a única condição. Diferente de `order.completed`, **não há guarda de pagamento** — `paymentStatus` normalmente vem como `"PENDING"` e isso é o esperado.

<Warning>
  `order.opened` **não** dispara para pedidos injetados como `COMPLETED` ou `CANCELLED`. Esses pedidos nunca "abrem": pulam o ciclo de pagamento diferido por completo e produzem apenas [`order.completed`](/pt/events/order-completed). Emiti-lo para eles arriscaria despachar o mesmo pedido duas vezes para a cozinha.
</Warning>

|                          |                                                                       |
| ------------------------ | --------------------------------------------------------------------- |
| Cobertura                | Global (todos os países, todos os canais)                             |
| Chave de idempotência    | `event.id` (= `flow_executions.id`)                                   |
| Dispara mais de uma vez? | Não, exceto em retentativa — use `event.id` para deduplicar           |
| Ordem de chegada         | Não garantida entre pedidos — ordene por `data.createdAt` se precisar |
| Retentativas             | Até 5 tentativas com backoff exponencial                              |

## A vida do pedido depois deste evento

`order.opened` é o **primeiro** de até três eventos do mesmo pedido. Conhecer a sequência importa, porque esse pedido vai chegar ao seu endpoint mais de uma vez:

```
order.opened      o pedido existe, ninguém pagou      status: OPEN
   ↓  (minutos depois — o entregador cobra, o cliente paga)
order.completed   a cobrança quitou o total inteiro   status: COMPLETED
   ↓  (se um documento fiscal for autorizado)
order.invoiced    SEFAZ autorizou a NFC-e / NF-e      (Brasil)
```

Um pedido cancelado antes do pagamento produz [`order.cancelled`](/pt/events/order-cancelled) em vez de `order.completed`.

<Note>
  Se o seu fluxo emite um documento fiscal em `order.opened`, o **mesmo pedido** vai passar de novo pelo seu nó fiscal em `order.completed`. Essa segunda passagem é esperada e inofensiva: o Fire detecta o documento existente e devolve um resultado idempotente de "já faturado" em vez de emitir outro. Veja [Política de pagamento diferido](#política-de-pagamento-diferido) abaixo.
</Note>

## O que vem em `trigger.data`

`trigger.data` é o **snapshot V4** — exatamente a mesma estrutura que `order.completed` carrega, com duas diferenças que você deve esperar:

| Campo                       | Em `order.opened`        | Em `order.completed`            |
| --------------------------- | ------------------------ | ------------------------------- |
| `status`                    | `"OPEN"`                 | `"COMPLETED"`                   |
| `paymentStatus`             | normalmente `"PENDING"`  | `"SUCCEEDED"`                   |
| `payments.paymentMethods[]` | o que o PDV **declarou** | o que foi realmente **cobrado** |

Essa última linha é a que surpreende os integradores. Leia com atenção.

### O meio declarado não é o meio cobrado

Em `order.opened` ninguém pagou, então `payments.paymentMethods[]` carrega o meio que o PDV **anunciou** ao criar o pedido — frequentemente o marketplace (`IFOOD`, `RAPPI`) ou um placeholder. `transactionStatus` vem como `"PENDING"` e `transactionId` geralmente vazio.

Quando a cobrança entra, o Fire **sobrescreve** esse array com os tenders reais e emite `order.completed`. Mesmo pedido, mesmo campo, significado diferente:

```json order.opened — declarado theme={null}
{
  "paymentMethodCode": "CASH",
  "processor": "IFOOD",
  "totalBill": 35.9,
  "transactionStatus": "PENDING",
  "transactionId": ""
}
```

```json order.completed — realmente cobrado theme={null}
{
  "paymentMethodCode": "CREDIT_CARD",
  "processor": "CIELO",
  "card": { "brand": "VISA", "lastFourDigits": "4242" },
  "totalBill": 35.9,
  "transactionStatus": "APPROVED",
  "transactionId": "A1",
  "authorizationCode": "AUTH-A1"
}
```

<Warning>
  Nunca trate `payments.paymentMethods[]` de `order.opened` como evidência de recebimento. É uma intenção, não um fato. Se você precisa saber o que foi realmente arrecadado, aguarde `order.completed` ou chame [Get order](/pt/api-reference/get-order), que expõe `settlement`.
</Warning>

## Política de pagamento diferido

`data.policy.deferredPayment` é a razão de existir deste evento. Ele diz se o pedido **pode ser trabalhado antes do pagamento**: cozinhado, faturado, despachado.

A política é resolvida **uma única vez**, na injeção, a partir da combinação canal × serviço × meio de pagamento declarado. Depois é **carimbada de forma imutável** no pedido, e todos os eventos seguintes a repetem sem recalcular. Dois eventos do mesmo pedido sempre carregam uma `policy` idêntica.

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

| Campo           | Tipo                | Significado                                                                                                                                     |
| --------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `eligible`      | `boolean`           | `true` → aja agora, o dinheiro vem depois. `false` → o pedido é pré-pago ou a política não pôde ser resolvida; aguarde `order.completed`.       |
| `resolvedAt`    | `string` (ISO 8601) | Quando a decisão foi tomada — na injeção, não na emissão.                                                                                       |
| `configVersion` | `string \| null`    | Impressão digital da configuração usada. Para forense: se dois pedidos decidiram diferente, compare isto. `null` quando não pôde ser calculado. |
| `resolvedFrom`  | `object`            | As três entradas por trás da decisão. `paymentMethod` é o meio **declarado**, e por isso pode não coincidir com o que foi cobrado no fim.       |

**Por que imutável?** Porque a decisão precisa ficar auditável. Se a configuração da loja mudar uma hora depois, um pedido já em voo deve continuar se comportando como foi instruído — e você precisa poder provar por quê. Mesmo padrão de `store.storeFiscalConfig`.

<Note>
  `policy` está presente em **todos** os eventos de pedido (`order.opened`, `order.completed`, `order.invoiced`, `order.cancelled`), não só neste. Um pedido com `eligible: false` também carrega o bloco — ele apenas diz que a resposta foi não.
</Note>

## Último estado conhecido

`data.lastKnown` é uma foto **orientativa** do que o Fire sabia sobre o estado de cozinha e fiscal do pedido no momento da emissão do evento.

```json theme={null}
"lastKnown": {
  "kds": null,
  "fiscal": { "status": "processing", "sourceEvent": "fiscal.callback" }
}
```

| Campo    | Tipo             | Significado                                                                                                |
| -------- | ---------------- | ---------------------------------------------------------------------------------------------------------- |
| `kds`    | `object \| null` | Último estado conhecido da cozinha. `null` quando nada rodou ainda.                                        |
| `fiscal` | `object \| null` | Último estado fiscal conhecido, com o evento que o produziu. `null` quando não há nem se espera documento. |

<Warning>
  **`lastKnown` é uma dica, nunca uma fonte de verdade.** Pode estar desatualizado, e em `order.opened` costuma vir `null` simplesmente porque nada aconteceu ainda. Não condicione uma ação irreversível a este campo — se você está prestes a emitir um documento fiscal, devoluções não são algo que você queira descobrir que precisava. Verifique o estado real, ou confie na idempotência do Fire.

  O próprio Fire segue essa regra: seu nó fiscal relê o estado do documento na fonte antes de emitir, e ignora `lastKnown` completamente.
</Warning>

Valores possíveis de `fiscal.status`: `pending`, `processing`, `authorized`, `contingency`, `cancelling`, `cancelled`, `rejected`, `denied`, `error`. O Fire ainda mantém dois estados internos para pedidos sem documento — esses são reportados aqui como `null`, para não vazar contabilidade interna dentro do seu contrato.

## Todo o resto

Os blocos restantes — `store`, `client`, `channel`, `orderLines`, `fulfillment`, `kds`, `device`, `operator`, `marketing`, `metadata`, `payments.totals` — são idênticos a `order.completed`. Em vez de duplicá-los, veja a [referência de campos de `order.completed`](/pt/events/order-completed#referência-de-campos).

## Erros comuns

<AccordionGroup>
  <Accordion title="Tratar order.opened como uma venda">
    Não é. Ninguém pagou. Contar `order.opened` em relatórios de faturamento infla os números e duplica quando `order.completed` chegar para o mesmo `orderId`.
  </Accordion>

  <Accordion title="Esperar order.opened para todo pedido">
    Pedidos pré-pagos (quiosque, checkout web) são injetados já `COMPLETED` e nunca o emitem. Se sua integração depende de `order.opened` chegar primeiro, ela vai pular esses pedidos em silêncio. Assine os dois.
  </Accordion>

  <Accordion title="Ler o meio de pagamento como definitivo">
    Veja [acima](#o-meio-declarado-não-é-o-meio-cobrado). Em `order.opened` é o que o PDV declarou, não o que foi cobrado.
  </Accordion>

  <Accordion title="Processar o mesmo pedido duas vezes">
    O mesmo `orderId` chega em `order.opened` e de novo em `order.completed`. É por design. Faça seu handler idempotente por `(orderId, ação)`, não por `orderId`.
  </Accordion>
</AccordionGroup>

## Próximo

* [`order.completed`](/pt/events/order-completed) — o mesmo pedido, quando o dinheiro entra
* [`order.cancelled`](/pt/events/order-cancelled) — se ele morre antes do pagamento
* [Confirmar pagamento](/pt/api-reference/confirm-payment) — o endpoint que quita um pedido aberto
* [Get order](/pt/api-reference/get-order) — leia `settlement` para ver quanto foi realmente arrecadado

## `data.fiscalRepresentation`

A **numeração fiscal** que o ponto de venda obteve *antes* de injetar o pedido:
cobra, pede os identificadores, imprime o comprovante e só então injeta. Por isso
viaja no pedido e não em um evento fiscal separado — quando o pedido nasce, isso
já aconteceu.

<Warning>
  **A presença deste bloco NÃO significa que o comprovante esteja autorizado.**
  São os números impressos no caixa; o veredito do órgão está em
  `lastKnown.fiscal.status`. Um ticket que diga "autorizado" só porque o bloco
  está presente declara algo que pode não ter acontecido.
</Warning>

**A chave viaja sempre.** Chega em `null` quando não se tentou numerar
— agregadores, países sem representação fiscal, ou comércios com a numeração
desativada — e traz o bloco quando houve tentativa.

Trazer o bloco significa **que se tentou numerar, não que foi numerado**:
`numberingStatus` diz como a tentativa terminou, e `failure` por quê quando não
terminou bem.

Ramifique pelo valor, não pela presença da chave:

```js theme={null}
if (data.fiscalRepresentation) {
  // houve tentativa de numeração — veja numberingStatus para saber como saiu
}
```

| Campo               | O que é                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `numberingStatus`   | Como terminou o **ato de numerar**: `GENERATED`, `PENDING`, `FAILED_RETRYABLE`, `FAILED_FINAL`, `UNAVAILABLE`. **Não é o veredito do órgão** — esse está em `lastKnown.fiscal.status`.                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `documentNumber`    | Número visível do comprovante, composto conforme o país (`005-004-000000042`). É apresentação e **quem o monta é o Fire**, não o órgão: para conciliar use `countryData`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `issuedAt`          | Quando foi **numerado**. Não é a data de autorização.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `authorizationMode` | `ONLINE`, `OFFLINE` ou `BATCH`. Conceito do provedor, não universal.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `providerCode`      | Identificador do adaptador que numerou.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `countryData`       | Os identificadores do órgão, no vocabulário do **país que numerou** — e só os desse país. Equador: `numeroComprobante` (o número visível do comprovante, já montado pelo provedor), `claveAcceso`, `establecimiento`, `puntoEmision`, `secuencial`, `ambiente`. Venezuela: `numeroControl`, `numeroFactura`, `serie`. **Percorra-o; não o indexe às cegas** — uma chave nova não é uma mudança que quebra. É o mesmo bloco que o endpoint de numeração devolve e que o callback do órgão traz. A referência por país, com as chaves de cada regime, está em [`countryData` por país](/pt/api-reference/fiscal-documents#countrydata-por-país). |
| `graphic`           | O artefato imprimível que o provedor devolveu (QR e afins), tal como veio. `null` se não devolveu nenhum.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `failure`           | Por que **não** há comprovante. `null` quando a numeração deu certo.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `providerIdentity`  | **Quem numerou, do lado do provedor**: `{ "name": "hio.fiscalization", "version": "2026.08.1", "reference": "HIO-91f3c2" }`. Diferente da bolsa abaixo, **tem forma**: os três campos estão no contrato e sempre chegam, com `null` quando não se aplicam. `reference` é **a referência de suporte do provedor** — o identificador que se cita a ele para encontrar a operação nos registros dele; não é a `Idempotency-Key` que o canal enviou. Não leva `providerCode`: esse é nosso e viaja acima.                                                                                                                                          |
| `providerMetadata`  | **A bolsa de diagnóstico do provedor**, tal como ele a devolveu: no Equador com a HIO chega `{ "deviceUid": "4B8E…", "externalStoreCode": "K000" }`. É **opaca** — as chaves são do provedor e podem mudar sem aviso, então não programe contra elas; serve para colar num ticket, não para ramificar. **É exatamente o mesmo campo que o endpoint de numeração devolve**, com o mesmo nome e o mesmo conteúdo: os três campos do provedor se leem igual nos dois extremos.                                                                                                                                                                    |
| `environment`       | Em qual ambiente o **Fire** numerou: `SANDBOX` ou `PRODUCTION`. É nosso, não do órgão — o do órgão viaja dentro de `countryData` com o código do país.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `compensates`       | Qual documento este anula. Presente **apenas** quando `documentType` é `CREDIT_NOTE`; `null` nos demais. Traz `documentNumber`, `issuedAt` e `reason` (o código canônico — o texto impresso é redigido por empresa e resolvido na resposta do endpoint de numeração).                                                                                                                                                                                                                                                                                                                                                                          |
| `history`           | Os documentos **anteriores** do pedido, do mais antigo ao mais novo. Vazio enquanto houve apenas um; quando um cancelamento numera, a nota de venda desce para cá e a nota de crédito fica no topo. Cada entrada tem **a mesma forma** do bloco acima, então se leem igual. Somente documentos: uma tentativa de numeração que falhou não entra.                                                                                                                                                                                                                                                                                               |

```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": []
}
```

**O veredicto do órgão não o altera.** O que o cliente levou impresso não muda
porque o órgão depois autorize ou rejeite — para isso existe `lastKnown.fiscal`,
que é o que de fato se move.

**O que o substitui é um documento novo.** O bloco carrega o documento fiscal
**vigente** do pedido. Enquanto houve apenas um, era sempre a nota de venda;
quando um cancelamento produz uma nota de crédito, é ela que fica no topo —
`documentType` diz qual é — e a nota de venda **desce para `history`**, inteira e
com seus próprios identificadores do órgão. Não se perde: se move. `compensates`
aponta para ela pelo número, então a relação fica explícita.

### Quando a numeração falha

Uma venda pode ser cobrada e ficar **sem comprovante fiscal**. Esse caso também
viaja, e precisa ser tratado: os identificadores vêm `null` e o motivo em
`failure`.

```json theme={null}
"fiscalRepresentation": {
  "numberingStatus": "FAILED_FINAL",
  "documentNumber": null,
  "issuedAt": null,
  "providerCode": "hio",
  "graphic": null,
  "failure": { "code": "RUC_INVALIDO", "scope": "FUNCTIONAL", "message": "CNPJ não habilitado" }
}
```

Ramifique por `failure.scope`:

* **`TECHNICAL`** — imprima "em trâmite" e siga. Pode se resolver sozinho.
* **`FUNCTIONAL`** — há um dado errado e repetir não resolve. Precisa correção.
  O que muda é `lastKnown.fiscal`.

<Note>
  **`lastKnown.fiscal.sourceEvent` agora informa a procedência real.** Antes era
  deduzida do status, e um `processing` semeado na injeção era reportado como
  `fiscal.callback` sem que nenhum callback tivesse ocorrido. Esse caso agora diz
  `order.injected`. Se você ramifica por este campo, contemple o valor novo.
</Note>
