O pior erro de integração fiscal não é a nota recusada: é a nota emitida duas vezes para a mesma venda. Ela acontece quando o envio sai, a resposta se perde no caminho (queda de internet, tempo esgotado, fila que reentrega a mensagem) e o sistema, sem saber, manda de novo. A Idempotency-Key existe para isso.
A regra em uma frase
Uma Idempotency-Key, no máximo uma nota autorizada.
Use como chave algo que já identifica a venda no seu sistema: o número do pedido, da ordem de serviço ou da fatura. Até 100 caracteres. Ela é obrigatória em toda emissão.
O que acontece em cada cenário
| Você manda | A API responde | O que fazer |
|---|---|---|
| A mesma chave e o mesmo corpo, de novo | 200 com "repetida": true e a mesma nota | Nada: é a nota que já existia. |
| A mesma chave com OUTRO corpo | 409 | Se é outra venda, use outra chave. |
| A mesma chave enquanto a primeira ainda processa | 409 | Consulte em alguns segundos. |
| A mesma chave depois de uma recusa (422) | Processa de novo | Corrija o corpo e mande: nenhuma nota existe. |
| Uma chave nova para a mesma venda | Uma nota nova | Evite: é assim que nasce a nota em dobro. |
O jeito certo de tentar de novo
async function emitir(pedido, nota) {
for (let tentativa = 1; tentativa <= 5; tentativa++) {
try {
const r = await fetch('https://erp.datafrontier.com.br/api/v1/nfe', {
method: 'POST',
headers: {
'X-Chave-Integracao': process.env.DF_CHAVE_API,
'Idempotency-Key': `pedido-${pedido.id}`, // SEMPRE a mesma para a mesma venda
'Content-Type': 'application/json',
},
body: JSON.stringify(nota),
});
// 201 autorizada, 200 repetida, 202 pendente: todas são "a nota desta venda".
if ([200, 201, 202].includes(r.status)) return r.json();
if (r.status === 422) throw new Error('Corrigir a nota: ' + JSON.stringify(await r.json()));
if (r.status !== 503 && r.status !== 409) throw new Error('HTTP ' + r.status);
} catch (e) {
if (tentativa === 5 || String(e.message).startsWith('Corrigir')) throw e;
}
await new Promise((ok) => setTimeout(ok, tentativa * 2000)); // espera crescente
}
}Repare que a chave é montada a partir do pedido, não gerada a cada tentativa. Um identificador aleatório novo por tentativa desliga toda a proteção.
Um detalhe que poupa dor de cabeça
Corpo inválido nem "gasta" a chave: se a validação da API recusar antes de ir à Sefaz, você corrige e manda de novo com a mesma chave. E o 202 (pendente) também é resposta final para esta regra: não reenvie com chave nova. O próximo tutorial explica o que fazer com ele.
Conhecer a API de nota fiscal Documentação completa
Tutorial escrito pela equipe da API em 29 de setembro de 2026, conferido com a versão v1 no ar. Regra fiscal muda: o enquadramento de imposto da sua empresa é com o seu contador. Viu algo desatualizado? Fale com a gente pelo WhatsApp.