CRM Oficina Martech
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:

  1. Filtre por mensagens depois do checkpoint usando from=<timestamp>
  2. Avance o checkpoint para o last_matched_at mais recente que viu
  3. 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 necessidadeFrequê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ário1x 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>.