Guias
Sincronizar com ERP
Padrão de sincronização incremental do CRM para um ERP usando timestamps de mensagens.
Caso de uso: você precisa replicar contatos novos do CRM para um sistema externo (ERP, data warehouse, ferramenta de email marketing) periodicamente.
Anti-pattern: paginação por offset
❌ Não use offset para sincronização incremental.
Se novos contatos forem inseridos entre uma requisição e outra, você pula registros ou duplica. Use timestamps.
Padrão correto: filtro temporal
Mantenha um checkpoint (timestamp do último sync) no seu sistema. Em cada execução:
- Filtre por mensagens depois do checkpoint usando
from=<timestamp> - Avance o checkpoint para o
last_matched_atmais recente que viu - Persista o novo checkpoint só depois que o batch foi processado com sucesso
async function syncIncremental(checkpoint: string) {
const url = new URL("https://crm.oficinamartech.com/api/contacts/message-search");
url.searchParams.set("organization_id", ORG_ID);
url.searchParams.set("q", "*"); // termo curinga ou seu filtro
url.searchParams.set("from", checkpoint);
url.searchParams.set("limit", "100");
const all: Contact[] = [];
let offset = 0;
while (true) {
url.searchParams.set("offset", String(offset));
const res = await fetch(url, {
headers: { Authorization: `Bearer ${OFM_API_KEY}` },
});
const json = await res.json();
all.push(...json.data);
if (!json.pagination.has_more) break;
offset = json.pagination.next_offset;
}
// Calcula novo checkpoint
const newCheckpoint = all.reduce(
(max, c) => (c.last_matched_at > max ? c.last_matched_at : max),
checkpoint,
);
// Processa e persiste
await persistInErp(all);
await saveCheckpoint(newCheckpoint);
return all.length;
}Frequência
| Sua necessidade | Frequência sugerida |
|---|---|
| Time real (lead novo → ligar) | 1-5 minutos |
| Operacional (CRM ↔ ERP) | 15-30 minutos |
| Analítico (data warehouse) | 1-4 horas |
| Bulk diário | 1x ao dia (madrugada) |
Webhooks de entrada (em vez de pull periódico) estão planejados. Acompanhe o roadmap.
Tratamento de falhas
- Se a requisição falhar, não avance o checkpoint — repita no próximo ciclo
- Se uma parte do batch falhar ao persistir, persista o checkpoint apenas até o ponto bem-sucedido
- Use retry com backoff para erros transitórios
Detecção de duplicatas
from é inclusivo — um contato com last_matched_at igual ao checkpoint atual aparece novamente. Faça deduplicação por contact.id no seu lado, ou use from=<checkpoint + 1ms>.