Arquitetura recomendada
No modo webhook próprio, o HookCloud Flow configura e verifica a rota; ele não se torna o CRM nem o motor de automação.
Meta WhatsApp Cloud API
↓
Webhook HTTPS do seu CRM, n8n, Make ou backend
↓
Fila, automação, leads, funis e atendimento do seu sistema
Seu backend
↓
Graph API oficial da Meta
↓
Envio pelo Phone Number ID conectadoHookCloud Flow
Onboarding oficial, credenciais, callback, readback, status, qualidade, username comercial e observabilidade.
Seu sistema
Mensagens, contatos, mídia, funis, tags, variáveis, regras, armazenamento e respostas.
Isolamento
Cada evento deve ser associado ao Phone Number ID, WABA, mensagem e identidade corretos.
Os POSTs chegam diretamente da Meta
Quando o card da conexão indica rota própria confirmada — normalmente custom_verified — os campos operacionais compatíveis com callback alternativo, como messages, são enviados pela Meta ao endpoint configurado para aquele número.
- A HookCloud valida a URL e o GET de verificação.
- Aplica o callback correspondente à conexão.
- Relê a configuração do Phone Number ID.
- Somente depois registra a rota como confirmada.
- A Meta passa a entregar os POSTs ao endpoint do assinante.
A HookCloud não reescreve, não enriquece e não retransmite o conteúdo normal das conversas nesse modo. Alguns eventos administrativos que não aceitam callback alternativo podem continuar chegando ao callback do aplicativo HookCloud para atualizar qualidade, templates, segurança e estado da conta.
metadata.phone_number_id para identificar o número exato. O WABA ID, sozinho, não distingue dois números pertencentes à mesma conta do WhatsApp Business.Corpo bruto e assinatura X-Hub-Signature-256
Como a entrega operacional é direta da Meta para o endpoint do assinante, a HookCloud não altera o corpo nem substitui os headers. O sistema de destino deve capturar o corpo bruto antes de fazer o parse JSON caso pretenda validar uma assinatura criptográfica.
| Item | Comportamento atual |
|---|---|
| Corpo do POST | Chega diretamente da Meta; a HookCloud não transforma o payload. |
X-Hub-Signature-256 | Quando enviado pela Meta, chega no request original. |
| Verify token | Protege o GET de verificação. Não é assinatura criptográfica do POST. |
| App Secret | Não é compartilhado com assinantes. |
| Assinatura própria da HookCloud | Não existe no modo direto, porque a HookCloud não está no caminho do POST. |
X-Hub-Signature-256 exige o App Secret responsável pela integração. Como esse segredo não é fornecido, o modo direto atual não atende a um requisito que exija validação HMAC independente pelo assinante. Uma eventual retransmissão assinada pela HookCloud seria outro produto, com fila, segredo individual, logs e política própria de tratamento de dados.Timeout, reentregas e idempotência
A política “3 tentativas, 5 segundos e timeout de 10 segundos” pertence somente à configuração inicial do callback. Depois que a rota está ativa, a Meta controla o timeout e as reentregas dos webhooks.
- Responda com HTTP
2xxo mais rápido possível. - Grave ou enfileire o evento antes de executar automações demoradas.
- Não presuma que um evento chegará uma única vez.
- Não dependa de um intervalo fixo entre reentregas.
- Use
messages[].idcomo chave de idempotência da mensagem. - Para status, combine o ID da mensagem, o tipo do status e o timestamp quando necessário.
- Mantenha logs e replay no seu próprio sistema; a HookCloud não oferece replay do conteúdo no modo direto.
const messageId = payload.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.id;
if (messageId && await alreadyProcessed(messageId)) {
return res.sendStatus(200);
}
await persistOrQueue(payload);
res.sendStatus(200);Click-to-WhatsApp e objeto referral
Quando a própria Meta associa a primeira mensagem a um anúncio ou ponto de entrada compatível, o objeto referral acompanha a mensagem. A HookCloud não remove esses campos no webhook próprio.
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WABA_ID_EXEMPLO",
"changes": [
{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "5511999999999",
"phone_number_id": "PHONE_NUMBER_ID_EXEMPLO"
},
"contacts": [
{
"profile": { "name": "Cliente Exemplo" },
"wa_id": "5511888888888"
}
],
"messages": [
{
"from": "5511888888888",
"id": "wamid.HBgMEXEMPLO",
"timestamp": "1787000000",
"type": "text",
"text": { "body": "Olá, quero saber mais." },
"referral": {
"source_url": "https://fb.me/EXEMPLO",
"source_id": "120200000000000000",
"source_type": "ad",
"headline": "Conheça nossa solução",
"body": "Fale com nossa equipe pelo WhatsApp",
"media_type": "image",
"ctwa_clid": "CLICK_ID_SANITIZADO"
}
}
]
}
}
]
}
]
}Os campos disponíveis variam conforme o tipo do anúncio, a mensagem e a versão da Graph API. Armazene o objeto recebido sem depender de todos os atributos e associe o referral ao lead e à primeira mensagem.
BSUID, username e telefone ausente
A integração deve tratar o telefone como opcional. Quando a Meta disponibiliza BSUID, a identidade técnica pode continuar presente mesmo se wa_id, from ou recipient_id vierem vazios ou ausentes.
Exemplo sanitizado de mensagem recebida sem telefone
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WABA_ID_EXEMPLO",
"changes": [
{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "5511999999999",
"phone_number_id": "PHONE_NUMBER_ID_EXEMPLO"
},
"contacts": [
{
"profile": {
"name": "Cliente Exemplo",
"username": "cliente.exemplo"
},
"user_id": "BR.13491208655302741918",
"parent_user_id": "BR.ENT.11815799212886844830",
"wa_id": ""
}
],
"messages": [
{
"from": "",
"from_user_id": "BR.13491208655302741918",
"from_parent_user_id": "BR.ENT.11815799212886844830",
"id": "wamid.HBgMQlIuEXEMPLO",
"timestamp": "1787000000",
"type": "text",
"text": { "body": "Olá." }
}
]
}
}
]
}
]
}Exemplo sanitizado de status para destinatário BSUID
{
"entry": [
{
"id": "WABA_ID_EXEMPLO",
"changes": [
{
"field": "messages",
"value": {
"metadata": {
"phone_number_id": "PHONE_NUMBER_ID_EXEMPLO"
},
"statuses": [
{
"id": "wamid.HBgMQlIuEXEMPLO",
"status": "delivered",
"timestamp": "1787000012",
"recipient_id": "",
"recipient_user_id": "BR.13491208655302741918",
"recipient_parent_user_id": "BR.ENT.11815799212886844830"
}
]
}
}
]
}
]
}| Campo | Uso recomendado |
|---|---|
contacts[].user_id | BSUID do contato. Guarde no contexto do Business Portfolio. |
messages[].from_user_id | BSUID do remetente da mensagem. |
statuses[].recipient_user_id | BSUID do destinatário associado ao status de envio. |
parent_user_id / from_parent_user_id / recipient_parent_user_id | Identidade pai, quando aplicável ao relacionamento empresarial. |
wa_id / from / recipient_id | Telefone, quando fornecido; não torne obrigatório. |
profile.username | Exibição. Não use como chave primária nem como destino de API. |
Os exemplos são sanitizados. Durante rollout e versões diferentes, campos opcionais podem ser omitidos em vez de enviados como string vazia.
Ciclo de vida do Meta Access Token
O token é obtido durante o Embedded Signup, armazenado de forma protegida e revelado somente a papéis autorizados. A HookCloud não define uma validade universal para ele e não promete renovação silenciosa.
| Etapa | Comportamento |
|---|---|
| Armazenamento | Protegido no backend; não deve ser salvo em frontend, prints ou workflows exportados. |
| Auditoria | Verifica validade, App ID, tipo do token, escopos, acesso à WABA e datas de expiração quando fornecidas. |
| Messaging ausente | A conexão não deve operar normalmente. |
| Management ausente | Pode existir modo limitado, com restrições para templates e metadados. |
| Revogação ou expiração | O painel solicita reautorização. |
| Recuperação | Uma auditoria posterior válida pode restaurar o estado local da credencial. |
| Rotação | O caminho normal é realizar nova autorização pelo Embedded Signup. |
Enviar mensagens pelo CRM: telefone ou BSUID
O endpoint continua sendo /PHONE_NUMBER_ID/messages. O campo do destinatário muda conforme o identificador disponível.
Quando você possui o telefone
curl -X POST \
"https://graph.facebook.com/vXX.X/PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer META_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "5511888888888",
"type": "text",
"text": { "body": "Olá!" }
}'Quando você possui somente o BSUID
curl -X POST \
"https://graph.facebook.com/vXX.X/PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer META_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient": "BR.13491208655302741918",
"type": "text",
"text": { "body": "Olá!" }
}'user_id não é o nome do campo outboundcontacts[].user_id ou messages[].from_user_id. Para responder por BSUID, use esse valor no campo recipient. Para responder por telefone, use to. Envie somente um dos dois.- Não use o username como destinatário técnico.
- Escolha o Phone Number ID que pertence ao mesmo Business Portfolio do BSUID.
- Guarde
messages[].idestatuses[].recipient_user_idpara reconciliar status. - Use a versão atual da Graph API e respeite janela de atendimento, templates e políticas da Meta.
Isolamento rigoroso entre números e leads
| Informação | Chave recomendada |
|---|---|
| Número que recebeu o evento | metadata.phone_number_id |
| Conta do WhatsApp Business | entry[].id — WABA ID |
| Business Portfolio | Business ID do card; necessário para o namespace do BSUID. |
| Conexão no suporte HookCloud | Connection ID do card |
| Mensagem | messages[].id |
| Lead por BSUID | contacts[].user_id / messages[].from_user_id, sempre junto do Business ID |
| Status por BSUID | statuses[].recipient_user_id |
| Telefone, quando presente | wa_id / from / recipient_id, normalizado em E.164 |
| Destino outbound por telefone | to |
| Destino outbound por BSUID | recipient |
| Anúncio | referral.source_id e referral.ctwa_clid |
- Não roteie apenas pelo WABA ID.
- Não use
display_phone_numbercomo chave primária. - Não use BSUID fora do Business Portfolio que o gerou.
- Não crie contato novo somente porque o telefone desapareceu ou o username mudou.
- Associe o referral à primeira mensagem e ao lead.
API pública e HookCloud Partner
O Flow atual não oferece contrato público e versionado para iniciar o Embedded Signup fora do painel, listar todas as conexões ou revelar credenciais por uma API externa.
Depois da conexão, o CRM utiliza diretamente a Graph API oficial com as credenciais do número. O HookCloud Partner, destinado a incorporar a conexão em plataformas SaaS, permanece planejado, mas não possui data pública ou acesso antecipado garantido.
Checklist para um piloto controlado
- Concluir o Embedded Signup com a empresa e o número corretos.
- Confirmar a rota como
custom_verified. - Receber mensagem de texto comum.
- Receber imagem ou documento e buscar a mídia conforme a API da Meta.
- Receber status de envio, entrega e leitura.
- Enviar mensagem pelo CRM com o Phone Number ID.
- Reentregar um evento de teste e confirmar idempotência.
- Validar uma mensagem Click-to-WhatsApp com
referral. - Validar BSUID e telefone ausente quando o recurso estiver disponível.
- Confirmar que nenhum número de outra conexão entra no mesmo fluxo.
Perguntas rápidas
O HookCloud armazena as mensagens do webhook próprio?
Posso adicionar Bearer Token ao POST enviado pela Meta?
O Flow possui replay de mensagens?
O Flow executa tags, variáveis ou etapas de funil?
Devo substituir to por recipient em todos os envios?
to quando o destino é o telefone em E.164. Use recipient quando o destino é o BSUID recebido em user_id ou from_user_id. Não envie os dois no mesmo pedido.Envie o e-mail do owner, Workspace ID, Connection ID, Phone Number ID, WABA ID, horário aproximado e um payload sanitizado para suporte@hookcloud.app. Nunca envie o token completo nem dados pessoais desnecessários.
