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/XMLCó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 timeimport 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ção | Endpoint de emissão | Endpoint de consulta |
|---|---|---|
| Emitir NFe | POST /nfe/emissao | GET /nfe/nota/{recibo} |
| Carta de correção | POST /nfe/correcao | GET /nfe/correcao/{recibo} |
| Cancelar NFe | POST /nfe/cancelamento | GET /nfe/cancelamento/{recibo} |
| Emitir NFCe | POST /nfce/emissao | GET /nfce/cupom/{recibo} |
| Cancelar NFCe | POST /nfce/cancelamento | GET /nfce/cancelamento/{recibo} |
| Emitir NFSe | POST /nfse/emissao | GET /nfse/nota/{recibo} |
| Reconhecimento fornecedor | POST /nffornecedor/reconhecimento | GET /nffornecedor/{recibo} |
Headers úteis durante o polling
Toda resposta da API retorna headers que ajudam a rastrear e regular o consumo:
| Header | Uso |
|---|---|
X-Request-Id | Cite no suporte ao reportar problemas. |
X-RateLimit-Limit | Limite total de requisições na janela atual. |
X-RateLimit-Remaining | Quanto resta. Use para ajustar o ritmo. |
X-RateLimit-Reset | Unix timestamp em que o limite reseta. |
Se X-RateLimit-Remaining ficar baixo, aumente o intervalo entre consultas.