{"id":504,"date":"2026-10-28T16:04:32","date_gmt":"2026-10-28T16:04:32","guid":{"rendered":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/"},"modified":"2026-10-28T16:04:43","modified_gmt":"2026-10-28T16:04:43","slug":"assinatura-webhook-whatsapp","status":"publish","type":"post","link":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/","title":{"rendered":"Como validar a assinatura do webhook do WhatsApp (X-Hub-Signature-256)"},"content":{"rendered":"\n<p><em>Atualizado em 28\/10\/2026<\/em><\/p>\n\n\n\n<p>Para validar a assinatura do webhook do WhatsApp, calcule um HMAC SHA-256 do corpo da requisi\u00e7\u00e3o usando o <strong>app secret<\/strong> do seu app da Meta como chave e compare o resultado com o valor do cabe\u00e7alho <code>X-Hub-Signature-256<\/code>, que vem no formato <code>sha256=&lt;hash&gt;<\/code>. Se os dois forem iguais, o evento veio da Meta e n\u00e3o foi alterado no caminho. O detalhe que mais derruba a valida\u00e7\u00e3o \u00e9 calcular o hash sobre o JSON j\u00e1 interpretado pelo framework, e n\u00e3o sobre os bytes exatos que chegaram.<\/p>\n\n\n\n<p>Este guia mostra o passo a passo, c\u00f3digo pronto para Node.js (Express), Python (FastAPI e Flask) e PHP, e os erros mais comuns. Se voc\u00ea ainda est\u00e1 montando o endpoint, comece por <a href=\"https:\/\/vectalk.com.br\/blog\/webhook-whatsapp-api\/\">webhook da API do WhatsApp<\/a> e volte aqui para a parte de seguran\u00e7a.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Por que validar a assinatura<\/h2>\n\n\n\n<p>A URL do seu webhook \u00e9 p\u00fablica. Qualquer pessoa que descobrir o endere\u00e7o pode mandar um <code>POST<\/code> com um JSON no formato da Meta, simulando uma mensagem de cliente, um pagamento confirmado por bot\u00e3o ou um status <code>delivered<\/code> que nunca aconteceu. Sem valida\u00e7\u00e3o, seu sistema aceita tudo.<\/p>\n\n\n\n<p>A <a href=\"https:\/\/developers.facebook.com\/docs\/graph-api\/webhooks\/getting-started\" target=\"_blank\" rel=\"noreferrer noopener\">documenta\u00e7\u00e3o de webhooks da Graph API<\/a> diz que a Meta assina todas as notifica\u00e7\u00f5es com SHA-256 e envia a assinatura no cabe\u00e7alho <code>X-Hub-Signature-256<\/code>, precedida de <code>sha256=<\/code>. A valida\u00e7\u00e3o n\u00e3o \u00e9 obrigat\u00f3ria, mas a pr\u00f3pria Meta recomenda fazer. Na pr\u00e1tica, \u00e9 o que separa um webhook confi\u00e1vel de um endpoint aberto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">As duas requisi\u00e7\u00f5es que o seu endpoint recebe<\/h2>\n\n\n\n<p>O mesmo endere\u00e7o recebe dois tipos de chamada, e cada uma tem sua checagem:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Requisi\u00e7\u00e3o<\/th><th>Quando acontece<\/th><th>O que validar<\/th><th>Resposta<\/th><\/tr><\/thead><tbody><tr><td><code>GET<\/code> de verifica\u00e7\u00e3o<\/td><td>Ao configurar ou alterar a URL no painel do app<\/td><td><code>hub.mode<\/code> igual a <code>subscribe<\/code> e <code>hub.verify_token<\/code> igual ao token que voc\u00ea definiu<\/td><td><code>200<\/code> com o valor de <code>hub.challenge<\/code><\/td><\/tr><tr><td><code>POST<\/code> de evento<\/td><td>Cada mensagem, status ou mudan\u00e7a na conta<\/td><td><code>X-Hub-Signature-256<\/code> contra o HMAC do corpo bruto<\/td><td><code>200<\/code> r\u00e1pido; processamento em fila<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Segundo a p\u00e1gina <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/create-webhook-endpoint\" target=\"_blank\" rel=\"noreferrer noopener\">Create a webhook endpoint<\/a>, se a verifica\u00e7\u00e3o for v\u00e1lida voc\u00ea responde <code>200<\/code> com o <code>hub.challenge<\/code>; se n\u00e3o for, responde qualquer coisa diferente de <code>200<\/code> (um 403, por exemplo). A mesma p\u00e1gina exige certificado TLS v\u00e1lido no endpoint: certificados autoassinados n\u00e3o s\u00e3o aceitos.<\/p>\n\n\n\n<p>Note que o <em>verify token<\/em> e o <em>app secret<\/em> s\u00e3o coisas diferentes. O verify token \u00e9 uma string que voc\u00ea inventa e cadastra no painel; ele s\u00f3 serve para o <code>GET<\/code>. O app secret \u00e9 gerado pela Meta e fica em <strong>Configura\u00e7\u00f5es do app &gt; B\u00e1sico<\/strong>; \u00e9 ele que assina os <code>POST<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Passo a passo da valida\u00e7\u00e3o<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Leia o corpo da requisi\u00e7\u00e3o <strong>como bytes<\/strong>, antes de qualquer parser de JSON.<\/li>\n\n\n<li>Calcule <code>HMAC-SHA256(chave = app secret, mensagem = corpo bruto)<\/code> e converta para hexadecimal.<\/li>\n\n\n<li>Monte <code>sha256=<\/code> + hash e compare com o cabe\u00e7alho <code>X-Hub-Signature-256<\/code> usando compara\u00e7\u00e3o em tempo constante.<\/li>\n\n\n<li>Se n\u00e3o bater, responda 401 ou 403 e descarte o evento.<\/li>\n\n\n<li>Se bater, fa\u00e7a o parse do JSON, coloque o evento numa fila e responda <code>200<\/code>.<\/li>\n\n<\/ol>\n\n\n\n<p>A compara\u00e7\u00e3o em tempo constante (<code>crypto.timingSafeEqual<\/code>, <code>hmac.compare_digest<\/code>, <code>hash_equals<\/code>) evita que um atacante descubra o hash byte a byte medindo o tempo de resposta.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Exemplo em Node.js com Express<\/h2>\n\n\n\n<p>O ponto central \u00e9 usar <code>express.raw()<\/code> na rota do webhook, para que <code>req.body<\/code> seja um <code>Buffer<\/code> com os bytes originais:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-js\">import express from 'express';\nimport crypto from 'node:crypto';\n\nconst app = express();\nconst APP_SECRET = process.env.META_APP_SECRET;\nconst VERIFY_TOKEN = process.env.WEBHOOK_VERIFY_TOKEN;\n\n\/\/ GET de verifica\u00e7\u00e3o\napp.get('\/webhook', (req, res) =&gt; {\n  const mode = req.query['hub.mode'];\n  const token = req.query['hub.verify_token'];\n  const challenge = req.query['hub.challenge'];\n  if (mode === 'subscribe' &amp;&amp; token === VERIFY_TOKEN) {\n    return res.status(200).send(challenge);\n  }\n  return res.sendStatus(403);\n});\n\n\/\/ POST de eventos: corpo bruto s\u00f3 nesta rota\napp.post('\/webhook', express.raw({ type: 'application\/json' }), (req, res) =&gt; {\n  const recebida = req.get('X-Hub-Signature-256') || '';\n  const esperada = 'sha256=' + crypto\n    .createHmac('sha256', APP_SECRET)\n    .update(req.body)\n    .digest('hex');\n\n  const a = Buffer.from(recebida);\n  const b = Buffer.from(esperada);\n  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {\n    return res.sendStatus(401);\n  }\n\n  const evento = JSON.parse(req.body.toString('utf8'));\n  res.sendStatus(200);\n  filaDeEventos.push(evento); \/\/ processe fora do ciclo da requisi\u00e7\u00e3o\n});\n\napp.use(express.json()); \/\/ demais rotas podem usar JSON normalmente\napp.listen(3000);<\/code><\/pre>\n\n\n\n<p>Se a aplica\u00e7\u00e3o j\u00e1 tem <code>app.use(express.json())<\/code> declarado antes dessa rota, o corpo chega interpretado e o hash n\u00e3o bate. Duas sa\u00eddas: declarar a rota do webhook antes do middleware global, ou guardar os bytes no pr\u00f3prio <code>express.json<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-js\">app.use(express.json({\n  verify: (req, _res, buf) =&gt; { req.rawBody = buf; },\n}));\n\/\/ depois, use req.rawBody no createHmac<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Exemplo em Python com FastAPI<\/h2>\n\n\n\n<p>No FastAPI, <code>await request.body()<\/code> devolve os bytes exatos. N\u00e3o use o modelo Pydantic do corpo para assinar:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-python\">import hashlib\nimport hmac\nimport json\nimport os\n\nfrom fastapi import FastAPI, HTTPException, Request, Response\n\napp = FastAPI()\nAPP_SECRET = os.environ[\"META_APP_SECRET\"].encode()\nVERIFY_TOKEN = os.environ[\"WEBHOOK_VERIFY_TOKEN\"]\n\n\n@app.get(\"\/webhook\")\nasync def verificar(request: Request):\n    p = request.query_params\n    if p.get(\"hub.mode\") == \"subscribe\" and p.get(\"hub.verify_token\") == VERIFY_TOKEN:\n        return Response(content=p.get(\"hub.challenge\", \"\"), media_type=\"text\/plain\")\n    raise HTTPException(status_code=403)\n\n\n@app.post(\"\/webhook\")\nasync def receber(request: Request):\n    corpo = await request.body()\n    recebida = request.headers.get(\"x-hub-signature-256\", \"\")\n    esperada = \"sha256=\" + hmac.new(APP_SECRET, corpo, hashlib.sha256).hexdigest()\n    if not hmac.compare_digest(recebida, esperada):\n        raise HTTPException(status_code=401)\n\n    evento = json.loads(corpo)\n    # enfileire o evento e responda r\u00e1pido\n    return {\"ok\": True}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Exemplo em Python com Flask<\/h2>\n\n\n\n<p>No Flask, use <code>request.get_data()<\/code>, que devolve o corpo bruto:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-python\">import hashlib\nimport hmac\nimport os\n\nfrom flask import Flask, abort, request\n\napp = Flask(__name__)\nAPP_SECRET = os.environ[\"META_APP_SECRET\"].encode()\n\n\n@app.post(\"\/webhook\")\ndef receber():\n    corpo = request.get_data()\n    recebida = request.headers.get(\"X-Hub-Signature-256\", \"\")\n    esperada = \"sha256=\" + hmac.new(APP_SECRET, corpo, hashlib.sha256).hexdigest()\n    if not hmac.compare_digest(recebida, esperada):\n        abort(401)\n    evento = request.get_json()\n    return \"\", 200<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Exemplo em PHP<\/h2>\n\n\n\n<p>Em PHP, o corpo bruto vem de <code>php:\/\/input<\/code>. Aten\u00e7\u00e3o ao <code>GET<\/code>: o PHP troca pontos por sublinhados nos nomes de par\u00e2metros, ent\u00e3o <code>hub.verify_token<\/code> vira <code>$_GET['hub_verify_token']<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-php\">&lt;?php\n$appSecret = getenv('META_APP_SECRET');\n$verifyToken = getenv('WEBHOOK_VERIFY_TOKEN');\n\nif ($_SERVER['REQUEST_METHOD'] === 'GET') {\n    if (($_GET['hub_mode'] ?? '') === 'subscribe'\n        &amp;&amp; hash_equals($verifyToken, $_GET['hub_verify_token'] ?? '')) {\n        echo $_GET['hub_challenge'] ?? '';\n        exit;\n    }\n    http_response_code(403);\n    exit;\n}\n\n$corpo = file_get_contents('php:\/\/input');\n$recebida = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';\n$esperada = 'sha256=' . hash_hmac('sha256', $corpo, $appSecret);\n\nif (!hash_equals($esperada, $recebida)) {\n    http_response_code(401);\n    exit;\n}\n\n$evento = json_decode($corpo, true);\nhttp_response_code(200);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Erros comuns que fazem a assinatura n\u00e3o bater<\/h2>\n\n\n\n<p><strong>Hash calculado sobre o JSON interpretado.<\/strong> \u00c9 o erro n\u00famero um. Ao fazer <code>JSON.stringify(req.body)<\/code> ou <code>json.dumps(payload)<\/code>, voc\u00ea gera um texto diferente do original: espa\u00e7os, ordem de chaves e escape de caracteres mudam. Um \u00fanico byte diferente muda o hash inteiro. Assine sempre os bytes que chegaram.<\/p>\n\n\n\n<p><strong>Encoding trocado.<\/strong> Converter o corpo para string com um charset errado (latin-1 em vez de UTF-8, por exemplo) altera nomes com acento e emojis. Trabalhe com bytes at\u00e9 a valida\u00e7\u00e3o terminar.<\/p>\n\n\n\n<p><strong>Secret errado.<\/strong> O valor certo \u00e9 o app secret do app que est\u00e1 inscrito no webhook. N\u00e3o \u00e9 o token de acesso, n\u00e3o \u00e9 o verify token e n\u00e3o \u00e9 o secret de outro app do mesmo portf\u00f3lio. Se voc\u00ea tem apps separados para teste e produ\u00e7\u00e3o, cada ambiente precisa do seu.<\/p>\n\n\n\n<p><strong>Prefixo ignorado.<\/strong> O cabe\u00e7alho traz <code>sha256=<\/code> antes do hash. Ou voc\u00ea compara a string completa (como nos exemplos), ou remove o prefixo dos dois lados.<\/p>\n\n\n\n<p><strong>Middleware ou gateway alterando o corpo.<\/strong> Proxies, gateways de API e fun\u00e7\u00f5es serverless \u00e0s vezes reformatam ou codificam o corpo antes de entregar ao seu c\u00f3digo. Se a valida\u00e7\u00e3o falha s\u00f3 em produ\u00e7\u00e3o, registre o tamanho do corpo recebido e compare com o <code>Content-Length<\/code>.<\/p>\n\n\n\n<p><strong>Secret trocado sem atualizar o servidor.<\/strong> Ao redefinir o app secret no painel, os eventos passam a chegar assinados com o novo valor. Se o servidor recusar tudo com 401, a Meta tenta reenviar: pela <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">vis\u00e3o geral de webhooks<\/a>, as entregas que n\u00e3o recebem <code>200<\/code> s\u00e3o repetidas com frequ\u00eancia decrescente por at\u00e9 7 dias, e isso pode gerar eventos duplicados. Monitore a taxa de 401 do endpoint para pegar esse cen\u00e1rio cedo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Boas pr\u00e1ticas depois da valida\u00e7\u00e3o<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Responda r\u00e1pido.<\/strong> Valide, enfileire e devolva <code>200<\/code>. Processamento pesado (IA, CRM, banco) vai para um worker.<\/li>\n\n\n<li><strong>Trate duplicatas.<\/strong> Use o <code>id<\/code> da mensagem (<code>wamid<\/code>) ou do status como chave de idempot\u00eancia, j\u00e1 que os reenvios podem repetir eventos.<\/li>\n\n\n<li><strong>Aceite payloads grandes.<\/strong> A vis\u00e3o geral de webhooks informa que um payload pode ter at\u00e9 3 MB; confira o limite de corpo do seu servidor.<\/li>\n\n\n<li><strong>N\u00e3o dependa de lista de IPs.<\/strong> A Meta muda seus endere\u00e7os periodicamente e sugere mTLS no lugar de liberar IPs fixos.<\/li>\n\n\n<li><strong>Teste localmente<\/strong> com um t\u00fanel antes de subir; veja <a href=\"https:\/\/vectalk.com.br\/blog\/testar-webhook-whatsapp-localmente\/\">como testar o webhook do WhatsApp com ngrok<\/a>.<\/li>\n\n<\/ul>\n\n\n\n<p>Para gerar um evento assinado no seu pr\u00f3prio ambiente de teste e conferir o c\u00f3digo, calcule o hash com o mesmo secret:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-bash\">corpo='{\"object\":\"whatsapp_business_account\",\"entry\":[]}'\nassinatura=$(printf '%s' \"$corpo\" | openssl dgst -sha256 -hmac \"$META_APP_SECRET\" | sed 's\/^.* \/\/')\ncurl -X POST http:\/\/localhost:3000\/webhook \\\n  -H \"Content-Type: application\/json\" \\\n  -H \"X-Hub-Signature-256: sha256=$assinatura\" \\\n  -d \"$corpo\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Como fazer isso com a Vectalk<\/h2>\n\n\n\n<p>A Vectalk \u00e9 um proxy da Cloud API oficial: o Hub recebe os eventos da Meta e repassa \u00e0s URLs que voc\u00ea cadastra o mesmo payload da documenta\u00e7\u00e3o da Meta, sem formato pr\u00f3prio. Voc\u00ea registra quantas URLs quiser por inst\u00e2ncia com <code>POST https:\/\/apis.vectalk.com.br\/api\/webhooks<\/code>, e o endpoint deve responder <code>200<\/code> em menos de 20 segundos, conforme a <a href=\"https:\/\/docs.vectalk.com.br\/concepts\/webhooks\">documenta\u00e7\u00e3o de webhooks da Vectalk<\/a>. O cabe\u00e7alho <code>X-Hub-Signature-256<\/code> descrito aqui \u00e9 o que a Meta envia a quem recebe direto do app; para saber como autenticar a entrega feita pelo Hub no seu caso, consulte a documenta\u00e7\u00e3o ou fale com o time pela <a href=\"https:\/\/vectalk.com.br\/contato.html\">p\u00e1gina de contato<\/a>. O parser do payload, a fila e a idempot\u00eancia continuam iguais. Para come\u00e7ar, crie sua conta em <a href=\"https:\/\/apps.vectalk.com.br\/register\">apps.vectalk.com.br\/register<\/a>.<\/p>\n\n\n\n<p>Com o webhook seguro, os pr\u00f3ximos passos naturais s\u00e3o <a href=\"https:\/\/vectalk.com.br\/blog\/baixar-midia-webhook-whatsapp\/\">baixar a m\u00eddia que o cliente envia<\/a> e controlar o ritmo de resposta para n\u00e3o esbarrar no <a href=\"https:\/\/vectalk.com.br\/blog\/rate-limit-throughput-api-whatsapp\/\">throughput e rate limit da API<\/a>. Para a vis\u00e3o geral da plataforma, veja o guia da <a href=\"https:\/\/vectalk.com.br\/blog\/api-oficial-do-whatsapp\/\">API oficial do WhatsApp<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Perguntas frequentes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Onde encontro o app secret?<\/h3>\n\n\n\n<p>No painel de desenvolvedores da Meta, em <strong>Configura\u00e7\u00f5es do app &gt; B\u00e1sico<\/strong>, no campo &#8220;Chave secreta do app&#8221;. Guarde em vari\u00e1vel de ambiente ou num gerenciador de segredos, nunca no reposit\u00f3rio.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">O verify token precisa ser igual ao app secret?<\/h3>\n\n\n\n<p>N\u00e3o, e n\u00e3o deveria. O verify token \u00e9 uma string que voc\u00ea escolhe e s\u00f3 serve para o <code>GET<\/code> de verifica\u00e7\u00e3o. O app secret \u00e9 gerado pela Meta e assina os eventos <code>POST<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Por que a verifica\u00e7\u00e3o GET passa e a assinatura POST falha?<\/h3>\n\n\n\n<p>Porque s\u00e3o checagens independentes. O <code>GET<\/code> s\u00f3 compara o verify token. Se o <code>POST<\/code> falha, quase sempre o hash est\u00e1 sendo calculado sobre o JSON interpretado ou com o secret de outro app.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Que c\u00f3digo devo devolver quando a assinatura \u00e9 inv\u00e1lida?<\/h3>\n\n\n\n<p>Qualquer c\u00f3digo diferente de <code>200<\/code>, como 401 ou 403. Lembre que entregas leg\u00edtimas recusadas s\u00e3o reenviadas, ent\u00e3o um secret desatualizado aparece como uma enxurrada de 401 e de eventos atrasados.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Preciso validar a assinatura em ambiente de teste?<\/h3>\n\n\n\n<p>Sim. Validar desde o primeiro dia evita que um c\u00f3digo sem checagem v\u00e1 para produ\u00e7\u00e3o. Para testar sem a Meta, gere a assinatura com <code>openssl<\/code> como no exemplo acima. Os detalhes de payload est\u00e3o em <a href=\"https:\/\/vectalk.com.br\/blog\/status-mensagem-webhook-whatsapp\/\">status de mensagem via webhook<\/a>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>Fontes oficiais consultadas em 28\/10\/2026:<\/strong> <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/create-webhook-endpoint\" target=\"_blank\" rel=\"noreferrer noopener\">Create a webhook endpoint (Meta)<\/a>, <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">WhatsApp webhooks: vis\u00e3o geral (Meta)<\/a>, <a href=\"https:\/\/developers.facebook.com\/docs\/graph-api\/webhooks\/getting-started\" target=\"_blank\" rel=\"noreferrer noopener\">Webhooks da Graph API: getting started (Meta)<\/a>, <a href=\"https:\/\/docs.vectalk.com.br\/concepts\/webhooks\">Webhooks na documenta\u00e7\u00e3o da Vectalk<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Como conferir o cabe\u00e7alho X-Hub-Signature-256 do webhook do WhatsApp com HMAC SHA-256, exemplos em Node.js, Python e PHP e os erros que fazem a valida\u00e7\u00e3o falhar.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[8],"tags":[],"class_list":["post-504","post","type-post","status-publish","format-standard","hentry","category-uncategorized-pt"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Assinatura do webhook do WhatsApp: X-Hub-Signature-256<\/title>\n<meta name=\"description\" content=\"Valide a assinatura do webhook do WhatsApp: HMAC SHA-256 com o app secret sobre o corpo bruto, com exemplos em Node.js, Python e PHP e os erros comuns.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Assinatura do webhook do WhatsApp: X-Hub-Signature-256\" \/>\n<meta property=\"og:description\" content=\"Valide a assinatura do webhook do WhatsApp: HMAC SHA-256 com o app secret sobre o corpo bruto, com exemplos em Node.js, Python e PHP e os erros comuns.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog Vectalk\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-28T16:04:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-28T16:04:43+00:00\" \/>\n<meta name=\"author\" content=\"wanderleyfcunha\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"wanderleyfcunha\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/\"},\"author\":{\"name\":\"wanderleyfcunha\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#\\\/schema\\\/person\\\/ff36ecd9d8257856f227f8e5d639db2b\"},\"headline\":\"Como validar a assinatura do webhook do WhatsApp (X-Hub-Signature-256)\",\"datePublished\":\"2026-10-28T16:04:32+00:00\",\"dateModified\":\"2026-10-28T16:04:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/\"},\"wordCount\":1485,\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/\",\"url\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/\",\"name\":\"Assinatura do webhook do WhatsApp: X-Hub-Signature-256\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#website\"},\"datePublished\":\"2026-10-28T16:04:32+00:00\",\"dateModified\":\"2026-10-28T16:04:43+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#\\\/schema\\\/person\\\/ff36ecd9d8257856f227f8e5d639db2b\"},\"description\":\"Valide a assinatura do webhook do WhatsApp: HMAC SHA-256 com o app secret sobre o corpo bruto, com exemplos em Node.js, Python e PHP e os erros comuns.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/assinatura-webhook-whatsapp\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Como validar a assinatura do webhook do WhatsApp (X-Hub-Signature-256)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/\",\"name\":\"Blog Vectalk\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#\\\/schema\\\/person\\\/ff36ecd9d8257856f227f8e5d639db2b\",\"name\":\"wanderleyfcunha\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g\",\"caption\":\"wanderleyfcunha\"},\"sameAs\":[\"https:\\\/\\\/vectalk.com.br\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Assinatura do webhook do WhatsApp: X-Hub-Signature-256","description":"Valide a assinatura do webhook do WhatsApp: HMAC SHA-256 com o app secret sobre o corpo bruto, com exemplos em Node.js, Python e PHP e os erros comuns.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/","og_locale":"en_US","og_type":"article","og_title":"Assinatura do webhook do WhatsApp: X-Hub-Signature-256","og_description":"Valide a assinatura do webhook do WhatsApp: HMAC SHA-256 com o app secret sobre o corpo bruto, com exemplos em Node.js, Python e PHP e os erros comuns.","og_url":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/","og_site_name":"Blog Vectalk","article_published_time":"2026-10-28T16:04:32+00:00","article_modified_time":"2026-10-28T16:04:43+00:00","author":"wanderleyfcunha","twitter_card":"summary_large_image","twitter_misc":{"Written by":"wanderleyfcunha","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/#article","isPartOf":{"@id":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/"},"author":{"name":"wanderleyfcunha","@id":"https:\/\/vectalk.com.br\/blog\/#\/schema\/person\/ff36ecd9d8257856f227f8e5d639db2b"},"headline":"Como validar a assinatura do webhook do WhatsApp (X-Hub-Signature-256)","datePublished":"2026-10-28T16:04:32+00:00","dateModified":"2026-10-28T16:04:43+00:00","mainEntityOfPage":{"@id":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/"},"wordCount":1485,"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/","url":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/","name":"Assinatura do webhook do WhatsApp: X-Hub-Signature-256","isPartOf":{"@id":"https:\/\/vectalk.com.br\/blog\/#website"},"datePublished":"2026-10-28T16:04:32+00:00","dateModified":"2026-10-28T16:04:43+00:00","author":{"@id":"https:\/\/vectalk.com.br\/blog\/#\/schema\/person\/ff36ecd9d8257856f227f8e5d639db2b"},"description":"Valide a assinatura do webhook do WhatsApp: HMAC SHA-256 com o app secret sobre o corpo bruto, com exemplos em Node.js, Python e PHP e os erros comuns.","breadcrumb":{"@id":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/vectalk.com.br\/blog\/assinatura-webhook-whatsapp\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/vectalk.com.br\/blog\/"},{"@type":"ListItem","position":2,"name":"Como validar a assinatura do webhook do WhatsApp (X-Hub-Signature-256)"}]},{"@type":"WebSite","@id":"https:\/\/vectalk.com.br\/blog\/#website","url":"https:\/\/vectalk.com.br\/blog\/","name":"Blog Vectalk","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/vectalk.com.br\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/vectalk.com.br\/blog\/#\/schema\/person\/ff36ecd9d8257856f227f8e5d639db2b","name":"wanderleyfcunha","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g","caption":"wanderleyfcunha"},"sameAs":["https:\/\/vectalk.com.br\/blog"]}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts\/504","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/comments?post=504"}],"version-history":[{"count":1,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts\/504\/revisions"}],"predecessor-version":[{"id":507,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts\/504\/revisions\/507"}],"wp:attachment":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/media?parent=504"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/categories?post=504"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/tags?post=504"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}