The package automatically registers webhook routes at the configured path (default: /whatsapp/webhook).
In your Meta App Dashboard:
- Go to WhatsApp > Configuration
- Set Callback URL to:
https://yourdomain.com/whatsapp/webhook - Set Verify Token to the value of your
WHATSAPP_WEBHOOK_VERIFY_TOKENenv variable - Subscribe to the webhook fields you need (e.g.,
messages)
WHATSAPP_WEBHOOK_PATH=api/whatsapp/webhookThis changes the route to /api/whatsapp/webhook.
The package handles the GET verification challenge automatically. When Meta sends the verification request, the controller:
- Checks
hub.verify_tokenagainst all configured accountwebhook_verify_tokenvalues - Returns the
hub.challengevalue on match - Returns 403 on mismatch
POST requests are validated using the X-Hub-Signature-256 header against the webhook_secret of each configured account. Invalid signatures are rejected with 403.
The package dispatches events based on the webhook payload:
Dispatched for every valid incoming webhook, before any processing. Useful for debugging or inspecting the full raw payload.
use Laraditz\Whatsapp\Events\WebhookReceived;
Event::listen(WebhookReceived::class, function (WebhookReceived $event) {
$event->payload; // Full raw webhook payload (entry, changes, etc.)
});Dispatched when a user sends a message to your WhatsApp number.
use Laraditz\Whatsapp\Events\MessageReceived;
Event::listen(MessageReceived::class, function (MessageReceived $event) {
$event->from; // Sender's phone number
$event->message; // Message body (text content or type placeholder)
$event->type; // Message type: 'text', 'image', 'video', etc.
$event->accountName; // Which WhatsApp account received it
$event->raw; // Full raw message data from the API
});Dispatched when a sent message is delivered to the recipient.
use Laraditz\Whatsapp\Events\MessageDelivered;
Event::listen(MessageDelivered::class, function (MessageDelivered $event) {
$event->messageId; // WhatsApp message ID (wamid.xxx)
$event->accountName; // Account name
$event->raw; // Full raw status data
});Dispatched when a sent message is read by the recipient.
use Laraditz\Whatsapp\Events\MessageRead;
Event::listen(MessageRead::class, function (MessageRead $event) {
$event->messageId; // WhatsApp message ID
$event->accountName; // Account name
$event->raw; // Full raw status data
});use Illuminate\Support\Facades\Event;
use Laraditz\Whatsapp\Events\MessageReceived;
// In boot() of a service provider
Event::listen(MessageReceived::class, function (MessageReceived $event) {
Log::info("Message from {$event->from}: {$event->message}");
});// app/Listeners/HandleWhatsappMessage.php
namespace App\Listeners;
use Laraditz\Whatsapp\Events\MessageReceived;
use Laraditz\Whatsapp\Facades\Whatsapp;
class HandleWhatsappMessage
{
public function handle(MessageReceived $event): void
{
// Auto-reply
Whatsapp::account($event->accountName)
->message()
->to($event->from)
->text("Thanks for your message! We'll get back to you soon.")
->send();
}
}Register in EventServiceProvider or use event discovery.
When logging.messages is enabled, the package automatically:
- Creates a record in
whatsapp_messagesfor inbound messages - Updates the
statusfield when delivery/read receipts arrive (sent->delivered->read)
For messages that may have missed status updates:
# Sync message statuses from the API
php artisan whatsapp:sync-messages
# For a specific account and date range
php artisan whatsapp:sync-messages --account=default --since=2024-01-01When logging.webhooks is enabled, every webhook payload is logged to the whatsapp_webhook_logs table with the event type (message, status) and full payload for debugging.