- v1 · atual
- v0 · descontinuado
Você está vendo o contrato atual (v1) de
order.completed — adiciona descontos de pedido e de produto (objeto Discount), impostos granulares, o enum completo de itemType (PRODUCT / COMBO / MODIFIER / PACKAGING) e fulfillment.delivery.deliveryConfirmationCode.order.completed dispara quando um pedido é injetado com sucesso e está pago. Carrega o snapshot V4 do pedido como trigger.data — todos os campos que seu flow precisa para agir sobre o pedido sem voltar a chamar o Fire.
Condição de disparo
O Fire emiteorder.completed exatamente uma vez por pedido, na primeira vez em que ambos são verdadeiros no momento de injeção:
order.status === "COMPLETED"order.paymentStatus === "SUCCEEDED"
PENDING de pagamento, ou que falham o pagamento, nunca produzem order.completed. Cancelamentos após completar produzem um evento separado order.cancelled — eles não retraem order.completed.
| 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, salvo em retentativas — use event.id para deduplicar |
| Ordem | Não garantida entre pedidos — ordene por data.createdAt se precisar |
| Retentativas | Até 5 tentativas com backoff exponencial |
O que tem em trigger.data
trigger.data é o snapshot V4 do pedido — o mesmo objeto que está persistido em flow_queue.trigger_data e exposto aos templates do seu flow.
As chaves top-level, em ordem:
| Chave | Tipo | Sempre presente |
|---|---|---|
orderId | string (UUID) | sim |
orderCode | string | null | sim |
businessDayDate | string (YYYY-MM-DD) | sim |
externalOrderId | string | sim |
redeemPoints | boolean | sim |
accumulatePoints | boolean | sim |
discount | boolean | sim |
createdAt | string | null (ISO 8601 UTC) | sim |
orderComment | string (pode ser "") | sim |
paymentStatus | string (sempre "SUCCEEDED") | sim |
status | string (sempre "COMPLETED") | sim |
marketing | object | null | sim |
store | object | sim |
device | object | sim |
channel | object | sim |
operator | object | sim |
client | object | null | sim |
payments | object | sim |
kds | object | sim |
metadata | object (frequentemente {}) | sim |
orderLines | object[] | sim |
fulfillment | object | sim |
Exemplo — payload real de produção (BR, sanitizado)
O exemplo abaixo vem de uma linha real deflow_queue.trigger_data (tenant sandbox brasileiro, canal KIOSK, serviço dine-in). Os campos PII são substituídos por placeholders; o restante dos campos e formatos é verbatim.
Os valores monetários são strings expressas como unidades menores inteiras × 10000 (ex.:
"229000" = 22.9000 BRL). Isso evita drift de ponto flutuante através de múltiplas integrações. Parseie com uma biblioteca decimal, nunca com parseFloat. A exceção é paymentMethods[].totalBill, que a origem às vezes envia como número JSON — trate ambos.Referência de campos
Identificadores top-level
UUID interno do pedido no Fire. Estável através de entregas; use junto com
event.id para rastreabilidade.Código curto legível mostrado em recibos e telas KDS (ex.:
95K, OC-br-001). null quando o canal não atribui um.Dia de negócio ao qual este pedido pertence, em
YYYY-MM-DD. Calculado em hora local da loja, então um pedido feito às 01:00 pode pertencer ao dia de negócio anterior dependendo do corte de fim de dia.O ID de pedido tal como provido pelo canal/agregador na injeção. Use para reconciliar com sistemas upstream (POS, dashboards de agregador).
Timestamp ISO 8601 UTC de quando o pedido foi originalmente feito. Distinto de
event.createdAt, que é quando a execução do flow começou.Sempre
"COMPLETED" para este evento.Sempre
"SUCCEEDED" para este evento.true se pontos de fidelidade foram resgatados neste pedido.true se o cliente acumulou pontos de fidelidade.true se algum desconto foi aplicado.Nota free-text do cliente para o pedido inteiro. Empty string quando não definido.
data.store
Snapshot da loja no momento em que o pedido foi completado.
data.client
Cliente que fez o pedido.
null para pedidos de canal totalmente anônimos. Para pedidos BR de “consumidor final”, client é populado com valores placeholder (govIdType: "FINAL_CONSUMER", govIdNumber: "00000000000").data.payments
Detalhamento de dinheiro.
data.fulfillment
Como o pedido é entregue.
data.kds
Contexto do kitchen display.
data.device e data.operator
{ uid, name, platform, metadata.ip } — dispositivo de origem. Os campos podem ser null para canais não físicos.{ uid, name, session.uid } — staff/caixa que processou o pedido. Todos os campos null para canais self-service (quiosque, web).data.orderLines
Produtos pedidos. Totalmente camelCase (transformado pelo builder V4).
data.marketing, data.metadata, data.channel
Loyalty + cupons.
null na maioria dos países hoje; reservado para uso futuro.Bag free-form para extras a nível de pedido. Frequentemente
{}.{ uid, code, metadata }. Exemplos de code: KIOSK, APP, IFOOD, RAPPI.Dados fiscais
Os dados fiscais são incluídos apenas quando a loja tem emissão fiscal habilitada (
store.storeFiscalConfig.enabled === true). Para países sem fiscal ou lojas sem configuração, todas as três localizações abaixo estão ausentes ou em null.order.completed carrega informação fiscal em três localizações distintas. Cada uma serve um propósito diferente:
1. data.store.storeFiscalConfig — identidade do emissor e config do provedor
Identifica a entidade legal que emite o documento e como autenticar com o provedor fiscal. Credenciais NÃO estão aqui intencionalmente — o nó fiscal as busca por provedor/account.
2. data.payments.metadata.fiscal — agregados fiscais a nível de pedido
Totais agregados estilo SEFAZ, prontos para envio ao provedor fiscal (seu provedor fiscal no Brasil). Os valores são strings × 10000.
3. data.orderLines[n].metadata.fiscal — classificação fiscal por linha
Códigos fiscais por produto. Usados pelo provedor fiscal para classificar cada linha no documento.
taxes[n].metadata (em payments.totals[].taxes[], orderLines[].price.totalPrice[].taxes[] e orderLines[].lineTotals[].taxes[]) com códigos como cst, cBenef, cClassTrib, reducao, rateNominal, rateEffective.
Variações por país
O exemplo acima é de uma loja brasileira — o caso mais complexo. O formato V4 é idêntico em todos os países, incluindo o detalhamento granular detaxes[]: cada país popula payments.totals[].taxes[] e os taxes por linha com seus impostos locais no mesmo formato { base, name, rate, amount, metadata }. O que muda por país:
- Nomes de imposto — BR usa
ICMS,PIS,COFINS,IBS_UF,IBS_MUN,CBS; outros países carregam seus impostos locais (ex.IVA) com a mesma estrutura. - Códigos de
metadata— BR carrega códigos SEFAZ (cst,cBenef,cClassTrib,reducao,rateNominal,rateEffective); outros países seus próprios códigos. - Emissão fiscal SEFAZ — apenas Brasil.
payments.metadata.fiscal,orderLines[].metadata.fiscal(ncm/cfop/csosn) e os eventosorder.invoiced/order.reversedsó aplicam ao BR. Os demais países ainda carregam seutaxes[], mas esses blocos SEFAZ estão ausentes.
- Brasil (BR)
- Argentina (AR)
- Chile (CL)
- Colombia (CO)
- Ecuador (EC)
- Venezuela (VE)
As lojas brasileiras com
storeFiscalConfig.enabled === true carregam o payload fiscal completo — veja a seção Dados fiscais acima. Marcadores de país:store.locationInfo.country.code: "BR"·name: "Brasil"·timezone: "America/Sao_Paulo"store.locationInfo.currencyCode: "BRL"store.storeFiscalConfig.govIdType: "CNPJ"(14 dígitos)store.storeFiscalConfig.secondaryGovIdType: "INSCRICAO_ESTADUAL"payments.totals[].currencyCode: "BRL",paymentMethods[].currencyCode: "BRL",orderLines[].selectedCurrency: "BRL"- Populados:
payments.metadata.fiscal(vBC / vNF / vICMS / vPIS / vCOFINS / vTotTrib …),orderLines[].metadata.fiscal(ncm / cfop / csosn),lineTotals[].taxes[](ICMS, PIS, COFINS, IBS_*)
Tabela de referência rápida
| País | country.code | Moeda efetiva | govIdType (formato) | Agregados fiscais |
|---|---|---|---|---|
| Brasil | BR | BRL | CNPJ (14 dígitos) | Sim — agregados SEFAZ completos |
| Argentina | AR | ARS | CUIT (XX-XXXXXXXX-X) | Não — null / vazio |
| Chile | CL | CLP | RUT (XXXXXXXX-X) | Não |
| Colombia | CO | COP | NIT (XXXXXXXXX-X) | Não |
| Ecuador | EC | USD (moeda oficial do Equador) | RUC (13 dígitos) | Não |
| Venezuela | VE | VES | RIF (J-XXXXXXXX-X) | Não |
| Outros países | varia | varia | varia | Não |
À medida que mais países tiverem um pipeline fiscal dedicado, seus eventos fiscais chegarão como
fiscal.*.{cc} (ex.: fiscal.authorized.co, fiscal.authorized.ec). Até lá, apenas order.completed e order.cancelled disparam para lojas não-BR — os blocos fiscais permanecem null / vazios.Handler de exemplo
Erros comuns
- Decimais como strings × 10000.
payments.totals[0].total === "229000"significa 22.9 BRL. Use uma biblioteca decimal; nunca comparseFloat. - O casing é misto em
payments.totals[]e partes depaymentMethods[]. Leia tantocurrencyCodequantocurrencyCodedefensivamente. O builder V4 transforma a maior parte do snapshot mas passa os objetos de payment sem alteração. fulfillment.deliverypode estar presente mesmo para serviços non-delivery com zeros placeholder. Sempre ramifique emfulfillment.service.code.clientpode ser um placeholder “FINAL_CONSUMER” populado em BR — não énull. TrategovIdType === "FINAL_CONSUMER"como anônimo para analítica.event.idé o ID de execução do flow, não o ID do pedido. Useevent.idpara idempotência (muda por entrega), eorderIdcomo chave de negócio.- Routing multi-tenant. Use
store.account.uid,store.vendor.uidestore.codepara rotear ao tenant correto no seu sistema, mesmo que o Fire já dê escopo ao flow do lado dele.
Eventos relacionados
order.cancelled
Dispara quando este pedido é cancelado depois.
order.invoiced
Apenas Brasil — dispara quando a SEFAZ autoriza o documento fiscal do pedido.

