Pular para o conteúdo

Fluxo assíncrono de emissão

Toda emissão de documento fiscal na API do FazNota é assíncrona. O motivo é simples: a comunicação com a SEFAZ pode levar de segundos a minutos, dependendo do volume e da disponibilidade do servidor estadual. A API responde imediatamente com um recibo e processa a emissão em segundo plano.

Diagrama do fluxo

sequenceDiagram
participant App as Sua aplicação
participant API as API do FazNota
participant SEFAZ as SEFAZ
App->>+API: POST /nfe/emissao
API-->>-App: status=001, recibo=abc123
Note over API,SEFAZ: Processamento assíncrono
API->>+SEFAZ: Envia XML
SEFAZ-->>-API: Autorização
loop Polling com backoff (intervalo mínimo 2s)
App->>+API: GET /nfe/nota/abc123
API-->>-App: status=002 (pendente) → 003 (emitindo) → 004 (emitida)
end
Note over App: status=004 → buscar DANFE/XML

Códigos de status durante o ciclo de vida

Após enviar uma emissão, o status retornado pelas consultas evolui assim:

001 (registrado) → 002 (pendente) → 003 (emitindo) → 004 (emitida) ✅
↘ 010 (cancelada)
↘ 900 (rejeitada SEFAZ — ou SEFAZ lenta, ver nota abaixo)
↘ 999 (erro interno)
# 900 pode voltar para 004 sozinho: se sefaz.codigo for 217/105, a SEFAZ ainda está
# processando e o resultado se resolve em minutos (reconciliação automática, até 3h).

Veja a tabela completa para o detalhamento.

Como implementar o polling

Regras de ouro

Exemplo em JavaScript

async function aguardarEmissao(recibo, token) {
const url = `https://api.mysebr.com.br/nfemyse-v3/rest/nfe/nota/${recibo}`;
const TERMINAIS = ['004', '010', '999'];
// SEFAZ lenta/instável: 900 com um desses códigos NÃO é definitivo, continue consultando.
// Ver: https://faznota.com.br/api/v3/conceitos/instabilidade-sefaz/
const SEFAZ_CODIGO_TRANSITORIO = ['217', '105'];
let intervalo = 2000; // 2 segundos iniciais
const intervaloMax = 30000; // 30 segundos no máximo
const inicio = Date.now();
const timeoutTotal = 5 * 60 * 1000; // 5 minutos
while (Date.now() - inicio < timeoutTotal) {
const res = await fetch(url, {
headers: { Authorization: `Token ${token}` },
});
const json = await res.json();
const ehTerminal =
TERMINAIS.includes(json.status) ||
(json.status === '900' && !SEFAZ_CODIGO_TRANSITORIO.includes(json.data?.sefaz?.codigo));
if (ehTerminal) {
return json;
}
await new Promise((r) => setTimeout(r, intervalo));
// Backoff exponencial até 30s
intervalo = Math.min(intervalo * 1.5, intervaloMax);
}
throw new Error(`Timeout consultando recibo ${recibo}`);
}

Exemplo em Python

import time
import requests
def aguardar_emissao(recibo, token, timeout=300):
url = f"https://api.mysebr.com.br/nfemyse-v3/rest/nfe/nota/{recibo}"
headers = {"Authorization": f"Token {token}"}
terminais = {"004", "010", "999"}
# SEFAZ lenta/instável: 900 com um desses códigos NÃO é definitivo, continue consultando.
# Ver: https://faznota.com.br/api/v3/conceitos/instabilidade-sefaz/
sefaz_codigo_transitorio = {"217", "105"}
intervalo = 2
inicio = time.time()
while time.time() - inicio < timeout:
r = requests.get(url, headers=headers, timeout=30)
data = r.json()
codigo_sefaz = (data.get("data") or {}).get("sefaz", {}).get("codigo")
eh_terminal = data["status"] in terminais or (
data["status"] == "900" and codigo_sefaz not in sefaz_codigo_transitorio
)
if eh_terminal:
return data
time.sleep(intervalo)
intervalo = min(intervalo * 1.5, 30)
raise TimeoutError(f"Timeout consultando recibo {recibo}")

Outros endpoints assíncronos

O mesmo padrão se aplica a:

OperaçãoEndpoint de emissãoEndpoint de consulta
Emitir NFePOST /nfe/emissaoGET /nfe/nota/{recibo}
Carta de correçãoPOST /nfe/correcaoGET /nfe/correcao/{recibo}
Cancelar NFePOST /nfe/cancelamentoGET /nfe/cancelamento/{recibo}
Emitir NFCePOST /nfce/emissaoGET /nfce/cupom/{recibo}
Cancelar NFCePOST /nfce/cancelamentoGET /nfce/cancelamento/{recibo}
Emitir NFSePOST /nfse/emissaoGET /nfse/nota/{recibo}
Reconhecimento fornecedorPOST /nffornecedor/reconhecimentoGET /nffornecedor/{recibo}

Headers úteis durante o polling

Toda resposta da API retorna headers que ajudam a rastrear e regular o consumo:

HeaderUso
X-Request-IdCite no suporte ao reportar problemas.
X-RateLimit-LimitLimite total de requisições na janela atual.
X-RateLimit-RemainingQuanto resta. Use para ajustar o ritmo.
X-RateLimit-ResetUnix timestamp em que o limite reseta.

Se X-RateLimit-Remaining ficar baixo, aumente o intervalo entre consultas.