VenddorDocumentação API
API atualAPI legada
Guia rápidoReferência completa
Carregando índice…
API atual/Referência completa/Webhooks e eventos

WhatsApp da loja

Rotas que a Meta chama para verificar a URL, entregar mensagens e status do WhatsApp Cloud API e trocar dados dos Flows de uma loja.

O canal WhatsApp Commerce recebe tudo o que acontece no número da loja (mensagens do cliente, confirmações de entrega e de leitura) por webhooks da Meta. Cada loja tem a sua URL, identificada pelo tenant_slug (a primeira parte do domínio da loja, por exemplo minhaloja). Você cola essa URL e o token de verificação no painel de desenvolvedores da Meta. A loja precisa ter o módulo WhatsApp Commerce ativo.

Verificar a URL

Quando você salva a URL na Meta, ela faz um GET com um desafio. A loja confere o token e devolve o desafio como texto.

GET/api/v1/webhooks/whatsapp/{tenant_slug}Pública

Verificação da Meta (hub.challenge)

Parâmetros de caminho

tenant_slugstringobrigatório
Identificador da loja: a primeira parte do domínio (minhaloja em minhaloja.io.venddor.com.br).

Parâmetros de consulta

hub.modestringobrigatório
subscribe
Sempre subscribe.
hub.verify_tokenstringobrigatório
Token de verificação cadastrado no módulo WhatsApp da loja.
hub.challengestringobrigatório
Texto que deve ser devolvido.

Exemplo de requisição

bash
curl "$BASE_URL/api/v1/webhooks/whatsapp/minhaloja?hub.mode=subscribe&hub.verify_token=$VERIFY_TOKEN&hub.challenge=1158201444"

Resposta

200Desafio devolvido (texto puro)
text
1158201444

Erros

StatusQuandoCorpo
400hub.mode diferente de subscribe{"error":"invalid hub.mode, expected 'subscribe'"}
403Token de verificação não cadastrado{"error":"webhook verify token not configured"}
403Token errado{"error":"invalid verify token"}
403Módulo whatsapp-commerce desligado{"error":"module_disabled","module":"whatsapp-commerce"}

Receber mensagens e status

A Meta envia aqui cada mensagem recebida e cada atualização de status (enviada, entregue, lida). A loja confere a assinatura, processa a mensagem em até 10 segundos e sempre confirma com 200, mesmo que o processamento interno falhe, porque a Meta repete por vários dias qualquer resposta diferente de 2xx. A rota tem um limite de 20 segundos; passado esse tempo a resposta é 503.

POST/api/v1/webhooks/whatsapp/{tenant_slug}Pública

Receber mensagens e status do WhatsApp

Parâmetros de caminho

tenant_slugstringobrigatório
Identificador da loja: a primeira parte do domínio (minhaloja em minhaloja.io.venddor.com.br).

Cabeçalhos

X-Hub-Signature-256stringobrigatório
sha256= mais o HMAC-SHA256 do corpo bruto em hexadecimal, calculado com o segredo do app da Meta (App Secret).

Corpo da requisição

(JSON)objectobrigatório
Notificação da Meta no formato do WhatsApp Cloud API (object, entry[].changes[].value).

Exemplo de requisição

bash
BODY='{"object":"whatsapp_business_account","entry":[{"id":"102290129340398","changes":[{"field":"messages","value":{"messaging_product":"whatsapp","metadata":{"display_phone_number":"551140041234","phone_number_id":"106540352242922"},"statuses":[{"id":"wamid.HBgM","status":"delivered","timestamp":"1791748900","recipient_id":"5511987654321"}]}}]}]}'
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$META_APP_SECRET" | sed 's/^.* //')"

curl -X POST "$BASE_URL/api/v1/webhooks/whatsapp/minhaloja" \
  -H "Content-Type: application/json" \
  -H "X-Hub-Signature-256: $SIG" \
  -d "$BODY"

Resposta

200Confirmado
json
{"status":"ok"}

Erros

StatusQuandoCorpo
400Não foi possível ler o corpo{"error":"failed to read request body"}
401Assinatura inválida ou ausente{"error":"invalid webhook signature"}
403Segredo do app não cadastrado na lojawebhook secret not configured (texto simples)
403Módulo whatsapp-commerce desligado{"error":"module_disabled","module":"whatsapp-commerce"}
503A rota excedeu o limite de 20 segundos(corpo de timeout)

Troca de dados de um Flow

Os Flows são formulários interativos do WhatsApp (cadastro, endereço, pagamento) que mostram dados da loja em cada tela. A cada passo a Meta chama esta rota com o pedido de dados criptografado e espera a resposta também criptografada. A autenticidade vem da própria criptografia: só a Meta consegue cifrar para a chave pública que a loja publicou. Por isso a rota não usa assinatura.

POST/api/v1/webhooks/whatsapp/{tenant_slug}/flowPública

Troca de dados criptografada de um Flow

Parâmetros de caminho

tenant_slugstringobrigatório
Identificador da loja: a primeira parte do domínio (minhaloja em minhaloja.io.venddor.com.br).

Parâmetros de consulta

phone_number_idstring
Id do número de telefone da Meta, para escolher a chave do Flow. Sem ele, a loja usa a chave ativa.

Corpo da requisição

encrypted_aes_keystringobrigatório
Chave AES do pedido, cifrada com a chave pública RSA da loja, em base64.
encrypted_flow_datastringobrigatório
Dados do pedido, cifrados com AES-GCM, em base64.
initial_vectorstringobrigatório
Vetor de inicialização, em base64.

Exemplo de requisição

bash
curl -X POST "$BASE_URL/api/v1/webhooks/whatsapp/minhaloja/flow?phone_number_id=106540352242922" \
  -H "Content-Type: application/json" \
  -d '{"encrypted_aes_key":"<base64>","encrypted_flow_data":"<base64>","initial_vector":"<base64>"}'

Resposta

200Resposta cifrada (texto simples, base64)
text
q3XyZ0p1Qm9...==

A resposta é o texto base64 da resposta do Flow, cifrada com a mesma chave AES e o vetor invertido, sem envelope JSON.

Erros

StatusQuandoCorpo
400Corpo sem os três campos, ou que não decifra{"error":"encrypted_aes_key, encrypted_flow_data, and initial_vector are required"} ou {"error":"failed to decrypt flow body"}
401Loja sem chave de Flow ativa{"error":"no active flow key registered for this store"}
421A chave RSA não decifra a chave AES (chave desatualizada na Meta){"error":"failed to decrypt AES key (key may need rotation)"}
403Módulo whatsapp-commerce desligado{"error":"module_disabled","module":"whatsapp-commerce"}

Chave pública do Flow

Devolve a chave pública que a loja usa nos Flows de um número, para você comparar com a que a Meta tem cadastrada. A chave pública é pública por definição.

GET/api/v1/webhooks/whatsapp/{tenant_slug}/public_keyPública

Chave pública ativa do Flow

Parâmetros de caminho

tenant_slugstringobrigatório
Identificador da loja: a primeira parte do domínio (minhaloja em minhaloja.io.venddor.com.br).

Parâmetros de consulta

phone_number_idstringobrigatório
Id do número de telefone da Meta.

Exemplo de requisição

bash
curl "$BASE_URL/api/v1/webhooks/whatsapp/minhaloja/public_key?phone_number_id=106540352242922"

Resposta

200Chave em formato PEM (texto simples)
text
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----

Erros

StatusQuandoCorpo
400Falta phone_number_id{"error":"phone_number_id is required"}
404Nenhuma chave ativa para o número{"error":"no active flow key for phone_number_id"}
403Módulo whatsapp-commerce desligado{"error":"module_disabled","module":"whatsapp-commerce"}
Duas URLs, uma para cada coisa

Na Meta, a URL de Webhook do app (mensagens e status) é a da seção "Receber mensagens e status". A URL de Endpoint do Flow é a que termina em /flow. Misturá-las é o erro mais comum: o Flow passa a falhar com 400 porque recebe uma notificação comum.

Veja também

  • Callback central do WhatsApp
  • Visão geral da entrada
Anterior
Nota fiscal
Próxima
Callback central do WhatsApp
Nesta página
  • Verificar a URL
  • Exemplo de requisição
  • Resposta
  • Erros
  • Receber mensagens e status
  • Exemplo de requisição
  • Resposta
  • Erros
  • Troca de dados de um Flow
  • Exemplo de requisição
  • Resposta
  • Erros
  • Chave pública do Flow
  • Exemplo de requisição
  • Resposta
  • Erros
  • Veja também