Integração · primeiro passo

Configuração inicial do webhook

Prepare o endereço do seu sistema que receberá os eventos dos números conectados. Faça esta configuração uma vez para o parceiro, antes de cadastrar clientes, criar instâncias ou gerar sessões de conexão WhatsApp.

Antes do webhook: conclua o cadastro obrigatório

Na contratação, escolha o pacote e informe seu e-mail; cadastre o cartão na Stripe para iniciar o trial de três dias. Ao acessar o Portal, o proprietário deve completar seu cadastro antes de abrir os recursos operacionais, inclusive Endpoints. Pessoa física informa nome completo, celular e CPF. Pessoa jurídica informa razão social, CNPJ, nome completo do responsável e celular.

O sistema valida formato e dígitos verificadores de CPF/CNPJ, inclusive CNPJ alfanumérico. Não consulta a Receita Federal, não confirma titularidade, existência do documento ou situação ativa da empresa e não verifica o celular por SMS. O cadastro é declarado pelo proprietário e poderá ser conferido manualmente pela HookCloud. Um número matematicamente válido não constitui prova de identidade.

Enquanto essa etapa estiver pendente, as rotas operacionais retornam 409 partner_registration_required. Consulte get-partner-onboarding-status; registration_complete=false orienta o proprietário a concluir o cadastro no Portal. Uma Partner API Key não pode enviar ou alterar esse cadastro. Não confunda os dados do contratante com os clientes que ele atenderá: o endpoint upsert-partner-customer não conclui esta etapa.

O trial continua correndo durante o cadastro e a configuração. Após concluir os dados, siga o GET abaixo. Como tratamos os dados cadastrais · Referência oficial do formato CNPJ alfanumérico.

1. Prepare o destino antes de conectar clientes

O cadastro e a validação do endpoint fazem parte da preparação da integração. Antes de cadastrar clientes, criar instâncias ou gerar novas sessões, a HookCloud exige a URL primária habilitada e uma validação GET salva para ela. O acesso ao Portal permite preparar essa etapa após a confirmação da contratação e a conclusão do cadastro obrigatório do proprietário. Testar sem salvar, ter uma URL cadastrada ou apenas um token configurado não libera os novos cadastros.

  • URL pública com HTTPS e certificado válido, acessível na porta padrão 443.
  • Rota GET para verificar a URL e rota POST para receber eventos, no mesmo caminho.
  • Token de verificação idêntico no formulário do Portal ou chamada API e no servidor do seu sistema. Você pode aceitar o valor sugerido ou informar o segredo que já configurou.
  • Receptor POST com validação de assinatura, armazenamento durável e tratamento de repetição.

Use um endereço definitivo, sem redirecionamento para login, outra rota ou outro domínio. A verificação não segue redirects e não usa uma sessão do navegador. Não use localhost, IP privado ou credenciais embutidas na URL.

2. Configure o mesmo token no seu backend

No Portal, abra Endpoints → Cadastrar e validar webhook (ou Configurar / revalidar webhook) e copie o Meta Verify Token mostrado. O campo é editável: copie o valor sugerido para seu servidor ou informe o token que seu servidor já aceita. Configure esse token no backend do seu sistema; o exemplo usa META_VERIFY_TOKEN. Depois volte ao Portal para testar e aplicar a URL.

Se fizer o cadastro diretamente pela API, também pode escolher um segredo aleatório e enviar esse mesmo valor em meta_verify_token. Não misture os dois caminhos com tokens diferentes. Maiúsculas, minúsculas e espaços fazem diferença; não deixe o valor vazio.

CredencialPara que serve
meta_verify_tokenComparar o desafio GET e confirmar que você controla a rota. É o mesmo valor aceito pelo seu backend.
Partner API KeyAutenticar chamadas do seu backend para a API da HookCloud. Não é o token do desafio GET.
Meta Access TokenAutorizar chamadas do seu backend à Graph API para a instância.
webhook_secretValidar a assinatura dos eventos POST enviados pela HookCloud. Não substitui o token de verificação GET; é fornecido separadamente no provisionamento.

Evite registrar hub.verify_token em logs públicos ou colocar credenciais no frontend. O GET de consulta da configuração não revela o token; guarde-o de maneira segura durante o cadastro.

3. Implemente o GET de verificação

O exemplo abaixo cria um servidor Express mínimo, com somente a verificação GET. Se seu projeto já possui app e listen, reutilize o aplicativo existente e adicione apenas a rota, sem iniciar outro servidor. Ajuste o caminho se a URL escolhida for diferente. O exemplo é uma adaptação para a integração HookCloud do mecanismo documentado pela Meta, com validação de configuração e parâmetros; não é uma reprodução literal de todo o aplicativo de exemplo oficial.

Executar o exemplo em um projeto Node.js

  1. Em um projeto do seu backend, instale a dependência com npm install express.
  2. Salve o código abaixo em webhook.mjs.
  3. Crie um arquivo .env somente no servidor com META_VERIFY_TOKEN igual ao valor copiado do Portal. Não publique nem envie esse arquivo ao repositório.
  4. Com uma versão de Node.js que aceite --env-file, execute node --env-file=.env webhook.mjs. Se seu provedor já injeta as variáveis de ambiente, basta node webhook.mjs.
  5. Publique a rota por HTTPS no domínio escolhido. Rodar na porta local 3000 não torna a URL pública nem configura o certificado.
Arquivo .env — somente no seu servidordotenv
META_VERIFY_TOKEN=COLE_O_TOKEN_EXIBIDO_NO_PORTAL
PORT=3000
Node.js / Express — verificação GETjavascript
import express from 'express';

const app = express();
const verifyToken = process.env.META_VERIFY_TOKEN;

// Copie o Meta Verify Token exibido em Endpoints no Portal HookCloud.
// Configure esse valor somente no servidor do seu sistema.
if (!verifyToken) {
  throw new Error('Configure META_VERIFY_TOKEN antes de iniciar o servidor.');
}

app.get('/webhooks/whatsapp', (req, res) => {
  const mode = req.query['hub.mode'];
  const token = req.query['hub.verify_token'];
  const challenge = req.query['hub.challenge'];

  if (
    mode === 'subscribe' &&
    typeof token === 'string' &&
    token === verifyToken &&
    typeof challenge === 'string' &&
    challenge.length > 0
  ) {
    return res.status(200).type('text/plain').send(challenge);
  }

  return res.sendStatus(403);
});

app.listen(process.env.PORT || 3000);

O exemplo só aceita um valor textual por parâmetro, rejeita token ausente ou inválido e devolve o challenge como texto puro. Parâmetros duplicados, arrays ou objetos não devem ser aceitos como se fossem um único token. A configuração ausente no servidor também não deve validar uma solicitação.

Query parameterRecebidoO que seu servidor faz
hub.modesubscribeConfirma que é um desafio de assinatura.
hub.verify_tokenValor informado no cadastroCompara com o segredo configurado no backend.
hub.challenge1234 no teste inicial HookCloud; outros valores nos desafios da MetaRetorna exatamente esse texto no corpo da resposta HTTP 200, com Content-Type text/plain. Nunca fixe a resposta em 1234 no seu código.

4. Teste a sua URL

Com a rota publicada, faça uma chamada de teste. Substitua o domínio e o token fictício pelos seus valores. Este teste confirma o comportamento do GET; não registra o endpoint na HookCloud e não testa o processamento dos eventos POST.

Desafio GET ilustrativobash
curl --get 'https://api.seusistema.com/webhooks/whatsapp' \
  --data-urlencode 'hub.mode=subscribe' \
  --data-urlencode 'hub.verify_token=TOKEN_DE_VERIFICACAO_FICTICIO' \
  --data-urlencode 'hub.challenge=1234'

Resultado esperado: HTTP 200, Content-Type: text/plain e corpo 1234. Faça também uma chamada com token incorreto: ela deve ser recusada. Não transforme qualquer requisição em sucesso apenas para passar na validação.

5. Valide e salve o endpoint na HookCloud

No Portal, em Endpoints → Cadastrar e validar webhook (ou Configurar / revalidar webhook), informe a URL HTTPS e um motivo para a configuração (de 3 a 500 caracteres no formulário do Portal). Confirme que seu backend aceita o Meta Verify Token copiado da tela, use Testar GET e depois Validar e salvar. Você pode ajustar o token no formulário; ele precisa corresponder exatamente ao valor aceito pelo seu servidor. Depois confira o destino salvo.

Se preferir configurar pelo backend, use estas rotas da Partner API com sua autenticação e permissão webhook.write; alterações pelo login do Portal exigem perfil owner ou admin.

5.1. Testar sem salvar

validate-partner-webhook-endpoint envia um GET real ao seu endereço. Uma resposta bem-sucedida confirma o desafio, mas não salva a configuração.

Body POST — validarjson
{
  "route": "validate-partner-webhook-endpoint",
  "webhook_url": "https://api.seusistema.com/webhooks/whatsapp",
  "meta_verify_token": "TOKEN_DE_VERIFICACAO_FICTICIO"
}

Confira verification.challenge_verified=true. Se a API retornar um meta_verify_token, preserve esse valor para salvar. Neste passo a passo, informe o token explicitamente para que ele corresponda ao já configurado no seu servidor.

5.2. Salvar a configuração validada

update-partner-webhook-endpoint valida novamente o GET e salva a configuração. O campo reason registra uma justificativa de 3 a 1000 caracteres.

Body POST — salvarjson
{
  "route": "update-partner-webhook-endpoint",
  "webhook_url": "https://api.seusistema.com/webhooks/whatsapp",
  "meta_verify_token": "TOKEN_DE_VERIFICACAO_FICTICIO",
  "reason": "Configuração inicial do webhook do sistema"
}

As duas chamadas usam https://api.hookcloud.app/functions/v1/swift-worker, cabeçalhos apikey: SUA_CHAVE_PUBLICA_DO_AMBIENTE, Authorization: Bearer SUA_PARTNER_API_KEY e Content-Type: application/json. A chave pública do ambiente (Publishable Key) e a Partner API Key são valores diferentes: copie cada um do ambiente correto, sem trocar seus cabeçalhos. O body acima contém o seletor route. Confira os exemplos completos na referência de endpoints.

5.3. Confirmar a liberação dos cadastros

Consulte get-partner-onboarding-status com permissão webhook.read. A resposta informa checkout_confirmed, registration_required, registration_complete, webhook_validated, can_create_customer e can_create_instance. Somente habilite a criação quando a permissão correspondente for true. Em falha de leitura, mantenha a criação bloqueada e permita repetir a consulta. Contas já habilitadas são reconhecidas pelo servidor; não peça outro cartão por suposição.

Uma tentativa prematura retorna 409 partner_webhook_verification_required. Prepare GET e POST, valide e salve o endpoint, e consulte novamente. O código deve ecoar qualquer desafio válido, embora a HookCloud use 1234 neste teste.

5.4. Conferir o destino persistido

Use get-partner-webhook-endpoint, com permissão webhook.read. Confira endpoint.url, enabled, is_primary e o estado da migração. endpoint=null significa que o destino ainda não foi cadastrado. meta_verify_token_configured=true confirma que existe um token salvo; não revela seu valor nem prova o processamento de POSTs.

Se já houver números conectados, mudar URL ou token pode iniciar uma migração dos callbacks. HTTP 202 e migration_status=pending não significam que todos os números já trocaram de destino. Acompanhe get-partner-webhook-migration antes de desligar a URL anterior. Não envie várias trocas em paralelo.

6. Prepare também o POST de eventos

A mesma URL precisa receber os POSTs. O GET valida o endereço; o POST traz mensagens, status e mudanças operacionais. Passar no desafio não garante que seu sistema esteja processando ou armazenando os eventos.

  1. Capture o corpo bruto antes de transformar o JSON, para validar a assinatura correta da origem.
  2. Confirme a autenticidade pelo mecanismo adequado à origem. Eventos HookCloud usam o segredo HMAC fornecido separadamente e timestamp. Para eventos diretos da Meta, combine com a HookCloud o mecanismo de autenticação disponível para sua integração antes de aceitar o conteúdo como confiável.
  3. Persista ou enfileire o evento de forma durável antes de responder HTTP 2xx.
  4. Processe o conteúdo com deduplicação e retentativas controladas, sem pressupor ordem ou entrega única.
  5. Associe o evento ao cliente correto. Para mensagens Meta, use o metadata.phone_number_id; eventos de WABA podem não ter esse campo. Eventos HookCloud usam os identificadores descritos no respectivo contrato.

Itere sobre todos os itens de entry[] e changes[] e sobre as listas de mensagens/status presentes; não processe apenas a primeira posição. Não use BSUID ou o telefone do destinatário como se fosse o ID do número comercial.

Ver contratos de POST, assinaturas e eventos →

Consulte também o catálogo de campos Meta: finalidade, payload, assinatura registrada no app e caminho de entrega de cada campo. A assinatura no app não confirma encaminhamento bruto ao seu endpoint nem habilitação do recurso.

Na configuração dos eventos HookCloud, o endpoint deve estar habilitado e receber os nomes desejados em subscribed_events ou *. Isso é diferente dos campos assinados no app da Meta. Não reconfigure o app Meta da HookCloud para cada cliente final.

7. Inicie as conexões e confirme a operação

Com o endpoint preparado e salvo, siga o Quickstart: cadastre o cliente, crie a instância, abra o link Connect e consulte o estado confirmado. A HookCloud aplica o destino à conexão autorizada; seu sistema usa os IDs retornados para relacionar cada evento ao cliente correto.

  • GET válido retorna o challenge e token incorreto é recusado.
  • URL/token foram salvos; não apenas testados.
  • Endpoint aparece habilitado na consulta e nenhuma migração está pendente de conclusão.
  • POST tem assinatura validada e evento persistido antes do 2xx.
  • O cliente concluiu a conexão e a saúde da conexão foi conferida.
  • Um evento real foi recebido e associado ao número/cliente correto.

Mensagens e status operacionais chegam ao seu receptor. Para alimentar os indicadores da HookCloud, seu backend pode reportar os status normalizados conforme o guia de Saúde de Entregas. A HookCloud não assume o processamento interno do seu sistema.

Quando a validação falhar

SintomaO que conferir
403 no desafioMesmo token no backend e no cadastro; hub.mode=subscribe; parâmetros únicos em formato texto.
200, mas validação recusadaO corpo deve ser somente o challenge. Remova JSON, HTML, aspas e conteúdo adicional.
404 ou 405O caminho publicado deve corresponder à URL cadastrada e aceitar GET, além de POST.
301, 302 ou página de loginUse a URL HTTPS final, sem redirect e sem autenticação por sessão. Preserve a verificação própria do token.
Timeout ou erro de certificadoCertificado válido, DNS público, porta 443 e resposta em até 10 segundos. Revise firewall/proxy sem desabilitar segurança globalmente.
Teste passou, mas endpoint ausenteA validação não salva. Execute update-partner-webhook-endpoint ou conclua o salvamento no Portal.
GET passou, mas eventos não aparecemConfira POST, assinatura, persistência, seleção de eventos, conexão e eventual migração pendente. Não use o sucesso do GET como prova de entrega.

Ao pedir suporte, informe URL sem credenciais, horário, status HTTP, request_id e, se houver, ID da migração. Não compartilhe tokens, segredo HMAC ou conteúdo pessoal das mensagens.

Produção e homologação

A base da API usada nos exemplos desta publicação é https://api.hookcloud.app. Escolha o ambiente correto no Portal e utilize a chave pública e a Partner API Key emitidas para ele. Mantenha URLs e tokens separados para os seus receptores de teste e produção. Stage e produção não compartilham o cadastro do endpoint: configurar um ambiente não configura automaticamente o outro.

Referências oficiais e próximos passos

O mecanismo de verificação segue a documentação da Meta; o cadastro do endpoint global, as permissões e a migração seguem os contratos da HookCloud.

Webhooks e eventos POST · Quickstart · Chamadas para configurar endpoints