Callback central do WhatsApp
URL única da Meta que encaminha cada mensagem à loja ou ao sistema dono do número, e a rota para cadastrar o destino de um número.
A Meta permite uma única URL de callback por aplicativo, mas a plataforma atende muitas lojas, cada uma com os seus números. O callback central resolve isso: a Meta chama sempre a mesma URL, a plataforma descobre o número comercial dentro da mensagem e encaminha para o destino cadastrado para aquele número. O destino pode ser a própria plataforma (uma loja Venddor) ou um sistema externo seu.
Verificar a URL central
Desafio de verificação da Meta para a URL central. Funciona como o da loja, mas o token de verificação é o da plataforma e não pertence a uma loja.
/api/v1/webhooks/whatsapp-routesPúblicaVerificação da Meta na URL central
Parâmetros de consulta
hub.modestringobrigatóriosubscribesubscribe.hub.verify_tokenstringobrigatóriohub.challengestringobrigatórioExemplo de requisição
curl "$BASE_URL/api/v1/webhooks/whatsapp-routes?hub.mode=subscribe&hub.verify_token=$VERIFY_TOKEN&hub.challenge=1158201444"Resposta
1158201444Erros
| Status | Quando | Corpo |
|---|---|---|
| 400 | hub.mode diferente de subscribe | {"error":"invalid hub.mode"} |
| 403 | Token errado | {"error":"invalid verify token"} |
Receber e encaminhar mensagens
A Meta envia aqui todas as notificações do aplicativo. A plataforma confere a assinatura, extrai o número comercial e procura a rota ativa daquele número:
- Se a rota aponta para a plataforma, a mensagem é processada pela loja dona do número.
- Se aponta para uma URL externa, a plataforma encaminha o mesmo corpo para ela (veja o contrato abaixo).
- Se não há rota, a notificação é ignorada.
A resposta à Meta é sempre 200 quando a assinatura confere, mesmo que o encaminhamento falhe, para a Meta não repetir a notificação e sobrecarregar um destino fora do ar.
/api/v1/webhooks/whatsapp-routesPúblicaEntrada central de notificações da Meta
Cabeçalhos
X-Hub-Signature-256stringobrigatóriosha256= mais o HMAC-SHA256 do corpo bruto, com o segredo do app da Meta.Corpo da requisição
(JSON)objectobrigatórioExemplo de requisição
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-routes" \
-H "Content-Type: application/json" \
-H "X-Hub-Signature-256: $SIG" \
-d "$BODY"Resposta
{"status":"ok"}{"status":"routed"}Outros 200: {"status":"forward_failed"} (o destino externo falhou), {"status":"ignored"} (nenhuma loja dona do número) e {"status":"process_error"}.
Erros
| Status | Quando | Corpo |
|---|---|---|
| 400 | Não foi possível ler o corpo | {"error":"failed to read body"} |
| 401 | Assinatura inválida | {"error":"invalid signature"} |
| 403 | Segredo do app não cadastrado | {"error":"app secret not configured"} |
| 503 | Credenciais da plataforma indisponíveis, ou limite de 20 segundos excedido | {"error":"platform credentials unavailable"} |
Contrato de quem recebe o encaminhamento
Quando a rota do número aponta para um sistema seu, a plataforma faz um POST na webhook_url cadastrada com o mesmo corpo recebido da Meta e estes cabeçalhos:
| Cabeçalho | Valor |
|---|---|
Content-Type | application/json |
X-Route-Name | Nome da rota |
X-Business-Phone | Número comercial, só dígitos, com DDI |
X-Route-Key e X-Route-Api-Key | Chave própria da rota, para o seu servidor reconhecer a origem |
Responda 2xx em até 12 segundos. Outro status ou demora é registrado como falha de encaminhamento e não é repetido pela plataforma.
Cadastrar uma rota
Sistemas externos cadastram (ou atualizam) o destino de um número chamando esta rota com a chave mestra de rotas, que a equipe Venddor fornece. É um upsert por telefone: registrar o mesmo número de novo atualiza a rota existente e mantém a chave dela.
/api/v1/webhooks/whatsapp-routes/registerPúblicaCadastrar ou atualizar a rota de um número
Cabeçalhos
X-Api-Keystringobrigatórioapi_key.Corpo da requisição
namestringobrigatóriophone_numberstringobrigatório55 é acrescentado se faltar. Entre 12 e 15 dígitos no total.webhook_urlstringverify_tokenstringactivebooleanpadrão: truefalse desativa a rota sem apagá-la.Exemplo de requisição
curl -X POST "$BASE_URL/api/v1/webhooks/whatsapp-routes/register" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $ROUTES_MASTER_KEY" \
-d '{"name":"Loja Centro","phone_number":"(11) 4004-1234","webhook_url":"https://api.minhaempresa.example.com/whatsapp/inbound","active":true}'Resposta
{
"success": true,
"message": "Route registered successfully",
"data": {
"route_id": 17,
"name": "Loja Centro",
"phone_number": "551140041234",
"webhook_url": "https://api.minhaempresa.example.com/whatsapp/inbound",
"verify_token": "meu-token-de-verificacao",
"api_key": "rk_live_example_not_real",
"active": true,
"created_at": "2026-10-11T20:30:00Z",
"updated_at": "2026-10-11T20:30:00Z"
}
}Campos da resposta
successbooleantrue quando registrou.messagestringdataobjectA rota.
route_idintegernamestringphone_numberstringwebhook_urlstringverify_tokenstringapi_keystringX-Route-Key ao encaminhar. Guarde-a para reconhecer a origem.activebooleancreated_atstringupdated_atstringErros
| Status | Quando | Corpo |
|---|---|---|
| 400 | Corpo inválido | {"success":false,"message":"Invalid request body","data":null} |
| 400 | name ausente ou telefone fora do formato | {"success":false,"message":"name is required","data":null} |
| 401 | Sem chave de API | {"success":false,"message":"API key required","data":null} |
| 403 | Chave de API inválida | {"success":false,"message":"Invalid API key","data":null} |