Sincronizar clientes e produtos
Quando você tem um sistema próprio (ERP, e-commerce) integrado ao FazNota, é comum precisar manter os cadastros sincronizados. Esta página mostra padrões eficientes para isso.
Quando sincronizar
| Cenário | Recomendação |
|---|---|
| Cadastro de cliente novo no seu sistema | Push imediato para o FazNota (POST) |
| Alteração de cliente | Push (PUT) sob demanda |
| Pull periódico (espelhar FazNota → seu sistema) | A cada 1h ou diário, paginado |
| Inicial (primeira sincronização) | Paginação completa, off-peak |
Push sob demanda (sistema → FazNota)
A forma mais simples: cada operação no seu sistema dispara uma chamada ao FazNota.
// Pseudo-códigoasync function onClienteSalvo(cliente) { if (cliente.isNew) { await mApi('POST', '/clientes', toMyseFormat(cliente)); } else { await mApi('PUT', `/clientes/${cliente.cpfCnpj}`, toMyseFormat(cliente)); }}Vantagens: simples, baixa latência. Desvantagem: se a chamada falhar, fica fora de sincronia até retry.
Pull com paginação completa (FazNota → sistema)
Para espelhar todos os clientes/produtos do FazNota no seu sistema:
async function sincronizarTodosClientes(token) { const todos = []; let pagina = 1; const tamanho = 100;
while (true) { const url = `${BASE}/clientes?page=${pagina}&page_size=${tamanho}`; const res = await fetch(url, { headers: { Authorization: `Token ${token}` }, }); const json = await res.json();
if (json.status !== '005' || !json.data) break; if (json.data.length === 0) break;
todos.push(...json.data);
if (json.data.length < tamanho) break; pagina++;
// Respeitando rate limit await new Promise((r) => setTimeout(r, 200)); }
return todos;}Pull incremental (apenas o que mudou)
Hoje o FazNota oferece o filtro dataInicial em NFSe. Para outros recursos
(clientes, produtos, NFe, NFCe), use o id como marcador:
async function sincronizarNovosClientes(token, ultimoIdSincronizado) { // Pega a primeira página (mais recentes vêm primeiro) const res = await fetch(`${BASE}/clientes?page=1&page_size=100`, { headers: { Authorization: `Token ${token}` }, }); const json = await res.json(); if (json.status !== '005') return [];
// Para nos clientes que já vimos const novos = []; for (const c of json.data) { if (c.id <= ultimoIdSincronizado) break; novos.push(c); }
return novos;}Sincronização de NFSes (com dataInicial)
async function sincronizarNFSes(token, dataInicial) { const todos = []; let pagina = 1; const tamanho = 50;
while (true) { const url = `${BASE}/nfse?dataInicial=${dataInicial}&page=${pagina}&page_size=${tamanho}`; const res = await fetch(url, { headers: { Authorization: `Token ${token}` }, }); const json = await res.json();
if (!json.data || json.data.length === 0) break; todos.push(...json.data); if (json.data.length < tamanho) break; pagina++;
await new Promise((r) => setTimeout(r, 200)); }
return todos;}
// Uso:const ontem = '2026-05-12';const nfses = await sincronizarNFSes(token, ontem);Boas práticas
-
Use cache local. Não consulte o FazNota a cada operação interna se você já tem os dados em cache. Use TTL razoável (1h para clientes, 15 min para notas em emissão).
-
Backoff exponencial em retries. Se uma sincronização falhar, espere 1s, 2s, 4s antes de tentar novamente.
-
Limite a concorrência. Não faça 100 chamadas simultâneas — use no máximo 5–10 em paralelo.
-
Monitore rate limit. Olhe
X-RateLimit-Remainingem cada resposta. Se ficar baixo, reduza o ritmo. -
Idempotência em escrita. Use
numero-origemúnico em emissões, e em POST de clientes/produtos use upsert (POST seguido de PUT se falhar por duplicidade).
Anti-padrões
| ❌ Evite | ✅ Prefira |
|---|---|
setInterval consultando a cada 1 segundo | Polling com intervalo de 30s+ ou eventos manuais |
for (i=1; i<99999; i++) fetch(...) em paralelo | Loop sequencial com await e pausa entre páginas |
| Consultar lista completa toda vez | Cache local + sincronização incremental |
| Esquecer rate limit headers | Monitorar X-RateLimit-Remaining |