Skip to main content
POST
O Fire resolve internamente qual provedor fiscal corresponde ao país da loja, pede a numeração e devolve os dados prontos para imprimir.
Três coisas antes de integrar:
  1. Aqui não há id de pedido. Ao cobrar, o pedido ainda não existe no Fire. O orderCode é a única coisa que liga esta solicitação à venda, então precisa ser a mesma string que depois viaja na injeção.
  2. A resposta não diz que o documento está autorizado. Diz que há números para imprimir. A autorização do órgão chega depois, de forma assíncrona.
  3. Você pede uma operação, não um tipo de documento. INVOICE ou CANCEL. Com qual instrumento fiscal isso se materializa — nota de venda, nota de crédito, evento de cancelamento — quem decide é o país, e não é assunto do ponto de venda.

O fluxo completo

1

Você cobra

O cliente paga no PDV ou no quiosque.
2

Você pede a numeração

Você chama este endpoint. O Fire resolve a loja, o emitente e o provedor, e grava a solicitação antes de sair atrás dos números.
3

Você imprime

Conforme printing.mode você imprime o comprovante fiscal ou um ticket provisório.
4

Você injeta o pedido

Com o corpo de sempre, sem acrescentar nada. O Fire correlaciona a venda com sua numeração pelo orderCode.
5

O órgão autoriza

Minutos depois. O Fire recebe o resultado do provedor e atualiza o pedido. Se quiser ver, consulte esta mesma solicitação.
A Fire nunca te trava por conta própria. Falhe o que falhar, este endpoint responde com uma decisão explícita em policy.numberingFailure.action — não com um erro que te deixa sem saber o que fazer.Mas a decisão nem sempre é seguir: a conta pode configurar que sem comprovante não se vende. Ramifique pelo action, nunca pelo código HTTP:
  • CONTINUE (o padrão) — imprima conforme printing.mode e injete o pedido. Se saiu sem numeração, chame de novo com o mesmo orderCode: nada completa sozinho, e um 202 que ninguém retenta fica assim para sempre.
  • REFUND — devolva a cobrança e não injete o pedido. Não há nada a completar depois: retentar a numeração de uma venda que você devolveu geraria um comprovante para algo que não aconteceu.
Nos dois casos: não retenha a venda nem retente em loop com o cliente esperando.Quantas vezes tentar de novo, no caminho CONTINUE: duas. Enquanto retryable vier true, chame de novo com o mesmo orderCode até mais duas vezes. Se depois da segunda tentativa ainda não houver numeração, trate como definitivo: a venda já foi injetada com comprovante provisório, e o que falta se resolve pelo suporte, não no balcão.Com REFUND não há retentativa: zero. A venda foi devolvida, e numerá-la depois geraria um comprovante de algo que não aconteceu.O limite é você quem aplica. O Fire numera cada tentativa e guarda para o suporte, mas não corta por conta própria: se você chamar uma quarta vez, ele pergunta ao provedor de novo. E a resposta não vai mudar por insistir — action não depende de retryable, então o que a terceira tentativa disser, a primeira já dizia.

Headers

string
obrigatório
Sua API key do Fire, com a permissão Fiscal Gateway (numbering).A conta e o vendor são derivados da key, nunca do corpo. Por isso o payload não leva accountId nem vendorId: uma credencial não pode mentir sobre a quem pertence.
string
obrigatório
UUID que identifica esta tentativa. Gere uma vez por venda e reutilize nas retentativas dessa mesma venda.
Não é isso que evita o documento duplicado — quem faz isso é o orderCode, que é a chave natural nas duas pontas: se você repetir o mesmo orderCode, recebe o mesmo documento mesmo gerando uma chave nova.O que esta chave acrescenta é detectar que você a reutilizou para outra venda: se a mesma chave chegar com um corpo diferente, o Fire responde 409 em vez de numerar. É uma proteção contra um bug do ponto de venda — não regerar a chave — que sem isso passaria despercebido.
string
Opcional. Um identificador seu para esta operação — o mesmo que você já usa nos seus logs.O Fire o guarda com a solicitação e o devolve em correlationId. Não muda nada do comportamento: serve para que, quando algo falhar, você possa cruzar o seu registro com o nosso sem ter que parear por horário e orderCode.Se você não enviar, correlationId vem null.

Corpo

É um payload próprio, não o da injeção de pedidos: só o que é necessário para numerar. Os nomes coincidem com os que você já usa (store, device, orderCode) para que você o monte recortando o que já tem, mas não envie o corpo completo do pedido — nada de products, payments nem shippingMethod. Cinco campos, e nenhum deles é um código do órgão.
string
obrigatório
Código da venda. É a chave de idempotência, a do Fire e a do provedor.Precisa ser único por conta e país, e o mesmo que você depois envia ao injetar o pedido. Se duas lojas da mesma conta usarem o mesmo orderCode, o Fire corta com 409 antes de emitir: sem esse corte, a segunda loja imprimiria o sequencial da primeira.
string
obrigatório
Data e hora de criação do pedido.Tem dois usos, e convém não confundi-los. É o fallback da data de emissão — a fonte principal é o dia de negócio aberto da loja, porque uma venda de madrugada pertence ao dia que segue aberto, não ao do relógio — e além disso viaja ao provedor fiscal como a hora em que a venda aconteceu, para os regimes que a exigem no comprovante.Sem fuso horário (2026-08-12 17:26:09), é interpretada como UTC. Ao provedor sai sempre normalizada, com Z.
string
padrão:"INVOICE"
O que se pede. Um de:
  • INVOICE — numerar a venda.
  • CANCEL — anular.
Você pede uma operação, não um tipo de documento. Com qual instrumento fiscal isso se materializa quem decide é o país: no Equador um cancelamento é uma nota de crédito com sua própria série de sequenciais; no Brasil é um evento de cancelamento que não produz comprovante novo.
Para anular você manda o mesmo orderCode da venda, com operation: "CANCEL". Nada mais: nem chaves fiscais, nem o número do documento original, nem identificadores do Fire.O Fire encontra o documento a compensar pela chave natural —país + orderCode + operação— e devolve a qual corresponde em document.compensates. Seu ponto de venda não precisa guardar nada nosso para poder anular.
object
obrigatório
A loja que emite. Com code, o Fire resolve o país, a identidade fiscal do emitente e o estabelecimento — não os envie você.
object
obrigatório
O aparelho que emite. É o mesmo bloco que você já manda na injeção de pedidos — não é preciso acrescentar nada.
Não declare o ponto de emissão. Antes havia um externalId com o qual o canal o informava; foi removido. Quem o atribui é o órgão sob o CNPJ/RUC do emitente, e o ponto de venda não fala essa língua: agora o provedor o resolve a partir do uid, igual ao que faz com store.code.Ele volta em countryData.puntoEmision, com o valor sob o qual foi efetivamente emitido.
array
O que foi cobrado. É o mesmo payments.totals que você já envia na injeção de pedidos — envie tal como está, inteiro.
O que se envia hoje, por país:Envie taxes[] com amount, não uma porcentagem solta. Um elemento por imposto, com name, base, rate e amount — a mesma forma em todos os países.O valor tem de vir calculado por você, que foi quem cobrou e imprimiu. Onde o identificador fiscal é um hash da nota —o CUFE colombiano— derivá-lo da porcentagem obriga outra pessoa a arredondar, e se ela arredondar diferente do caixa, o identificador deixa de corresponder ao papel que o cliente tem.
Os valores vão sem escalar. Envie o número tal como cobrou: 50000, 42016.81. Não o multiplique por 10.000.Essa escala existe, mas é de outro caminho: os eventos do pedido (order.completed e os demais) levam os mesmos valores como inteiro em string ×10.000, porque é assim que o FIRE os armazena. Aqui não.Se você integra os dois caminhos, essa é a única conversão que precisa fazer — e fazê-la ao contrário significa declarar dez mil vezes o montante.
Envie o valor tal como cobrou e imprimiu. O Fire não arredonda nem reformata: o número da requisição e o do comprovante são o mesmo.Importa porque há regimes em que o identificador fiscal é um hash da nota — o CUFE colombiano, por exemplo. Se o valor que entra no hash não é o impresso, o identificador não corresponde à nota que o cliente tem em mãos.
object
Quem comprou. É o mesmo bloco que você já envia na injeção de pedidos: envie inteiro, tal como está. Não recorte, não renomeie, não traduza.O Fire lê dali o que o regime do país precisa e descarta o resto. Que seja o bloco completo e não um subconjunto é de propósito: se cada país exigisse o seu próprio recorte, o ponto de venda teria de saber qual campo cada órgão olha — que é exatamente o que este contrato evita.Os demais campos —uid, email, phone, gender, birthdate, externalId— trafegam e não são fiscalizados. O Fire não os reenvia ao provedor fiscal: não são assunto do órgão.
Os valores que o Fire espera em govIdType:Hoje não há guard: mande o que mandar, a venda é numerada. O campo trafega tal como está até o provedor fiscal, então um valor fora desta lista não quebra a numeração — chega a ele, que é quem tem de reconhecê-lo.Por isso convém se ater: um CEDULA onde vai CI, ou duas grafias diferentes para o consumidor final, são documentos que saem errados sem que nada falhe no caminho.
Consumidor final: envie os dois campos, sem traduzir nenhum.
O número é você quem envia, igual a qualquer outra venda. O que não deve fazer é convertê-lo para o que cada regime exige: o NIT genérico 222222222222 da DIAN na Colômbia, a ausência de destinatário no Brasil. Isso é resolvido pelo provedor fiscal, que é quem está certificado perante o órgão.É deliberado: essa regra muda por país e por resolução do órgão, e não deveria obrigar você a fazer deploy do ponto de venda quando mudar.O Fire também não mexe. O bloco client trafega tal como está até o provedor: não preenchemos o número, não normalizamos e não validamos. O que você envia é o que ele recebe.
object
Chave-valor da venda: o que muda em cada transação e que algum país exige.É opaco para a sua integração: o Fire não interpreta, transporta. As chaves válidas dependem do país da loja e uma chave desconhecida é rejeitada com 400 — é preferível um erro do Fire a um campo inventado viajando até o órgão.Na maioria dos casos vai vazio: o que é constante da loja não se manda aqui, se configura uma vez (veja abaixo).

O que NÃO se manda: a configuração da loja

Tudo o que é constante da loja se configura uma única vez no backoffice e viaja sozinho: a identidade fiscal do emitente, e um bloco chave-valor por país para os atributos que o provedor daquele país precise.
Esse chave-valor vive na configuração fiscal da loja, separado por país. É a razão pela qual este endpoint é o mesmo em todo lugar: o que é específico de cada país se administra, não se programa nem se envia em cada venda.Se a sua integração começar a precisar de um campo novo por país, a resposta quase sempre é configurá-lo ali — não acrescentá-lo ao payload.
string
Só para CANCEL, e só quando a resolução automática não basta: um cancelamento que referencia um documento de outro pedido, ou várias notas para o mesmo.No caso normal não envie. O Fire encontra o original pela chave natural, então seu ponto de venda não precisa guardar nenhum identificador nosso para poder anular.

Resposta

string
Identificador da solicitação no Fire. É com ele que você consulta o desfecho depois.
string
Eco do código que você enviou.
string
Eco do header x-correlation-id, ou null se você não mandou. É para rastreabilidade: não participa da numeração nem da idempotência.
boolean
true se esta solicitação já existia e foi devolvida como estava, sem numerar de novo.
string
Status da numeração: consegui números para imprimir?Cinco valores possíveis. Os quatro primeiros descrevem como terminou a tentativa; o quinto diz que não houve tentativa porque esta loja não numera.
PENDING não significa “não há comprovante”: significa “não sabemos”. A comunicação caiu e o provedor pode ter numerado, consumido um sequencial e emitido o documento sem que a gente fique sabendo.Tente de novo com o mesmo orderCode. O Fire retoma a solicitação e volta a perguntar ao provedor; se da primeira vez numerou, você recebe esse mesmo documento em vez de um novo. Numerar de novo com outro orderCode seria declarar a mesma venda duas vezes ao órgão.
NOT_APPLICABLE é o único que não é gravado: não cria solicitação fiscal (fiscalRequestId: null) e não aparece nos eventos do pedido. Existe porque o PDV sempre chama este endpoint — é assim que ele descobre se a loja numera — e responder com um erro faria cada venda de uma loja sem gateway parecer uma falha.
string
Status do documento perante o órgão: ele autorizou?PENDING · AUTHORIZED · REJECTED · CANCELLED
Nesta resposta é sempre PENDING: há números, não há veredicto. Só o resultado do provedor o move, e ele chega depois. Colapsar os dois status em um é o erro que faz um PDV achar que uma venda está autorizada quando ela apenas está numerada.
string
Em qual ambiente o Fire numerou: SANDBOX ou PRODUCTION.É nosso, não do órgão. Sai da configuração fiscal da conta —que é por vendor e por país, então a mesma conta pode ter o Equador em produção e a Colômbia em sandbox— e fica congelado na solicitação: se amanhã a configuração mudar, este valor continua dizendo com o que esta venda foi numerada.
Não confunda com o ambiente do órgão, que viaja dentro de countryData com o vocabulário do país (ambiente: "PRUEBAS" | "PRODUCCION" no Equador). São dois fatos distintos: um diz contra qual configuração o Fire emitiu, o outro o que o órgão declarou. Normalmente coincidem — e quando não, é exatamente isso que você precisa poder ver, por isso um não se deduz do outro.
null quando requestStatus é NOT_APPLICABLE: nada foi numerado, então não houve ambiente em que numerar.
object
O que você precisa para imprimir, sem saber de países. null se nada foi numerado.
sequential e serie não estão mais aqui. São peças com forma de país —no Equador a série são seis dígitos que se partem ao meio— e vivem em countryData com o nome que o órgão delas lhes dá. Em document ficou só o que significa o mesmo em todo lugar.
object
Os identificadores do país, no vocabulário do seu órgão e prontos para imprimir.
O bloco muda inteiro conforme o país, e os rótulos também. Na Colômbia documentLabel é FACTURA ELECTRONICA DE VENTA e authorizationLabel é VALIDACION PREVIA — são os nomes da DIAN, não uma variante do texto equatoriano.ambiente chega traduzido nos dois países, e aí está o ponto: a DIAN codifica 1 como produção e o SRI como homologação. O Fire resolve isso para que nenhum canal precise carregar essa tabela.
É um mapa aberto: as chaves são definidas pelo regime de cada país, não por este contrato. Um país novo entra sem que a forma da resposta mude.
Os valores vêm traduzidos, não em código do órgão. O provedor manda ambiente: "2" —é assim que o SRI define— e aqui chega "PRODUCCION", que é o que o ticket diz. Traduzir do lado do canal significaria que cada integrador carrega sua cópia da tabela do órgão, e o primeiro que copiar errado imprime “PRUEBAS” numa nota de produção.
Não procure campos fixos: percorra as chaves que vierem. O Equador traz claveAcceso, o a Colômbia cufe, o Brasil chaveAcesso. Um canal que leia countryData.claveAcceso direto funciona no Equador e quebra no segundo país.

countryData por país

Hoje o gateway numera no Equador e na Colômbia. Cada país que entra soma sua aba aqui — e só isso: a forma da resposta não muda, porque o bloco é aberto.
Comprovantes do SRI.
Quem compõe o número é o provedor, não o Fire. O formato é do regime —quinze dígitos em três trechos, art. 18 do Reglamento de Comprobantes de Venta— e quem o conhece é quem está certificado perante o SRI. Se o regime mudar a convenção, muda lá e não é preciso que o Fire faça deploy.document.documentNumber é um eco deste mesmo valor, para que você não tenha que entrar no bloco do país só para imprimir. É o mesmo fato, não dois.
As três peças soltas não são um substituto. O Reglamento permite omitir os zeros à esquerda do sequencial, então 001-020-123 pode ser tão legal quanto 001-020-000000123. Compor o número você mesmo a partir de establecimiento, puntoEmision e secuencial é adotar uma convenção que não lhe cabe: imprima numeroComprobante tal como chega.
object
A filial que emite, para o cabeçalho do comprovante.
object
A pessoa jurídica que emite: o cabeçalho e o rodapé do comprovante, já resolvidos.
store, company e document.compensates vêm em toda resposta deste endpoint, incluindo NOT_APPLICABLE e o 400 de loja que não pode emitir, inclusive na da retentativa idempotente — o canal precisa do cabeçalho tanto na primeira vez quanto quando repete por uma queda de rede.As consultas (GET por fiscalRequestId ou orderCode) os devolvem em null: são resolvidos ao emitir e não são gravados com a solicitação. Se a sua integração precisar deles para reimprimir, use os dados de impressão.
object
Chave → string exata a codificar, pronta para renderizar. Por exemplo { "qr": "1208202601…811" }.É um mapa aberto porque o comprovante de cada país não leva sempre a mesma coisa, e um país pode precisar de mais de um elemento. Percorra as chaves que vierem, não procure campos fixos.O Fire não gera imagens: o tamanho e a resolução dependem da sua impressora, e isso só quem imprime sabe.
object
O que você pode imprimir. É uma regra legal do país, não uma derivação de haver documento: por isso quem resolve é o Fire e não cada canal.
object
O que fazer com a venda quando não deu para numerar. Quem decide é a conta, não você: se configura por vendor no backoffice e a Fire devolve a decisão já tomada, igual a printing.Viaja sempre, inclusive quando a numeração deu certo. Ramifique pelo valor, nunca pela presença da chave.
O que esta política decide, e o que não decide.Decide uma única coisa: se o caixa devolve o dinheiro ao cliente quando a venda foi cobrada e não deu para numerar. Nada mais.Não decide o que você imprime — isso é printing, e é uma regra legal do país, não uma preferência de ninguém. Não bloqueia vendas: quando você pede a numeração o cliente já pagou, então não há venda para bloquear. E não depende de retryable: uma falha que se resolve sozinha continua sendo uma falha, e se a conta configurou devolver, devolve-se.Quem configura é a conta, por país e por vendor, no backoffice. Você não deduz nem negocia: a Fire devolve resolvido, igual a printing. Se não estiver configurado, se trouxer um valor que não reconhecemos, ou se não conseguimos ler, aplica-se CONTINUE — o padrão aponta para esse lado de propósito, porque uma configuração mal escrita não pode disparar devoluções de dinheiro.Dois casos a ignoram por completo, não importa como esteja configurada: quando não houve falha (GENERATED ou NOT_APPLICABLE), e quando o que falhou foi um cancelamento (operation: "CANCEL") — ali o pedido existe e o dinheiro dele não foi devolvido, então não há o que devolver.Os outros dois campos são o recibo da decisão: configVersion diz com qual configuração se decidiu e resolvedFrom com qual contexto. Servem para reconstruir uma devolução de três semanas atrás mesmo que hoje a conta esteja configurada de outro jeito.
Onde se configura e o que acontece sem isso. A política é definida por conta, país e vendor. Se o vendor não tem, se traz um valor que não reconhecemos, ou se não conseguimos ler, aplica-se CONTINUE — e esse padrão aponta para esse lado de propósito: uma configuração mal escrita não pode disparar devoluções. Você vê isso como configVersion: null.
Cancelamentos nunca pedem devolução. Se o que falhou foi um operation: "CANCEL", a resposta traz CONTINUE independentemente da configuração: não há cobrança a estornar, porque a venda já aconteceu e continua válida. O que falta é o documento do cancelamento.PENDING obedece sim à configuração. O provedor não ter respondido não é uma exceção: para o caixa, não ter número é não ter comprovante. Você distingue de uma recusa apenas por resolvedFrom.requestStatus. Um PENDING traz failureCode como qualquer outro — um timeout chega como PROVIDER_TIMEOUT / TECHNICAL — então não procure na ausência do código.Tem uma consequência que vale ter em mente: o provedor pode ter numerado mesmo assim e não ter conseguido avisar. Se esse documento aparecer depois, vai existir um comprovante de uma venda que você devolveu, e ele precisa ser cancelado.

O que fazer quando chega REFUND

Três passos, nesta ordem. O terceiro é o que se esquece.
1

Devolva a cobrança no balcão

O cliente já pagou. Essa devolução é você quem faz com o seu meio de pagamento — a Fire não movimenta dinheiro nem sabe se você devolveu.
2

Não injete o pedido

Não mande para Criar pedido. Essa venda não aconteceu: injetá-la deixaria um pedido cobrado sem comprovante fiscal, o que é pior do que não tê-lo.
3

Reporte com Registrar venda perdida

POST /orders/lost-sales, copiando policy.numberingFailure.lostSaleReason em reason. É o único passo que nos avisa.
Se você pular o passo 3, essa venda não existe em lugar nenhum.Não há pedido —você não injetou— e não há evento. Do nosso lado só fica a solicitação fiscal que falhou, que diz que não deu para numerar mas não diz que houve dinheiro envolvido nem que você devolveu. Ninguém fica sabendo que aquela loja parou de vender, e o fechamento de caixa não consegue explicar.O reporte é a única trilha. Retentar é seguro — é idempotente por orderId + vendor — então se você ficou sem rede bem ali, acumule e reenvie.

Quando o que falha é um cancelamento

Cancelar são duas chamadas, nesta ordem: primeiro você pede aqui a numeração da nota de crédito (operation: "CANCEL"), e só depois chama Cancelar pedido. Se a numeração da nota falha, este endpoint responde como sempre: nunca um 4xx. PENDING e FAILED_RETRYABLE voltam 202; FAILED_FINAL volta 200. O corpo traz o failure com o motivo e o fiscalRequestId para escalar. E policy.numberingFailure.action vem sempre CONTINUE, com lostSaleReason: null, independentemente de como a conta esteja configurada. Não é uma exceção arbitrária: aqui não há cobrança a estornar. A venda já aconteceu, está em orders e continua válida — o que falta é o papel do cancelamento, não o dinheiro.
Mas o pedido não é cancelado. O cancel valida que a nota de crédito exista, e sem ela responde 409 FISCAL_CREDIT_NOTE_MISSING.Essa é a grande diferença em relação a uma venda: na venda a falha te deixa seguir com um ticket provisório; no cancelamento te deixa travado, com o pedido ainda válido.O que fazer: se retryable vier true, chame aqui de novo com o mesmo orderCode — a Fire retoma a solicitação. Se for FAILED_FINAL, leia failure.scope e escale com o fiscalRequestId: não há nada que o caixa possa fazer, e ninguém retenta por você.
Um FAILED_FINAL na nota de crédito não se resolve esperando. Essa solicitação fica gravada como definitiva, e chamar de novo com o mesmo orderCode — mesmo com o provedor já saudável — devolve a mesma resposta sem voltar a perguntar a ele. Não é uma retentativa que falha: é a resposta arquivada.A consequência é que esse pedido não pode mais ser cancelado por este caminho: continua vigente no Fire, com a sua nota, e Cancelar pedido responde 409 FISCAL_CREDIT_NOTE_MISSING para sempre. Escalar aqui não é “avise e tente de novo mais tarde” — é avise, porque isso já não se destrava sozinho.
object
Por que não há documento. null quando há.
PROVIDER_TIMEOUT e PROVIDER_CONTRACT_VIOLATION chegam com requestStatus: "PENDING", não com uma falha definitiva. Nos dois casos o provedor pode ter numerado sem que a gente consiga ler: emitir outro comprovante por fora declararia a mesma venda duas vezes ao órgão.
string
Nosso identificador de adaptador (hio), não o nome do provedor. É o que diz com qual integração esta venda foi numerada. null em NOT_APPLICABLE: nenhum interveio.
object
Quem numerou, do lado do provedor. Tem forma —os três campos fazem parte do contrato— e por isso viaja separado da bolsa opaca. null quando não se numerou nada.
object
A bolsa de diagnóstico do provedor, tal como chegou. Opaca: não tem forma garantida e ninguém deve programar contra suas chaves — elas mudam sem aviso e sem versionar o contrato. Serve para colar num ticket, não para ramificar.null quando o provedor não mandou nada.
É o mesmo campo que viaja no evento, com o mesmo nome e o mesmo conteúdo. Os três campos do provedor —providerCode, providerIdentity, providerMetadata— se leem igual aqui e em fiscalRepresentation: o que se aprende num extremo serve no outro.

Códigos de status

O código HTTP não diz se você conseguiu comprovante. 200 pode ser uma retentativa idempotente que numerou perfeitamente, ou uma rejeição definitiva do órgão. Ramifique por printing.mode e requestStatus, nunca pelo código sozinho.
A chamada é síncrona, mas tem um orçamento de tempo. O cliente está parado no caixa: o Fire espera o provedor alguns segundos e, se não responder, corta e devolve 202 em vez de deixar a venda pendurada.Esse 202 não é uma promessa de que depois chega por outro canal ao seu PDV: é o Fire dizendo “não tenho números ainda, imprima provisório e siga”.Para completá-la, tente de novo com o mesmo orderCode. O Fire retoma a solicitação e volta a perguntar ao provedor. É raro, mas existe porque a alternativa — falhar a venda — é pior.

O que fazer com cada resposta

O que segue descreve o caminho CONTINUE, que é o padrão e o da maioria das contas. Se policy.numberingFailure.action disser REFUND, a instrução se inverte: você não injeta o pedido e não retenta a numeração — devolve a cobrança e reporta a venda perdida.O resto de cada estado —o que significa e se a falha se resolve sozinha— vale nos dois casos.
printing.mode: "FISCAL_DOCUMENT". Imprima o comprovante com document.documentNumber e desenhe os códigos de graphic. Injete o pedido com o mesmo orderCode.Se printing.reason for ISSUED_OFFLINE, o comprovante é válido mas foi emitido em contingência: imprima a legenda que aquele país exige.
O provedor não respondeu: timeout ou conexão cortada. Pode ter numerado e consumido um sequencial sem que a gente fique sabendo.Imprima o ticket provisório e injete o pedido. Depois tente de novo com o mesmo orderCode: o Fire retoma a solicitação e volta a perguntar ao provedor, então se da primeira vez numerou, você recupera esse documento.
Não assuma que a venda ficou sem comprovante. Emitir um novo por outro caminho pode declarar a mesma venda duas vezes ao órgão.
O provedor respondeu que não pode agora. Diferente de PENDING, aqui sabemos com certeza que nada foi numerado.Imprima provisório, injete o pedido e tente de novo com o mesmo orderCode.
Tentar de novo com o mesmo corpo vai dar no mesmo. Leia failure.message, que traz o motivo real, e failure.scope, que diz de quem é o problema:
  • FUNCTIONAL — há um dado que o fisco não aceita. Corrige-se na venda ou na configuração da loja.
  • TECHNICAL — a integração com o provedor está quebrada. A venda está certa; o que falha é a conexão com quem numera. Ninguém no caixa consegue resolver.
Nos dois casos: imprima o ticket provisório, injete o pedido e escale com o fiscalRequestId. Com CONTINUE, a venda fica cobrada sem comprovante fiscal — isso também viaja nos eventos do pedido, para que você possa compensar. Com REFUND não há pedido nem evento: a única trilha é o reporte de venda perdida.
PROVIDER_AUTH_FAILED não é uma queda do provedor. Ele respondeu, e rápido: 742 ms no exemplo. O que ele rejeitou foi a nossa credencial —errada, revogada ou rotacionada do lado dele—, então é configuração e não algo transitório: por isso retryable é false e o estado é FAILED_FINAL, e não PENDING.Se em vez disso você vir PROVIDER_TIMEOUT com requestStatus: "PENDING", aí sim o provedor não respondeu a tempo — e aí vale tentar de novo.Repare também no bloco company do exemplo: a identidade chega para o cabeçalho, mas countryLines e legends vêm vazios porque não há comprovante declarando nada.
Não é um erro. Este vendor não tem representação fiscal: não há nada a numerar e nenhuma solicitação foi criada (fiscalRequestId: null).Imprima seu ticket de sempre e injete o pedido normalmente. É a resposta esperada para agregadores, países sem gateway fiscal e comércios com a numeração desativada.
store e company vêm aqui também. Nada foi numerado, então chega a identidade do emissor e não o aparato fiscal (countryLines e legends vazios). É o mesmo bloco de qualquer outra resposta: não há uma forma diferente para aprender neste caso.
Nestes casos nenhuma solicitação fiscal foi criada: corrija e chame de novo.Se você receber 404 com uma mensagem de loja não encontrada, verifique se a sua API key é a do vendor dono daquela loja — a mensagem inclui contra qual vendor foi buscado.O 400 de loja que não pode emitir traz a identidade do emissor em data. É o caso de uma loja sem CNPJ/RUC ou não habilitada: a venda já aconteceu e você ainda precisa imprimir um provisório, então o cabeçalho viaja junto com o erro.
Chame sempre. É assim que você sabe se a loja numera.Você não precisa sincronizar configuração nem decidir por país: se aquele vendor não tem representação fiscal, a resposta é 200 com requestStatus: "NOT_APPLICABLE" e printing.mode: "NONE" — você imprime seu ticket e segue. Não é um erro e nenhuma solicitação é criada.É o mesmo desvio que você já tem: você ramifica por printing.mode, não pelo código HTTP.

Anular

Você manda o mesmo orderCode da venda com operation: "CANCEL". Nada mais.
A resposta tem a mesma forma da de uma nota de venda. Mudam três coisas:
A nota de crédito tem sua própria numeração. Não continua a das notas de venda: no exemplo, a nota de venda é 005-004-000000068 e o cancelamento dela 005-004-000000002. São duas sequências distintas sob o mesmo estabelecimento e ponto de emissão.
O cancelamento é um comprovante fiscal novo, não uma exclusão. A nota original continua existindo perante o órgão e precisa ser conservada: o que a nota de crédito faz é compensá-la.Por isso GET /numbering?orderCode=… devolve dois documentos para aquele pedido.

Se não houver nada a anular

Se a venda nunca foi numerada —porque a loja não emite, ou porque a numeração falhou— o cancelamento responde 400:
É um 400, não uma falha dentro de um 200. É a única diferença importante entre anular e emitir: ao emitir, uma rejeição do órgão viaja como resposta bem-sucedida com requestStatus: "FAILED_FINAL", porque é a resposta à sua pergunta. Aqui não há pergunta a responder — você pediu para compensar algo que não existe.Seu ponto de venda imprime seu comprovante de cancelamento interno e segue.

Quando o cancelamento não se resolve na hora

Cancelar tem os mesmos desfechos incertos que faturar, e vale dizer em voz alta porque é fácil supor que cancelar sempre fecha.
Uma recusa deixa a venda faturada. Se o cancelamento voltar FAILED_FINAL, o documento original não foi compensado e continua produzindo efeitos fiscais. Não é um estado intermediário do qual o sistema saia sozinho: não há retentativa automática.Medido em produção sobre 72 pedidos cancelados: 67 fecharam o circuito, 3 ficaram aguardando confirmação e 2 foram recusados. Esses ~7% não se resolvem sem intervenção.
Cancelar o pedido e cancelar o documento são coisas diferentes. Seu pedido pode ficar cancelado na hora enquanto o cancelamento fiscal ainda está em andamento. Se você precisa de certeza fiscal — um fechamento contábil, uma conciliação — consulte o documento; o status do pedido não lhe dá isso.

Quando o instrumento não é uma nota de crédito

No Equador o cancelamento produz um documento novo. Em outros países não: no Brasil é um evento de cancelamento que não gera comprovante, e ali a resposta chega com status: "CANCELLED" e document: null. Não é um erro — é o desfecho correto daquela operação naquele país. Por isso você pede operation e não um tipo de documento: quem decide o instrumento é o regime.

Consultar uma solicitação

São dois endpoints de leitura, e existem para quando o caminho normal não basta: você perdeu a resposta síncrona, ou quer ver se o órgão já autorizou sem esperar o evento. Na operação diária você não deveria precisar deles — os dados chegam pelos eventos do pedido.
  • Por identificadorGET /numbering/{fiscalRequestId}.
  • Por pedidoGET /numbering?orderCode=…. Devolve items[], porque um pedido pode ter dois documentos: a nota de venda e o cancelamento que a compensa. É o que você usa quando perde a resposta por uma queda de rede — o orderCode é a única coisa que você tem em mãos.
Quando o órgão autoriza, documentStatus passa a AUTHORIZED.