Skip to main content
POST
Callback fiscal
Este endpoint é inbound — seu provedor fiscal faz POST nele sempre que um documento fiscal é autorizado, rejeitado, denegado, cancelado ou falha. É a API canônica multi-país de fiscal callback que aceita payloads de BR, CO, EC, CL, AR, VE. O Fire valida o payload, atualiza o estado fiscal do pedido em fiscal_documents e orders.fiscal, e — para o Brasil — despacha eventos outbound order.invoiced / order.reversed para seus Integration Flows.
Este endpoint é assíncrono. O Fire autentica, roda o guard de source-of-truth + tenancy, deduplica, pré-marca o pedido como processing e enfileira o callback — depois retorna 202 Accepted com um webhookEventId (tipicamente em menos de 100 ms). A atualização de fiscal_documents / orders.fiscal acontece um instante depois em um worker em segundo plano (normalmente em ~2 segundos). Para ver o resultado do processamento, consulte GET /v1/webhooks/events/{webhookEventId}. Problemas corrigíveis pelo cliente (payload inválido, eventId errado, tenant errado, uma ação reusando o evento de outra) são rejeitados sincronamente com 4xx antes do 202.

Como complementa order.completed e order.cancelled

order.completed e order.cancelled carregam o estado de negócio de um pedido. O callback fiscal carrega o estado fiscal (autorização SEFAZ / DIAN / SRI / SII / AFIP / SENIAT). Juntos formam este lifecycle: Após processar o callback, o próximo order.completed ou order.cancelled para o mesmo orderId reflete o estado fiscal atualizado em:
  • data.store.storeFiscalConfig — contexto do emissor (CNPJ / NIT / RUC / RUT / CUIT / RIF…)
  • data.payments.metadata.fiscal — agregados fiscais totais (BR populado; outros países null)
  • data.orderLines[].metadata.fiscal — classificação fiscal por linha (BR populado; outros null)
Para o Brasil especificamente, também é emitido um evento order.invoiced (ou order.reversed) separado com as referências do documento SEFAZ em data.fiscal.
Hoje, apenas order.invoiced e order.reversed estão cabeados como eventos outbound (Brasil). O endpoint valida e armazena callbacks para os 6 países (CO, EC, CL, AR, VE, BR), e o estado fiscal atualizado aparece no próximo evento order.completed / order.cancelled independentemente do país. Os eventos outbound para CO/EC/CL/AR/VE estão a caminho.

Autenticação

Este endpoint requer uma API key com scope webhooks:fiscal, vendor-scoped ao account dono do pedido. Keys sem scope ou apenas a nível account são rejeitadas com 403 Forbidden.
string
obrigatório
Sua API key do Fire. Gere uma no dashboard em Settings → API Keys → Developer keys, com scope webhooks:fiscal e um binding de vendor para o account cujos pedidos esta key pode atualizar.
string
Opcional Bearer <token>. Não exigido para este endpoint hoje, mas reservado para futuros tokens emitidos pelo provedor.

Corpo da requisição

O body é um objeto JSON com estes campos top-level. O formato do document é discriminado por countryCode — veja Documento por país abaixo.
string
obrigatório
Código de país ISO 3166-1 alpha-2. Um de BR, CO, EC, CL, AR, VE. Determina as regras de validação do objeto document.
string
obrigatório
Estado do documento. Um de:
  • fiscal_graphic — o provedor está entregando a representação gráfica (o artefato imprimível) do documento. Não é uma aprovação nem um estado terminal — veja O estado fiscal_graphic abaixo.
  • authorized — a autoridade fiscal aprovou o documento
  • cancelled — um documento previamente autorizado foi cancelado
  • rejected — o documento foi rejeitado (validação, schema, assinatura)
  • denied — a autoridade negou a solicitação (tipicamente falha permanente de regra de negócio)
  • error — ocorreu um erro não recuperável no provedor ou autoridade
Quando eventType é fiscal_graphic, authorized ou cancelled, o campo document é obrigatório. Quando é rejected, denied ou error, o campo error é obrigatório.
string
obrigatório
O id próprio do seu provedor para esta entrega. Armazenado para auditoria/forense — não é a chave de idempotência. O Fire deduplica por (orderId, eventId), então você pode enviar um providerEventId novo a cada retentativa sem criar duplicatas. Use o ID nativo do evento do provedor se disponível; caso contrário, um UUID.
string
obrigatório
Timestamp ISO 8601 UTC de quando o evento ocorreu na autoridade fiscal (não quando o provedor enviou o callback).
string
obrigatório
UUID do pedido no Fire. Coincide com data.orderId nos eventos order.completed e order.cancelled. O Fire o usa para encontrar o documento fiscal existente.
string
obrigatório
UUID de correlação e chave de idempotência (junto com orderId). Deve ser o event.id de um envelope V4 que o Fire emitiu para este pedido — ecoe-o exato; nunca o invente.
  • Verificação de fonte da verdade. Um eventId que não referencie um evento do Fire para esse pedido é rejeitado com 400 antes do 202.
  • Cada ação carrega seu próprio evento. Ecoe o event.id do evento que disparou esta ação — a emissão order.invoiced para um callback authorized, o evento de cancelamento/estorno para um callback cancelled. Reusar o eventId de uma ação para outro eventType (ex. um cancelled que ecoa o eventId do authorized) é rejeitado com 409 — um cancelamento deve referenciar seu próprio evento, não se pendurar no da autorização. Veja Idempotência e cenários.
object
O documento fiscal autorizado / cancelado. Obrigatório quando eventType é authorized ou cancelled. O formato varia por país — veja Documento por país.
object
Contexto de erro para resultados negativos. Obrigatório quando eventType é rejected, denied ou error.
object
Bag free-form para extras específicos do provedor (resposta raw, IDs internos, etc.). Não validado; passa para o log de auditoria.

Documento por país

O formato exigido do campo document depende do countryCode. Todas as variantes compartilham os campos base abaixo (comuns aos 6 países) mais os identificadores específicos do país exigidos por aquela autoridade.

Campos base comuns

Aplicam-se a qualquer countryCode. docType e docSubtype são obrigatórios; o restante é opcional — envie-os sempre que seu provedor fiscal os tiver disponíveis. O Fire os persiste em fiscal_documents / orders.fiscal e os reemite nos eventos outbound order.invoiced / order.reversed (Brasil) e no próximo order.completed / order.cancelled.
pdfUrl e xmlUrl são armazenados exatamente como você os envia — o Fire não baixa nem re-hospeda o arquivo. Se seu provedor assina essas URLs com expiração, considere que o link armazenado pode caducar; baixe e persista o artefato do seu lado se precisar de acesso durável.
Documentos fiscais brasileiros (NF-e / NFC-e). Use este código de país ao enviar callbacks do seu provedor fiscal ou de qualquer outro provedor BR.Além dos campos base comuns (docType, docSubtype, pdfUrl, xmlUrl, emittedAt, etc.), o BR exige estes identificadores específicos:O exemplo abaixo inclui os campos base opcionais (pdfUrl, xmlUrl, emittedAt, totalAmount, taxAmount, currencyCode) — todos podem ser omitidos, mas envie-os se seu provedor os tiver:

O estado fiscal_graphic

fiscal_graphic informa que o seu provedor está entregando a representação gráfica — o artefato imprimível (PDF / RIDE / DANFE) do documento. É um estado próprio, não um resultado:
  • Não é uma aprovação. Receber fiscal_graphic não diz nada sobre a autoridade ter aprovado o documento. O Fire armazena a representação e o documento permanece em estado não terminal.
  • É opcional. Se o seu provedor não tem representação gráfica para um documento, envie authorized (ou qualquer estado terminal) diretamente — não é necessário um fiscal_graphic antes. Ambos os fluxos são válidos.
  • Pode compartilhar o eventId com o seu desfecho. A representação e o resultado terminal pertencem à mesma ação, então você pode enviar fiscal_graphic e depois authorized / rejected / denied / cancelled reutilizando o mesmo eventId. Isso não é um conflito e nunca retorna 409 — veja Idempotência e cenários.
  • Exige document com pdfUrl. O PDF é a representação, portanto é obrigatório. xmlUrl continua opcional aqui — o XML legal viaja com a autorização.
  • Não dispara nenhum evento de saída. order.invoiced e order.reversed seguem atrelados a authorized e cancelled respectivamente. A representação apenas muda o estado do documento.
fiscal_graphic (CO)

Resultados negativos (rejected, denied, error)

Para estados não autorizados, omita document e forneça error. O countryCode ainda se aplica (valida o roteamento); o documento não é exigido porque não há artefato autorizado.
Rejeitado

Resposta

Em caso de sucesso o endpoint retorna 202 Accepted — o evento foi autenticado, validado, deduplicado e enfileirado. Um 202 não significa que o documento fiscal já foi atualizado; isso acontece de forma assíncrona em um worker em segundo plano. Use o endpoint de status para confirmar o resultado final. O body traz dois ids distintos para não haver ambiguidade: eventId é o id que você enviou (devolvido como echo), webhookEventId é o id do Fire para o registro enfileirado.
boolean
Sempre true quando a requisição foi aceita e enfileirada.
boolean
true quando este (orderId, eventId) já foi ingerido com o mesmo eventType — o registro existente é retornado e nada é re-enfileirado. false para um evento novo.
string
Echo do eventId que você enviou (o event.id da emissão do Fire). Use-o para correlacionar este acuse com a sua requisição.
string
O id do Fire para o registro enfileirado em webhook_events. Passe para GET /v1/webhooks/events/{webhookEventId} para consultar o resultado do processamento. Em uma duplicata é o mesmo id retornado na primeira vez.
string
Status atual do registro na fila — queuedprocessingprocessed (e retry / failed / dead / ignored).
string
Timestamp ISO 8601 UTC de quando o Fire recebeu pela primeira vez este evento. Estável entre retentativas — útil como âncora de rastreamento.
string
Resumo legível do que aconteceu.

Verificar o resultado

Como o processamento é assíncrono, o 202 só confirma que o evento foi enfileirado. Para ver se o documento fiscal foi atualizado, consulte o endpoint de status com o webhookEventId retornado pelo 202:
string
Ciclo de vida na fila: queuedprocessingprocessed (pronto) · failed / dead (esgotou as retentativas) · retry (aguardando a próxima tentativa) · ignored.
number
Tentativas de processamento até agora.
object | null
Em sucesso, o resultado do worker — ex. { "kind": "updated", "documentId": "…", "receiptId": "…" }.
object | null
{ "message": "…" } quando a última tentativa falhou; null caso contrário.
Um 404 é retornado para ids desconhecidos — ou ids de outro tenant — sem vazar existência. Autentique com a mesma key webhooks:fiscal que usou no callback.

Idempotência e cenários

O Fire deduplica callbacks por (orderId, eventId)não por providerEventId (que você pode regenerar livremente). Um evento é único com o seu pedido: o mesmo (orderId, eventId) reenviado com o mesmo eventType é um replay benigno; o mesmo (orderId, eventId) com um eventType diferente é uma tentativa de pendurar uma ação no evento de outra, e o Fire rejeita. fiscal_graphic é a exceção. É um passo da mesma ação, não um desfecho concorrente, então pode compartilhar o eventId com o estado terminal que vem depois — essa combinação é aceita, nunca retorna 409. Esta é a matriz completa de comportamento — cada combinação que você pode enviar:
Um cancelamento precisa do seu próprio evento. Você não pode cancelar um documento reenviando o eventId da autorização com eventType: "cancelled" — isso retorna 409. O Fire é a fonte da verdade: um cancelamento deve referenciar o evento de cancelamento/estorno que o Fire emitiu (um eventId distinto). Retornar um 202 duplicado aqui diria erroneamente que o cancelamento foi aceito enquanto o Fire nunca cancelou — por isso o Fire o rejeita explicitamente.
409 vs 202. Um 409 é o único caso em que um callback bem formado e autenticado é recusado na camada de idempotência — porque aceitá-lo divergiria o estado. Um replay do mesmo tipo nunca é um erro: retorna 202 para que suas retentativas fiquem limpas. Um 503 é nosso (infra transitória), então é seguro e esperado retentar.

Concorrência

As transições de estado em fiscal_documents usam locking otimista. Se dois callbacks para o mesmo documento chegarem simultaneamente, um tem sucesso e o outro resolve para idempotent ou regression conforme a ordem. O merge de orders.fiscal JSONB é atômico.

O que acontece após o 202

O 202 apenas enfileira o evento. Um worker em segundo plano então o pega — em ~2 segundos via o wake-up instantâneo, ou no próximo ciclo de polling como fallback — e:
  1. A linha fiscal_documents é upsertada com o novo status e referências do documento (chaveAcesso, protocolo, cufe, cae, etc., conforme o país).
  2. A coluna orders.fiscal JSONB é mergeada com os mesmos dados — visível no próximo evento order.completed / order.cancelled para o mesmo orderId, independente do país.
  3. Um trigger outbound é despachado — para o Brasil, triggerType = 'order.invoiced' (para eventType=authorized) ou 'order.reversed' (para eventType=cancelled). Os Integration Flows ativos para esse trigger rodam e fazem POST para o seu endpoint.
  • Hoje, apenas order.invoiced e order.reversed estão cabeados. Disparam quando um callback authorized/cancelled para uma loja BR é processado.
  • Para CO/EC/CL/AR/VE, os eventos outbound equivalentes ainda não estão cabeados — os callbacks são validados e armazenados, e o estado fiscal se reflete no próximo order.completed / order.cancelled para o mesmo pedido.

Relacionado

order.completed

Veja onde o estado fiscal aterrissa dentro do snapshot V4 do pedido.

order.invoiced

Evento outbound BR-only disparado por este callback.

Injetar pedido

O endpoint de injeção que cria o pedido que este callback atualiza.

Autenticação

Como funcionam API keys, scopes e vendor binding.