Notifications
The package ships a Laravel notification channel, so WhatsApp works like mail or SMS: $user->notify(new OrderShipped($order)).
Route the notifiable
Tell Laravel where to send. Return a phone number for the Cloud API, or a WhatsApp ID for the Web sidecar:
class User extends Authenticatable
{
use Notifiable;
public function routeNotificationForWhatsapp($notification): ?string
{
return $this->phone; // '+966512345678' or '966512345678@c.us'
}
}Returning null skips the notification for that user.
Write the notification
Add 'whatsapp' to via() and a toWhatsApp() method. Return a string for plain text, or a WhatsAppMessage for anything else:
use Illuminate\Notifications\Notification;
use Kstmostofa\LaravelWhatsApp\Notifications\WhatsAppMessage;
class OrderShipped extends Notification
{
public function __construct(public Order $order) {}
public function via($notifiable): array
{
return ['mail', 'whatsapp'];
}
public function toWhatsApp($notifiable): WhatsAppMessage
{
return WhatsAppMessage::create("Your order #{$this->order->id} has shipped.");
}
}You can also list the channel class, Kstmostofa\LaravelWhatsApp\Notifications\WhatsAppChannel::class, instead of 'whatsapp'.
Message types
// Text
WhatsAppMessage::create('Hello');
// Approved template (always sent through the Cloud API)
WhatsAppMessage::create()->template('order_shipped', 'en_US', [
['type' => 'body', 'parameters' => [['type' => 'text', 'text' => '#42']]],
]);
// Media by URL. The body doubles as the caption unless you pass one.
WhatsAppMessage::create('Your invoice')->document('https://example.com/inv.pdf', 'invoice.pdf');
WhatsAppMessage::create()->image('https://example.com/photo.jpg', 'Caption');
WhatsAppMessage::create()->video('https://example.com/clip.mp4');
// Quote an earlier message (text and media; not templates)
WhatsAppMessage::create('Following up on this')->replyTo($messageId);
// Link previews for URLs in a Cloud text message
WhatsAppMessage::create('Track it: https://example.com/t/42')->previewUrl();Choosing the backend
Without an explicit choice, the backend follows the recipient, exactly like WhatsApp::send(): phone numbers go to the Cloud API, and IDs ending in @c.us, @g.us or @broadcast go to the Web sidecar. Templates always use the Cloud API.
WhatsAppMessage::create('Hi')->viaCloud(); // default phone_number_id
WhatsAppMessage::create('Hi')->viaCloud('123456789'); // a specific phone_number_id
WhatsAppMessage::create('Hi')->viaWeb(); // default Web session
WhatsAppMessage::create('Hi')->viaWeb('support'); // a specific Web sessionForcing a template through viaWeb() throws an InvalidArgumentException.
With several Cloud numbers configured, send from a named account:
WhatsAppMessage::create('Your ticket was answered')->fromAccount('support');Overriding the recipient
->to() replaces the notifiable's route for one message:
WhatsAppMessage::create('Your driver is here')->to($order->delivery_phone);On-demand notifications
No model needed:
Notification::route('whatsapp', '+966512345678')->notify(new OrderShipped($order));Queueing
Implement ShouldQueue on the notification as usual. Failures surface as CloudApiException or SidecarException, so Laravel's normal retry and failed() handling applies.
Testing
WhatsApp::fake() captures notification sends too. See Testing.