Skip to main content
A maioria dos parceiros já tem um CRM (HubSpot, RD Station, Pipedrive, ActiveCampaign, Salesforce) que é a fonte de verdade dos contatos. Este guia mostra como manter a comunidade Cativa em sincronia com o CRM usando a API administrativa (lookup por email, criação de usuário, vínculo de external-id, atribuição de badge) e quais as decisões de design (chave natural, conflitos, idempotência) que você precisa tomar.

Cenário

Seu time de marketing usa HubSpot. Cada vez que um lead é qualificado e ganha a tag Pago Anual lá, você quer que essa pessoa apareça na sua comunidade Cativa com o badge Premium (que dá acesso ao grupo VIP, ao curso pago, etc.). Quando a tag é removida (ou o cliente cancela), o badge precisa sair. A Cativa é a fonte de verdade da comunidade (quem está no grupo, quem completou qual lição, quem postou o quê). O CRM é a fonte de verdade da relação comercial (lead, oportunidade, cliente, churn). A integração faz a ponte entre os dois.

Pré-requisitos

  1. API Key da Cativa: gerada no Console (Developers > API Keys). Veja Quick Start: API Key. Todas as chamadas abaixo usam Authorization: Bearer cativa_live_....
  2. Acesso de API ao seu CRM: token do HubSpot, da RD Station, etc. A Cativa não fornece SDK pra esses CRMs; use os SDKs oficiais (@hubspot/api-client, pipedrive-node-sdk, etc.).
  3. Um servidor de integração rodando do seu lado: pode ser um worker Node, um Cloud Function/Lambda, um job no Airflow, qualquer coisa que execute código com acesso aos dois lados.

Mapeamento conceitual

A pergunta central é: como reconhecer que o contato 1234 no HubSpot é o mesmo usuário 01HQ7Z3X4Y... na Cativa? A chave natural recomendada é o email (ela está dos dois lados desde o cadastro). Depois do primeiro casamento, cacheie o vínculo dos dois lados: guarde o Contact ID do CRM no usuário Cativa com PATCH /admin/users/{userId}/external-id e, se quiser, guarde o User ID Cativa numa propriedade custom do CRM (ex: cativa_user_id). Assim você para de depender de lookup por email a cada execução.
A Cativa tem um campo de ID externo no User, gravável via PATCH /admin/users/{userId}/external-id. Use-o como a forma canônica de vincular a chave do seu CRM ao usuário Cativa. Com o vínculo persistido no próprio usuário, a tabela de mapeamento local (descrita abaixo) vira opcional (só uma otimização de cache do seu lado).

Dois fluxos possíveis

Quando usar: você não tem webhook do CRM disponível, ou os volumes são pequenos (até alguns milhares de contatos), ou um delay de minutos/horas é aceitável.Um worker do seu lado roda numa frequência (ex: a cada 15 minutos), lê o estado do CRM, lê o estado da Cativa, calcula o diff e aplica.
Prós: simples de implementar, fácil de debugar, fácil de fazer backfill. Contras: delay (não é real-time), gasto desnecessário de API calls quando nada mudou.

Descobrir e vincular um usuário existente

O casamento pelo email é o coração da sincronização. Faça uma vez por contato e persista o vínculo no próprio usuário Cativa.
1

Resolva o email para o usuário Cativa

GET /admin/users/email/{email} retorna o usuário com aquele email no tenant da sua chave. Este é o caminho canônico da sincronização CRM.
Resposta 200 OK (ilustrativa; schema completo na API Reference, tag Users):
Se o email não existe no tenant, o endpoint responde 404 Not Found, trate esse caso como “criar usuário” (seção abaixo):
2

Grave o Contact ID do CRM no usuário Cativa

Capture o id do retorno e, logo em seguida, grave o Contact ID do seu CRM no usuário com PATCH /admin/users/{userId}/external-id:
Resposta 200 OK (ilustrativa) com o vínculo já refletido:
Com o vínculo persistido no próprio usuário Cativa, os próximos syncs não precisam mais refazer o lookup por email.
Se sua chave é dona de um usuário e você só quer conferir a credencial e o tenant, GET /tenant/api/v2/auth/me retorna o usuário dono da chave e o customer (tenant) ao qual ela pertence:
Resposta 200 OK (ilustrativa):

Opcional: tabela de mapeamento local como cache

O external-id no usuário Cativa já resolve o vínculo. Se ainda assim você quiser evitar toda ida à API da Cativa (por latência ou custo), mantenha uma tabela de cache do seu lado:
E popule via webhook:
  1. Cadastre um listener Cativa pro evento user_created. Toda vez que alguém entra na comunidade, o webhook chega com User.Id e User.Email. Insere/atualiza essa linha.
  2. Cadastre um listener pro evento user_received_badge. Toda mudança de badge atualiza a linha.
Depois disso, seu worker de sync resolve email para cativa_user_id localmente. Trate a tabela como cache: a fonte de verdade do vínculo continua sendo o external-id gravado no usuário Cativa.

Criar usuário a partir do CRM

Quando o contato do CRM ainda não existe na Cativa (o lookup por email retorna 404), crie o usuário com POST /admin/users. Aproveite e já grave o externalId no mesmo request:
Resposta 201 Created (ilustrativa), guarde o id (e o externalId já vinculado) para os próximos syncs:
O schema completo do body está na aba API Reference, tag Users. Se preferir que o próprio usuário defina a senha, envie o link de cadastro do tenant pelo seu CRM (HubSpot Email, RD Station Email) em vez de criar via API. Para grandes massas iniciais (milhares de contatos), o time da Cativa também importa uma planilha via Console. Alinhe em dev@cativa.digital.

Atribuir badge

A atribuição de badge por API Key administrativa está disponível. Há duas formas, sob /admin/membership/badges: Por email (ideal pro CRM, dispensa resolver o userId antes):
Por id (quando você já tem o userId Cativa em cache):
Resposta 200 OK (ilustrativa; schema completo na API Reference, tag Badge):
Para remover, use o DELETE no mesmo recurso por id:
No worker, as funções de atribuir e remover chamam esses endpoints direto:
A Cativa garante que atribuir o mesmo badge duas vezes é idempotente, o estado final é o mesmo (a segunda chamada responde sucesso sem duplicar). Mesma coisa pra remover badge que já não está atribuído. Isso simplifica retries no seu worker (ver Badges como permissão).

Esqueleto de worker pull-based

Com os endpoints de write disponíveis, o worker abaixo roda ponta a ponta. As funções assignBadge/removeBadge (definidas acima) já batem na API real.

Tratar conflitos

Erros comuns

Quando o seu worker é a única autoridade sobre um badge e ele não vê motivo no CRM, ele remove. Mas se o badge foi atribuído por outra fonte (compra paywall, importação manual), o sync apaga indevidamente.Solução: mantenha uma lista de “badges gerenciados pelo CRM” no seu worker. Só atribua e remova esses. Badges fora da lista são ignorados pelo diff.
Em syncs grandes (milhares de contatos), você pode bater rate limit no CRM ou na Cativa. Implemente:
  • Backoff exponencial em 429 (a Cativa respeita Retry-After).
  • Paginação no CRM (ex: getPage(100, after, ...) no HubSpot).
  • Paralelismo controlado (ex: p-limit(5) no Node).
Se você só popula crm_cativa_mapping via webhook, qualquer disparo perdido vira lacuna. Por isso recomendamos:
  • Um reconcile job semanal que pega todos os contatos do CRM com email e tenta dar match com os usuários conhecidos.
  • Logging do X-Cativa-Execution-Id em todo webhook recebido, se faltar, dá pra abrir ticket de investigação.
Acontece quando o usuário usa email pessoal pra comprar e email corporativo pra entrar na comunidade (ou vice-versa). Não tem solução automática, você precisa uma propriedade adicional no CRM (ex: community_email) e usar essa pro lookup em vez do email principal.

Próximos passos

Subscrever webhooks Cativa

Configure listeners para user_created e user_received_badge para manter sua tabela de mapeamento atualizada.

Liberar acesso via compra externa

O caso específico de “compra externa → badge” tem padrões e cuidados próprios.