Skip to main content
Esta é a página de referência única para integrar webhooks da Cativa. Um webhook é um POST que a Cativa envia para uma URL sua toda vez que um evento acontece no tenant (um usuário se cadastra, um pagamento é confirmado, um post é publicado). Em vez de você ficar consultando a API de tempos em tempos, a Cativa avisa você no instante do evento. Aqui você encontra: como cadastrar o listener, a lista de eventos, como verificar a assinatura, e como lidar com retries e duplicatas.
Um evento por listener. Cada cadastro escuta um nome de evento (ex: user_created). Para escutar vários eventos, crie vários listeners, apontando todos para a mesma URL se quiser. Cada listener tem o seu próprio secret.

Duas formas de cadastrar

Pelo Console

Interface visual, sem código. Ideal para configurar rápido e revelar o secret na tela.

Pela API de gestão

Programático e versionável. Ideal para provisionar listeners em escala ou via infraestrutura como código.

Cadastrar pelo Console

No painel Cativa, abra Console > Webhooks e clique em Adicionar listener. O fluxo pede 3 informações:
  1. URL, o endpoint público do seu app que vai receber o POST (ex: https://meuapp.com/webhooks/cativa).
  2. Evento, o nome do evento que você quer escutar (snake_case, ex: user_received_badge).
  3. Secret, gerado automaticamente. Após criar o listener, abra-o e clique em Reveal secret para copiar o valor (formato whsec_ + 64 caracteres hex). O secret só pode ser visualizado pelo admin do tenant. Guarde com segurança no seu cofre de credenciais.

Cadastrar pela API de gestão

Os endpoints de gestão de webhook ficam sob o recurso admin/integration/{customerId}/webhooks. O {customerId} é o ID do seu tenant.
  • Base URL: https://apis.cativalab.digital/tenant/api/v2
  • Autenticação: header Authorization: Bearer YOUR_API_KEY (a API key começa com cativa_).
1

Crie a assinatura (e guarde o secret)

Faça um POST informando o EventName e a Url. A resposta traz o Secret uma única vez. Copie e guarde antes de fechar a conexão, porque depois disso ele não é retornável pela API (só revelável pelo Console).
Resposta:
Se você omitir GroupId, o listener dispara para o evento no tenant inteiro. Informe um GroupId para escutar apenas um grupo específico.
2

Receba o POST no seu endpoint

Todo disparo chega como POST com Content-Type: application/json e os headers X-Cativa-Signature, X-Cativa-Execution-Id, X-Cativa-Automation-Id e X-Cativa-Idempotency-Key (detalhados em Headers de cada entrega).
3

Verifique a assinatura HMAC

Antes de confiar no payload, recompute o HMAC-SHA256 com o seu Secret e compare em tempo constante com o header X-Cativa-Signature. Rejeite disparos com timestamp fora da janela de 5 minutos. Código pronto em Node e Python na seção Verificando a assinatura HMAC.
4

Responda 2xx rápido

Responda 200 (qualquer 2xx serve) assim que validar a assinatura. Não faça o trabalho pesado dentro do request. Enfileire o processamento e responda rápido, senão o disparo estoura timeout e entra em retry desnecessário.
5

Deduplique reentregas

A entrega é at-least-once. Use o header X-Cativa-Idempotency-Key (ou X-Cativa-Execution-Id) para descartar duplicatas. Detalhes e código em Idempotência.
6

Deixe a Cativa re-tentar as falhas

Se você responder erro 5xx/408/429 ou cair a conexão, a Cativa re-tenta sozinha na curva de backoff. Você não precisa fazer nada além de voltar a responder 2xx. Detalhes em Retries e falhas permanentes.

Endpoints de gestão

Todos exigem Authorization: Bearer YOUR_API_KEY e usam a base https://apis.cativalab.digital/tenant/api/v2.
Desative temporariamente ou troque a URL sem recriar o listener (o secret é preservado):
Logs de uma assinatura específica:
Todas as execuções do tenant, filtrando por falhas de um evento nas últimas 24h:

Eventos disponíveis

Use exatamente esses nomes em snake_case no campo EventName ao cadastrar, é como a Cativa faz o match.

Verificando a assinatura HMAC

A assinatura é o que prova que o disparo veio mesmo da Cativa (e não de alguém que descobriu sua URL). Sempre verifique antes de processar. Cada disparo chega com o header:
  • t, timestamp Unix (em segundos) do momento do disparo.
  • v1, HMAC-SHA256 (hex, minúsculo) sobre a string "<t>.<rawBody>", usando o secret do listener como chave.
A verificação tem três passos:
  1. Parse do header em t e v1.
  2. Anti-replay, rejeite o request se |now - t| > 300 segundos (5 minutos é o padrão de mercado). Isso barra o replay de um request antigo capturado.
  3. Recomputar o HMAC e comparar em tempo constante (timingSafeEqual / hmac.compare_digest), nunca com ==.
Compute o HMAC sobre o body bruto (os bytes exatos recebidos), nunca sobre o JSON re-serializado. Re-serializar muda espaços e ordem de chaves e invalida a assinatura. Em Express use express.raw; em Flask use request.get_data().

Headers de cada entrega

Retries e falhas permanentes

Se seu endpoint não responder com 2xx, a Cativa re-tenta de acordo com a curva:
São 6 retries após a tentativa inicial (7 entregas no total), cobrindo cerca de 33 horas. Todos os retries da mesma entrega carregam o mesmo X-Cativa-Idempotency-Key e X-Cativa-Execution-Id. A Cativa respeita o header Retry-After que você retornar (limitado ao máximo da próxima janela do backoff).

Tabela de comportamento por status

A lógica: status na faixa 4xx (exceto 408 e 429) significa “o request está errado e re-tentar não vai ajudar”, tipicamente bug do cliente, URL desativada ou auth incorreta. Status 5xx, 408, 429 e erros de transporte significam “tente de novo mais tarde”.

Quando todas as tentativas falham

Se a 7ª tentativa também falhar, a entrega vira dead-letter e fica registrada nos logs (consultáveis por GET .../webhooks/{webhookId}/logs e GET .../executions). Monitore o uptime do seu endpoint pelo seu lado e, se desconfiar de eventos perdidos, cheque os logs ou abra ticket em dev@cativa.digital.

Idempotência

A entrega é at-least-once. O mesmo evento pode chegar mais de uma vez (retries após timeout, perda de conexão na hora de responder). Você precisa detectar duplicatas no seu lado. A chave canônica é o header X-Cativa-Idempotency-Key: é determinístico por entrega e se mantém igual em todos os retries (o X-Cativa-Execution-Id também serve). Salve esse ID na mesma transação da lógica de negócio:
Isso garante que ou tudo aconteceu, ou nada aconteceu, sem chance de processar duas vezes.

Boas práticas

Valide a assinatura, enfileire o payload (fila, tabela de outbox, tópico) e responda 2xx na hora. Processamento pesado dentro do request estoura timeout e gera retries desnecessários.
Nunca aja sobre um payload não verificado. Sua URL pode vazar (logs, proxies) e qualquer um pode enviar POST para ela. O HMAC é o que separa o disparo legítimo do forjado.
Grave o X-Cativa-Idempotency-Key e descarte reentregas. Assuma que todo evento pode chegar duas vezes.
Chamadas externas dentro do handler (CRM, email) devem ter timeout curto. Se um provedor terceiro travar, você trava a resposta e vira retry.
Não reuse um secret entre ambientes. Um listener de staging e um de produção têm secrets distintos por design. Trate-os como credenciais separadas.

Eventos relacionados

Webhooks (visão geral)

Por que webhooks, garantias de entrega e o formato dos payloads.

user_received_badge

Página de referência completa de um evento, payload, headers e receiver de exemplo.