Saltar para o conteúdo principal
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, guarda o veredito do ente no pedido e despacha order.invoiced / order.reversed para seus Integration Flows — para todos os países. O que você envia aqui é o que os consumidores dos eventos leem: veja Do callback aos eventos.
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 um callback authorized, o Fire emite order.invoiced; após um cancelled, order.reversed. Os dois disparam para todos os países — o país viaja no bloco fiscal do evento, não no nome. Os eventos seguintes do pedido para o mesmo orderId também refletem o novo estado em data.lastKnown.fiscal. Para o panorama fiscal completo — numeração, callback e eventos, e como se encaixam — veja a visão geral fiscal.

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 Developers → API Management, com scope webhooks:fiscal e um binding de vendor para o account cujos pedidos esta key pode atualizar.
string
Alias legado: a mesma API key do Fire, como Bearer pk_live_.... Prefira x-api-key; se os dois chegarem, é usado x-api-key.

Corpo da requisição

O body é um objeto JSON com estes campos top-level. Tudo o que é canônico vive aqui em cima; document leva SOMENTE o vocabulário do ente do seu país, escolhido por country — 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.Antes se chamava countryCode.
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 failure é 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) — um eventType diferente no mesmo par retorna 409, exceto fiscal_graphic e as retentativas após uma falha (veja Retentativas e cancelamento rejeitado) — 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 vocabulário do ente do seu país, e nada mais: claveAcceso, cufe, chaveAcesso, folio, cae… Obrigatório quando eventType é authorized, cancelled ou fiscal_graphic. Veja Documento por país.Os campos comuns —documentType, o número, as URLs, os valores, as datas— não vão aqui dentro: estão na raiz. Tudo o que vai em document chega aos eventos como authority.countryData, com os mesmos nomes de chave.

Campos canônicos (raiz)

Significam a mesma coisa nos seis países, então vivem na raiz do payload e não dentro de document. É a mesma regra da resposta de numeração fiscal, para que o mesmo fato não seja procurado em duas profundidades distintas segundo por onde entrou.
string
SALE_INVOICE ou CREDIT_NOTE — o mesmo vocabulário da numeração fiscal. Obrigatório quando há comprovante (authorized / cancelled), e deve corresponder ao evento: authorized é um SALE_INVOICE, cancelled é um CREDIT_NOTE. Qualquer outra combinação retorna 400.Antes era docType: "invoice" | "cancellation". O nome antigo é ignorado, não traduzido: um payload authorized ou cancelled que traz só docType recebe 400 em documentType.
string
Como o seu regime o chama: nfce, nfe, factura, boleta, factura_a. Aberto: não o validamos contra uma lista e não ramifica nada do nosso lado — é referencial. Obrigatório quando há comprovante.

Tipos de documento

O Fire aceita exatamente dois valores em documentType. Não existe um terceiro tipo: qualquer outro valor retorna 400. Como cada regime chama seu documento vai em docSubtype, e esse campo é aberto: nfce, nfe (Brasil), factura (Equador, Colômbia), boleta (Chile), factura_a (Argentina) e qualquer outro nome que o seu órgão use. O Fire não o valida contra uma lista nem decide nada com ele.
Não confunda com o catálogo de tipos de documento: esse endpoint lista os documentos de identificação do comprador (CEDULA, CPF, NIT…), não tipos de documento fiscal.
string
O número visível do comprovante, como o ente o compõe (12388, 001-020-000000123, C012001). As peças que o formam continuam viajando em document com os nomes do país. Obrigatório em authorized: o Fire não o deduz mais.
string
Data/hora UTC (ISO 8601) em que o documento foi emitido. Mesmo nome que na numeração fiscal. Obrigatório em authorized.
string
Data/hora UTC (ISO 8601) em que o ente aprovou o documento — um fato diferente de issuedAt. Podem distar segundos (autorização on-line) ou horas (contingência autorizada quando a conexão volta). Opcional; se ausente, os consumidores dos eventos veem authority.authorizedAt: null. Em um cancelamento use cancelledAt: um callback cancelled mantém o issuedAt e o authorizedAt que o documento já tinha —são os da fatura— e só usa os que você enviar se o Fire não tinha nenhum.
string
Data/hora UTC em que o ente aprovou o cancelamento. Envie-o em cancelled.
string
ONLINE, OFFLINE ou BATCH. OFFLINE é contingência: o comprovante vale mas foi emitido sem conseguir consultar o ente, e há regimes que exigem que o ticket o diga (o RIDE equatoriano imprime EMISION POR CONTINGENCIA).
string
Link de download do PDF (DANFE / RIDE). HTTPS, baixável por GET direto, válido por pelo menos 24 h — o Fire o arquiva. Obrigatório para authorized e cancelled.
string
Link de download do XML legal do ente. Mesmas condições que pdfUrl. Obrigatório para authorized e cancelled.
number
Total bruto do documento, em decimais reais (não escalados). Obrigatório em authorized.
number
Total de impostos do documento, em decimais reais. Obrigatório em authorized.
string
Código ISO 4217 — exatamente 3 letras (BRL, COP, USD). Obrigatório em authorized.
string
O id do documento no seu sistema. É por ele que o PDF e o XML são buscados e com ele se pede um cancelamento. Obrigatório em authorized.
object
O que se imprime: um mapa chave → string exata a codificar ({ "qr": "…" }, { "ted": "…" }). A chave nomeia o propósito; como se desenha é decisão do template do ticket. Fica na raiz, ao lado de document, como na resposta de numeração fiscal. Obrigatório e não vazio em fiscal_graphic; opcional nos demais.
object
Quem emitiu e com qual versão. Chega ao pedido e aos eventos como authority.providerIdentity — o mesmo nome da numeração fiscal — com as três chaves sempre presentes. Se você não enviar provider, ou enviá-lo vazio, providerIdentity é null.
object
Por que NÃO há comprovante. Obrigatório quando eventType é rejected, denied ou error.Antes se chamava error, e agora leva a mesma forma que a resposta de numeração fiscal.
object
Bag free-form para extras específicos do provedor (resposta raw, IDs internos, etc.). Não validado. Chega ao pedido e aos eventos como authority.providerMetadata, tal como veio e opaco — igual à numeração fiscal. Ausente ou {} vira null. Não envie null: omita ou envie {} — null retorna 400.Antes se chamava providerSpecific.
A raiz não aceita chaves extras. Só são lidos os campos acima; qualquer outra chave de raiz é descartada em silêncio — não é rejeitada. orderCode não faz parte do contrato — o pedido é resolvido por orderId.

O que é obrigatório, por evento

authorizedAt, cancelledAt, authorizationMode e provider são sempre opcionais. Um campo obrigatório enviado como null conta como ausente.

Documento por país

A forma exigida de document depende de country. document leva SOMENTE os identificadores do ente desse país — os campos comuns aos seis vivem na raiz do payload, acima.
document mudou de conteúdoAté agora document misturava duas coisas: o que significa o mesmo em todos os países —docType, pdfUrl, xmlUrl, os valores, as datas— e o vocabulário do ente de cada um. Essa mistura se propagava para tudo o que lia o callback.Agora o canônico vive na raiz e document fica só com o do regime. É a mesma forma da resposta de numeração fiscal: o mesmo fato, no mesmo lugar, sem importar por onde entrou.Outras mudanças do mesmo pacote: countryCode → country, docType → documentType (SALE_INVOICE / CREDIT_NOTE, sem alias), error → failure (com scope e details), providerSpecific → metadata, e emittedAt → issuedAt. Novos na raiz: documentNumber, authorizedAt e graphic.
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 canônicos da raiz (documentType, docSubtype, documentNumber, pdfUrl, xmlUrl, issuedAt, etc.), o BR exige estes identificadores específicos:O exemplo abaixo é um payload authorized completo: todo campo de raiz que ele mostra é obrigatório para esse evento, exceto provider e metadata, que são opcionais e chegam ao pedido como authority.providerIdentity e authority.providerMetadata — veja O que é obrigatório, por evento.

O estado fiscal_graphic

fiscal_graphic informa que o seu provedor está entregando a representação gráfica — o que o caixa imprime para o 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 e um graphic não vazio. A representação gráfica é o que o caixa imprime — o QR, o TED, a chave de acesso codificada — e viaja no graphic da raiz. O PDF e o XML são os arquivos do documento autorizado e chegam com authorized.
  • 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 (EC)

Resultados negativos (rejected, denied, error)

Para estados não autorizados, omita document (ou envie null) e forneça failure. country ainda se aplica (valida o roteamento); o documento não é exigido porque não há artefato autorizado — e documentType/docSubtype também não, já que não há comprovante a tipificar. Um resultado negativo não guarda dados de comprovante. Se você enviar documentNumber, providerDocId, issuedAt, authorizedAt, valores, pdfUrl, xmlUrl ou graphic com rejected, denied ou error, o Fire os ignora: só são guardados documentType, docSubtype, as chaves do país em document, failure, provider e metadata. Um documento que já tinha dados de comprovante os mantém.
Rejeitado

Retentativas e cancelamento rejeitado

Uma emissão com falha pode ser retentada. Se você reportou rejected, denied ou error e depois retenta junto ao órgão, envie o novo resultado com o mesmo eventId — o da emissão. O Fire aceita e o fluxo segue normal: se o novo resultado for authorized, order.invoiced é despachado. Se a retentativa falhar de novo, o motivo novo substitui o anterior.
Cancelamento rejeitado pelo órgão. Quando o Fire pede para anular uma nota autorizada (evento order.cancelled), o pedido fica “cancelando”. Se o órgão não aceitar o cancelamento, envie rejected, denied ou error com o eventId desse cancelamento e o motivo em failure. O Fire interpreta como cancelamento com falha: a nota continua válida (o pedido volta para authorized, com o motivo em error) e nenhum evento é despachado. Se depois você retentar e o órgão aceitar, envie cancelled com o mesmo eventId e order.reversed é despachado.
Um rejected sobre uma nota autorizada que não está sendo cancelada continua significando o mesmo de sempre: o órgão rejeitou a nota.

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. Um eventType diferente no mesmo par nunca chega a este campo: retorna 409, exceto fiscal_graphic.
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 — queued → processing → processed (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: queued → processing → processed (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). O mesmo par reenviado com o mesmo eventType é um replay benigno; o mesmo par com um eventType diferente retorna 409 — uma tentativa de pendurar uma ação no evento de outra — exceto fiscal_graphic, que pode compartilhar o eventId com o seu resultado. 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. Quando o pedido já tem documento, o callback é associado a ele pelo eventId. Um callback com outro eventId válido termina em notFound, não em regression; reenviar o eventId do documento com um estado anterior é um reenvio do mesmo par. Nenhum dos dois altera o documento.

O que acontece após o 202

Do callback aos eventos

Como cada campo que você envia aqui chega a order.invoiced e order.reversed.

Visão geral fiscal

Numeração, callback e eventos em uma só imagem.
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. O documento fiscal é atualizado com o novo estado e os identificadores do ente.
  2. O veredito é guardado no pedido, estruturado: campos canônicos, amounts, countryData e graphic — e acrescentado ao histórico fiscal do pedido.
  3. Um evento outbound é despachado, para todos os países: order.invoiced para eventType=authorized, order.reversed para eventType=cancelled. Os Integration Flows ativos para esse evento rodam e fazem POST para o seu endpoint. fiscal_graphic, rejected, denied e error atualizam o estado mas não emitem evento.

Do callback aos eventos

Quem consome order.invoiced ou order.reversed lê exatamente o que você enviou aqui, reorganizado no bloco fiscal do evento. A referência completa desse bloco está em order.invoiced. Os campos da raiz caem em fiscal.authority (ou cancellation.fiscal.authority) com os mesmos nomes, exceto os três valores, que se agrupam em authority.amounts. document vira authority.countryData, e provider e metadata viram providerIdentity e providerMetadata (null se ausentes ou vazios). A tabela campo a campo está em Do callback aos eventos. document e countryData são o mesmo bloco. O Fire não mantém uma lista das chaves de cada país: tudo o que vem em document e não é campo canônico chega intacto a countryData. Um identificador novo que o seu ente passe a exigir viaja até os eventos sem nenhuma mudança do lado do Fire.

Por que este endpoint mantém o caminho /v1

As renomeações de campos acima (docType → documentType, countryCode → country, error → failure, providerSpecific → metadata) quebram um emissor que ainda use os nomes anteriores: ele recebe 400 indicando o campo. Mesmo assim o endpoint manteve o caminho. Quando o contrato mudou, este callback só levava tráfego de testes em produção, e o cliente de testes do próprio Fire mudou na mesma release, então um /v2 paralelo teria mantido duas formas de dizer a mesma coisa sem nenhum emissor. O lado dos eventos é diferente — tem consumidores em produção — e os três eventos afetados publicaram cada um uma nova versão documentada.

Relacionado

order.completed

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

order.invoiced

Evento outbound disparado por um callback authorized, para todos os países.

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.