Ver planos
Início/ Blog/ WhatsApp/ Como integrar a WhatsApp Cloud API ao Laravel
WhatsApp

Como integrar a WhatsApp Cloud API ao Laravel

C
Carlos 25 de maio de 2026 · 9 min de leitura
Como integrar a WhatsApp Cloud API ao Laravel
Em resumo

A integração tem três partes: credenciais em config/services.php lendo o .env, um serviço dedicado que fala com a Graph API pelo cliente Http do Laravel e um controller de webhook com uma rota GET para o handshake e uma POST para os eventos. Em produção, valide a assinatura e processe em fila.

Como integrar a WhatsApp Cloud API a uma aplicação Laravel?

São três peças. Primeiro, guarde token, Phone Number ID e versão da API no .env e exponha tudo em config/services.php. Segundo, crie um serviço que fale com a Graph API usando o cliente Http do Laravel. Terceiro, publique duas rotas de webhook: uma GET, que responde ao handshake da Meta com o hub_challenge, e uma POST, que recebe os eventos e despacha o processamento para uma fila.

Quem desenvolve um SaaS, um e-commerce ou um CRM em Laravel já percebeu que o WhatsApp deixou de ser um extra do produto e virou parte do fluxo principal.

Com a Cloud API hospedada pela própria Meta, essa integração ficou bem mais direta do que era na época dos intermediários. Neste guia vamos montar a fundação de uma integração séria entre Laravel e Cloud API: configuração de credenciais, serviço de envio e recebimento de eventos por webhook.

Escopo deste guia: aqui montamos a base técnica, ou seja, variáveis de ambiente, serviço de envio e webhook. Para colocar em produção você ainda vai precisar de filas, logs, reprocessamento, validação de assinatura e monitoramento. Falamos de cada um deles no final.

2 bilhões
de pessoas usam o WhatsApp em mais de 180 países, o que faz do canal um requisito de produto e não um diferencial
Meta, comunicado oficial sobre o WhatsApp

O que você precisa ter em mãos

Antes de abrir o terminal, confirme que a conta no Meta for Developers já tem os ativos da API oficial. Se algum deles faltar, o código abaixo simplesmente não vai autenticar.

  • Phone Number ID Identificador da linha que vai enviar as mensagens, seja o número de teste ou o de produção. Ele fica na seção WhatsApp do app, em Configuração da API.
  • WhatsApp Business Account ID Identificador da conta comercial vinculada à empresa. Não confunda com o anterior: um aponta para a conta inteira, o outro para uma linha específica.
  • Token de acesso permanente Credencial gerada no Gerenciador de Negócios para autenticar as chamadas à Graph API. O token temporário do painel de teste expira em 24 horas e não serve para produção.
  • App Secret Você vai usá-lo para validar a assinatura dos webhooks. Ele fica em Configurações básicas do aplicativo, no Meta for Developers.
  • HTTPS no ambiente público A Meta só entrega webhook em endpoint com certificado válido. Em desenvolvimento local, um túnel como o ngrok resolve.

Passo 1: configure as credenciais

Comece mapeando tudo no .env. Token nunca vai para dentro do código, nem em controller, nem em serviço versionado.

WHATSAPP_TOKEN=seu_token_permanente_aqui
WHATSAPP_PHONE_NUMBER_ID=seu_phone_number_id
WHATSAPP_VERSION=v20.0
WHATSAPP_VERIFY_TOKEN=um_token_qualquer_que_voce_inventa
WHATSAPP_APP_SECRET=seu_app_secret

O WHATSAPP_VERIFY_TOKEN é uma senha que você mesmo escolhe. Ela não vem da Meta: você define aqui e informa o mesmo valor no painel ao cadastrar o webhook. Serve só para provar, no handshake, que os dois lados combinaram.

Em seguida, exponha as credenciais em config/services.php, que é o lugar padrão do framework para isso.

'whatsapp' => [
    'token'           => env('WHATSAPP_TOKEN'),
    'phone_number_id' => env('WHATSAPP_PHONE_NUMBER_ID'),
    'version'         => env('WHATSAPP_VERSION', 'v20.0'),
    'verify_token'    => env('WHATSAPP_VERIFY_TOKEN'),
    'app_secret'      => env('WHATSAPP_APP_SECRET'),
],

Cuidado com o cache de configuração. Depois de mudar qualquer variável em produção, rode php artisan config:clear e reconstrua o cache. Sem isso a aplicação continua lendo os valores antigos e você perde horas procurando um erro que não existe no código.

Passo 2: crie o serviço de envio

O Laravel já traz o cliente Http, então não é preciso instalar nada. O que vale a pena é isolar a conversa com a Meta em uma classe própria, em vez de espalhar chamadas HTTP pelos controllers. Quando a Meta mudar a versão da API, você altera um arquivo só.

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class WhatsAppService
{
    protected string $baseUrl;
    protected string $token;

    public function __construct()
    {
        $this->token = config('services.whatsapp.token');

        $this->baseUrl = 'https://graph.facebook.com/'
            . config('services.whatsapp.version')
            . '/' . config('services.whatsapp.phone_number_id');
    }

    public function sendTemplateMessage(
        string $to,
        string $templateName,
        string $languageCode = 'pt_BR',
        array $components = []
    ): array {
        $response = Http::withToken($this->token)
            ->post("{$this->baseUrl}/messages", [
                'messaging_product' => 'whatsapp',
                'to'                => $to,
                'type'              => 'template',
                'template'          => [
                    'name'       => $templateName,
                    'language'   => ['code' => $languageCode],
                    'components' => $components,
                ],
            ]);

        return $response->json();
    }
}

Esse método envia mensagens de template, que é o único formato aceito para iniciar conversa fora da janela de atendimento. Se você ainda não cadastrou os seus, o guia sobre modelos de mensagem no WhatsApp API mostra como escrever e submeter cada um.

Para mensagem livre dentro da janela de 24 horas, a URL e a autenticação são as mesmas. Muda só o corpo, que passa a usar o tipo text em vez de template.

Passo 3: publique o webhook

Para receber respostas dos clientes e mudanças de status, a aplicação precisa expor um endpoint público. A Meta faz duas coisas nele: um GET uma única vez, para validar o endereço, e POST a cada evento.

Comece pelas rotas, em routes/api.php:

use App\Http\Controllers\WhatsAppWebhookController;
use Illuminate\Support\Facades\Route;

Route::get('/whatsapp/webhook',  [WhatsAppWebhookController::class, 'verify']);
Route::post('/whatsapp/webhook', [WhatsAppWebhookController::class, 'handle']);

Agora o controller. Repare que o handle() devolve 200 imediatamente e joga o trabalho pesado para uma fila, que é o desenho recomendado desde o primeiro dia.

<?php

namespace App\Http\Controllers;

use App\Jobs\ProcessWhatsAppEvent;
use Illuminate\Http\Request;

class WhatsAppWebhookController extends Controller
{
    public function verify(Request $request)
    {
        $verifyToken = config('services.whatsapp.verify_token');

        if ($request->query('hub_mode') === 'subscribe'
            && hash_equals($verifyToken, (string) $request->query('hub_verify_token'))) {
            return response($request->query('hub_challenge'), 200);
        }

        return response('Forbidden', 403);
    }

    public function handle(Request $request)
    {
        ProcessWhatsAppEvent::dispatch($request->all());

        return response('EVENT_RECEIVED', 200);
    }
}

A Meta envia os parâmetros do handshake com ponto, como hub.mode e hub.verify_token. O PHP converte esses pontos em sublinhado ao montar o array da query, por isso lemos hub_mode e hub_verify_token. Se preferir não depender desse comportamento, leia a query string bruta da requisição.

Em projetos que ainda passam essa rota pelo middleware VerifyCsrfToken, adicione api/whatsapp/webhook à lista de exceções. A Meta não envia token CSRF e a requisição seria recusada antes de chegar ao controller.

Com o webhook recebendo eventos, o próximo passo natural é montar um chatbot em cima da API do WhatsApp.

Boas práticas para produção

Uma integração que funciona no ambiente de teste costuma quebrar no primeiro pico de volume. Estes quatro pontos evitam a maior parte dos problemas.

  • Responda rápido e processe em fila Nada de consultar banco, chamar CRM ou rodar lógica de bot dentro do handle. Receba o payload, despache um job e devolva 200. Se você demorar, a Meta considera falha e reentrega o mesmo evento.
  • Valide a assinatura de cada requisição Confira o cabeçalho X-Hub-Signature-256 com o App Secret antes de confiar no conteúdo. Sem isso, qualquer pessoa que descobrir a URL do seu webhook pode injetar mensagens falsas na aplicação.
  • Trate a reentrega e a idempotência O mesmo evento pode chegar mais de uma vez. Guarde o identificador da mensagem e ignore o que já foi processado, senão o cliente recebe a mesma resposta automática duas vezes.
  • Separe os ambientes Use números, tokens e URLs de webhook diferentes para desenvolvimento, homologação e produção. Um teste disparando na base real é um problema que ninguém quer explicar.

Sobre a fila: no exemplo acima, o ProcessWhatsAppEvent é um job comum do Laravel. Rode a fila com Redis e monitore pelo Horizon. Assim você enxerga a latência de processamento e reprocessa o que falhou sem perder evento.

Quando construir e quando conectar

O código acima resolve a integração. O que costuma consumir meses de time não é ele: é a camada que vem depois. Painel multiatendente, filas por setor, permissões por usuário, histórico por cliente, gestão de templates, auditoria, relatórios e o monitoramento de tudo isso.

A Atys é construída exatamente sobre essa camada. Se a sua necessidade é enviar notificações transacionais a partir do seu produto, o serviço deste guia resolve bem e vale manter. Se a necessidade é uma equipe atendendo pelo mesmo número, com regra de distribuição e indicador de tempo de resposta, construir tudo do zero raramente compensa.

A conexão já vem pronta

Criação da conta comercial, verificação do número e cadastro do webhook são feitos pelo fluxo oficial da Meta, sem você manter credencial nenhuma.

Fila, retry e idempotência resolvidos

O processamento de eventos, a reentrega e o tratamento de duplicidade já estão implementados e monitorados.

API para o seu sistema falar

O seu backend continua no comando: dispara mensagens e recebe eventos pela API da Atys, sem reimplementar a camada de atendimento.

Painel para a equipe humana

O que o bot não resolve cai em uma fila com histórico, e o gestor acompanha o tempo de resposta por atendente.

Para entender como essa camada se liga ao restante do processo comercial, vale ver como funciona a integração entre CRM e WhatsApp.

Resumindo

A base de uma integração entre Laravel e Cloud API cabe em três arquivos: a configuração das credenciais, um serviço de envio e um controller de webhook. O resto é disciplina de produção, com fila, assinatura validada e idempotência.

Se a sua empresa quer pular a construção da camada operacional e ir direto para o atendimento, fale com o time da Atys. E se o que te trouxe aqui foi segurança e volume, o guia sobre segurança e escalabilidade na API oficial é a leitura seguinte.

Preciso de um BSP para usar a Cloud API no Laravel?
Não. A Cloud API é hospedada pela própria Meta e você fala direto com a Graph API. O intermediário só volta a fazer sentido em cenários que exigem hospedagem própria da API local, que a Meta vem descontinuando.
Por que a Meta não valida meu webhook?
Nos casos mais comuns, a URL não está em HTTPS com certificado válido, o verify token cadastrado no painel não é igual ao do .env, ou a rota está sendo bloqueada por CSRF ou por um middleware de autenticação. Teste o GET manualmente antes de cadastrar.
O token de acesso expira?
O token de teste do painel expira em 24 horas. Já o token gerado por um usuário de sistema no Gerenciador de Negócios pode ser permanente, e é esse o que você deve usar em produção.
Posso enviar qualquer mensagem pela API?
Dentro da janela de 24 horas depois da última mensagem do cliente, sim, texto livre. Fora dela, só modelos previamente aprovados pela Meta, e a categoria do modelo define a tarifa da conversa.
Como testo o webhook em ambiente local?
Suba um túnel HTTPS para a sua máquina, com ngrok ou equivalente, e cadastre a URL gerada no painel da Meta. Lembre-se de atualizar o endereço sempre que o túnel reiniciar.
#integração #webhook #WhatsApp Cloud API #Laravel #PHP
C
Carlos Conteúdo · Atys

Continue lendo

Outros artigos da mesma categoria que podem te ajudar.

O que é WhatsApp Business API? Guia para PMEs em 2026
WhatsApp · 6 min

O que é WhatsApp Business API? Guia para PMEs em 2026

Vários vendedores no mesmo número, celular que desconecta, medo de banimento. Se o WhatsApp da sua empresa já chegou nes...

M Marcelo
12 jun
Como atender vários clientes no mesmo WhatsApp
WhatsApp · 6 min

Como atender vários clientes no mesmo WhatsApp

Vários atendentes no mesmo número do WhatsApp, sem celular circulando pela empresa: as três opções disponíveis, o que mu...

M Marcelo
12 jun
Como dividir o atendimento do WhatsApp entre a equipe
WhatsApp · 8 min

Como dividir o atendimento do WhatsApp entre a equipe

Quando o time cresce, o WhatsApp vira disputa por lead e mensagem esquecida. Veja os três modelos de divisão de atendime...

M Marcelo
12 jun
Dê o próximo passo

Tudo o que sua empresa faz para vender, em um só sistema

Atendimento, CRM, marketing, financeiro e IA na mesma plataforma. Veja funcionando na sua operação.

Agendar demonstração

Recebemos seu contato!

Um especialista da Atys vai falar com você em breve para agendar a demonstração.

Agendar demonstração

Em 20 minutos um especialista mostra a Atys na sua realidade.

BR +55