Pular para o conteúdo principal

Sincronizar contatos da HubSpot por API sem perder nenhuma atualização

sincronizar contatos HubSpot API

Sincronizar contatos da HubSpot parece a tarefa mais simples do mundo até a segunda execução. A primeira roda traz tudo, funciona lindamente, e você marca a tarefa como concluída. Aí chega a segunda execução, e com ela uma escolha que define o destino inteiro da integração: você traz a base toda de novo, o que é lento, caro e some com os limites de taxa, ou traz só o que mudou desde a última vez, o que é rápido e elegante, mas cheio de armadilhas para quem não conhece as regras.

A resposta certa é quase sempre a sincronização incremental, e ela depende inteiramente de uma coisa: como você usa as datas de criação e de modificação dos registros. Acertar esse detalhe é a diferença entre uma rotina que roda em segundos e captura cada mudança fielmente, e uma rotina que perde atualizações em silêncio ou que vai entupindo o destino de duplicatas até ninguém mais confiar no que está lá.

Neste guia, vou te mostrar o padrão incremental completo, do primeiro carregamento da base ao ponteiro que torna cada rodada seguinte quase instantânea. É o mesmo padrão que sustenta um BI sempre atualizado, um ERP que recebe exatamente os contatos certos e uma régua de relacionamento que não deixa ninguém de fora por causa de um dado velho.

Os dois carimbos de tempo que mandam na sincronização

Todo registro na HubSpot carrega dois campos de data que são o coração de qualquer sincronização: createdate, que marca quando o registro foi criado, e hs_lastmodifieddate, que marca a última vez que ele mudou. A carga inicial varre a base por createdate, do mais antigo ao mais novo. A sincronização incremental, da segunda execução em diante, faz uma busca por hs_lastmodifieddate maior que o instante em que a última rodada terminou. Esse filtro por data de modificação é poderoso porque captura, de uma vez só, tanto os contatos novos quanto os que foram editados, sem você precisar tratar os dois casos separadamente.

POST /crm/v3/objects/contacts/search

{

"filterGroups": [

{ "filters": [

{ "propertyName": "hs_lastmodifieddate", "operator": "GTE", "value": "1719700000000" }

] }

],

"sorts": [{ "propertyName": "hs_lastmodifieddate", "direction": "ASCENDING" }],

"properties": ["email", "firstname", "lastname", "hs_lastmodifieddate"],

"limit": 100

}

Por que isso importa para a sua operação

Uma sincronização incremental bem feita é o que mantém os seus sistemas falando a mesma língua sem nenhum esforço humano. O time de vendas vê no ERP exatamente o mesmo contato que o marketing vê na HubSpot. O BI reflete a base de hoje, não a de uma semana atrás. Quando a sincronização perde atualizações, o efeito é pior do que não ter sincronização alguma, e esse é um ponto que pouca gente percebe. Sem sincronização, todo mundo sabe que precisa conferir na HubSpot. Com uma sincronização furada, todo mundo confia em um dado que está errado: uma mudança de estágio que não propagou, um email atualizado que não chegou no outro sistema, e a decisão é tomada em cima de informação velha, com a falsa sensação de que está tudo certo.

O erro que faz você perder atualizações

O instinto de quase todo mundo é usar o horário exato em que a última sincronização terminou como ponto de corte da próxima. Não faça isso. Volte para trás e trabalhe sempre com uma janela que tem sobreposição. O motivo é técnico e importante: registros alterados bem na virada do corte podem escapar da busca, seja por uma pequena diferença de relógio entre o seu sistema e os servidores da HubSpot, seja, mais comum, porque a Search API lê de um índice com consistência apenas eventual. Um registro recém-criado ou recém-alterado, mesmo já com o hs_lastmodifieddate preenchido, pode levar alguns instantes, e às vezes vários minutos, para aparecer nos resultados da busca. Por isso a janela de sobreposição deve ser pelo menos tão larga quanto esse atraso de indexação, e não apenas alguns segundos.

Dica de quem já apanhou: prefira sempre repetir a perder. Uma janela com sobreposição de alguns minutos traz alguns registros repetidos, que você remove de graça na deduplicação por id. Perder uma atualização, ao contrário, é um erro silencioso que ninguém percebe até o dado divergir lá na frente, quando já é tarde demais para saber exatamente o que escapou e quando.

Pagine e deduplique por id

A busca pagina por cursor e carrega o teto de 10.000 registros por conjunto de filtros, igual a qualquer outra busca. Se uma janela de sincronização trouxer mais que isso, estreite o intervalo de tempo até caber abaixo do teto. E, no momento de gravar no destino, use sempre o id do contato como chave da operação. É isso que faz a mágica funcionar: um contato que aparece duas vezes por causa da sobreposição da janela é simplesmente atualizado pela segunda vez, em vez de virar um registro novo. A deduplicação por id é o que torna a sobreposição segura, porque você ganha a garantia de nunca perder uma mudança sem pagar o preço de duplicar registros.

O que fazer em picos de atividade

Em dias de campanha grande, de importação de listas ou de uma automação que tocou muitos registros de uma vez, uma janela curta de tempo pode estourar o teto de 10.000 com facilidade. Nesses casos, a solução é estreitar a janela de forma dinâmica: se uma faixa de tempo trouxe um volume perto do teto, divida-a pela metade e rode as duas metades separadamente. Isso mantém cada busca confortavelmente abaixo do limite mesmo quando o volume de mudanças dispara, e evita que um pico de atividade quebre a sincronização justo no momento em que ela é mais necessária.

Lidando com exclusões e arquivamentos

A sincronização incremental por data de modificação captura criações e edições com elegância, mas tem um ponto cego importante que você precisa tratar conscientemente: as exclusões. Quando um contato é apagado ou arquivado na HubSpot, ele simplesmente para de aparecer na busca, sem deixar nenhum rastro ou aviso. Se o seu destino precisa refletir essas exclusões, trate-as à parte, por exemplo comparando periodicamente o conjunto de ids ativos na HubSpot com o conjunto de ids que existe no destino, e marcando como inativo tudo o que sumiu da origem mas continua no destino.

Vale decidir essa política cedo, no desenho da integração: o destino espelha exclusões ou apenas acumula registros para sempre? Para um BI histórico, talvez você prefira manter o registro com uma marca de inativo, preservando o histórico. Para um ERP operacional, talvez precise remover de fato para não trabalhar com dados mortos. Não existe uma resposta única e certa, mas existe a obrigação de escolher de forma consciente, porque o silêncio da API sobre as exclusões não vai tomar essa decisão por você.

Guarde o novo ponto de corte

No fim de cada execução, salve o maior hs_lastmodifieddate que você efetivamente processou naquela rodada. A próxima sincronização vai partir exatamente desse ponto, menos a margem de sobreposição que você definiu. Esse ponteiro persistido é o que transforma a rotina em algo realmente incremental, em vez de varrer um intervalo fixo arbitrário toda vez. Guarde-o num lugar que sobreviva entre as execuções: um campo numa tabela de controle, uma variável de estado do fluxo de automação, um arquivo dedicado. O importante é que ele não se perca quando a rotina termina.

O fluxo completo, do início ao fim

  1. Carga inicial: varra a base por createdate, paginando por cursor, e grave tudo no destino usando o id do contato como chave.
  2. Guarde o ponteiro: salve o maior hs_lastmodifieddate processado nessa primeira carga.
  3. Sincronização incremental: busque por hs_lastmodifieddate maior que o ponteiro, menos a janela de sobreposição.
  4. Pagine a busca por cursor; se uma janela passar de 10.000 registros, estreite o intervalo de tempo e rode de novo.
  5. Deduplique por id ao gravar, para que a sobreposição da janela atualize em vez de duplicar.
  6. Atualize o ponteiro com o novo máximo de hs_lastmodifieddate e repita o ciclo na próxima rodada.

Na prática: a base que crescia sozinha de madrugada

Uma operação rodava a sincronização de contatos toda noite e a base de destino inchava sem parar, noite após noite. A rotina não tinha ponteiro nem deduplicação por id: ela simplesmente recriava registros a cada execução, somando duplicata sobre duplicata. Em poucas semanas, o destino tinha quase o triplo de contatos que a HubSpot realmente continha, e qualquer relatório construído em cima daquela base era pura ficção, com taxas e totais que não significavam nada.

A correção foi adotar o ponteiro de hs_lastmodifieddate e deduplicar por id na gravação, e o efeito foi duplo e imediato. O crescimento fantasma da base parou na primeira noite. E, de quebra, a sincronização passou a rodar em uma fração do tempo, porque deixou de reprocessar a base inteira e passou a tocar apenas os contatos que de fato mudaram desde a noite anterior. A mesma rotina que levava horas passou a terminar em minutos, com um dado finalmente confiável no outro lado.

Reflexão para quem lidera a operação: uma sincronização confiável é invisível quando funciona e catastrófica quando falha em silêncio. O investimento em fazer o incremental direito, com ponteiro, sobreposição e deduplicação, não aparece no dia a dia, mas é o que garante que cada decisão tomada nos outros sistemas se apoie em um dado que reflete a realidade da HubSpot. Dado sincronizado não é luxo técnico, é a base da confiança entre as áreas.

Checklist da sincronização incremental

  1. A carga inicial varre por createdate e grava com o id do contato como chave?
  2. A sincronização incremental busca por hs_lastmodifieddate maior que o ponteiro?
  3. Existe uma janela de sobreposição de alguns minutos no ponto de corte?
  4. A busca pagina por cursor e estreita o intervalo quando passa de 10.000?
  5. A gravação deduplica por id, para a sobreposição não criar duplicatas?
  6. As exclusões e arquivamentos têm uma política definida e tratada à parte?
  7. O ponteiro do maior hs_lastmodifieddate é persistido entre as rodadas?

Perguntas frequentes

Por que usar uma janela com sobreposição?

Para não perder registros alterados na virada do corte. A Search API lê de um índice com consistência eventual, então um registro recém-alterado pode levar alguns instantes, às vezes minutos, para aparecer, e os relógios entre sistemas podem variar. Dimensione a sobreposição para cobrir esse atraso de indexação. Ela traz alguns repetidos, removidos de graça pela deduplicação por id.

Devo sincronizar por createdate ou por hs_lastmodifieddate?

Carga inicial por createdate. Sincronização incremental por hs_lastmodifieddate, que captura tanto contatos novos quanto editados desde o último corte, num filtro só. Uma ressalva para contatos: eles têm dois campos de modificação, lastmodifieddate (mudanças de propriedade, visível no app) e hs_lastmodifieddate (qualquer atividade, incluindo engajamento como abertura de email e pageview). O hs_lastmodifieddate pega mais, mas pode subir por motivos alheios ao seu dado, então escolha conscientemente. A resposta ainda traz um campo updatedAt no nível de cima, que espelha esse valor e é consistente para guardar como ponteiro.

O que faço se a janela passar de 10.000 registros?

Estreite o intervalo de tempo até ficar abaixo do teto da Search API, e pagine cada faixa por cursor. Em picos de atividade, divida a janela pela metade de forma dinâmica.

Como evito duplicar contatos no destino?

Use o id do contato como chave ao gravar. Assim um contato que aparece duas vezes por causa da sobreposição é atualizado em vez de criar um registro novo.

Como trato exclusões na sincronização incremental?

A busca por data de modificação não enxerga exclusões. Trate-as à parte, comparando os ids ativos na HubSpot com os do destino e marcando como inativo ou removendo o que sumiu, conforme a sua política.

Dá para sincronizar empresas e negócios do mesmo jeito?

Sim. O padrão de createdate para carga inicial e hs_lastmodifieddate para incremental vale para qualquer objeto. Muda só o tipo na URL e as propriedades que você pede.

Tem um CRM, um ERP ou um BI que precisa receber os contatos atualizados da HubSpot, sem perder nem duplicar? Na Insight Sales desenhamos sincronizações incrementais que rodam confiáveis em volume. Fale com a gente e descubra como podemos ajudar.

Pronto para levar sua operação ao próximo nível.

Fale com um especialista e descubra como podemos ajudar.

paper-plane