PHPackages                             jordanmiguel/laravel-whatsapp-wuz - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. jordanmiguel/laravel-whatsapp-wuz

ActiveLibrary

jordanmiguel/laravel-whatsapp-wuz
=================================

Laravel package for WhatsApp device management via WuzAPI with multi-owner support

v0.0.2(2mo ago)0724↑105%MITPHPPHP ^8.2

Since Feb 25Pushed 2mo agoCompare

[ Source](https://github.com/jordanmiguel/laravel-whatsapp-wuz)[ Packagist](https://packagist.org/packages/jordanmiguel/laravel-whatsapp-wuz)[ Docs](https://github.com/jordanmiguel/laravel-whatsapp-wuz)[ RSS](/packages/jordanmiguel-laravel-whatsapp-wuz/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (9)Versions (3)Used By (0)

Laravel WhatsApp Wuz
====================

[](#laravel-whatsapp-wuz)

[![Latest Version on Packagist](https://camo.githubusercontent.com/0c724c50a2b4541c6c692db3ac486949bc4f8322246be7c978f29a3da1e3760f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6f7264616e6d696775656c2f6c61726176656c2d77686174736170702d77757a2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jordanmiguel/laravel-whatsapp-wuz)[![Total Downloads](https://camo.githubusercontent.com/26f16cf8c9b3e786ee13fe45d39c2b849795e69b75a5dff9bdb3e8d01b621bd0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a6f7264616e6d696775656c2f6c61726176656c2d77686174736170702d77757a2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jordanmiguel/laravel-whatsapp-wuz)[![License](https://camo.githubusercontent.com/5f0fd82e595e7fb96d26ff0719c7548583d5d509150db16b58cad1af8d45a162/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6a6f7264616e6d696775656c2f6c61726176656c2d77686174736170702d77757a2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jordanmiguel/laravel-whatsapp-wuz)[![Buy me a coffee](https://camo.githubusercontent.com/a9881d124480ce2b0be74c07d49ac8994ab61ff2b16ff44238db5a998741e210/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646f6e6174652d50617950616c2d626c75652e7376673f7374796c653d666c61742d737175617265)](https://www.paypal.com/donate/?hosted_button_id=6PAXAFGESHQDY)

A Laravel package for managing WhatsApp devices through [WuzAPI](https://github.com/asternic/wuzapi). Connect multiple WhatsApp numbers to your application with multi-owner, multi-device support, Laravel notifications, and automatic webhook handling.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Quick Start](#quick-start)
- [Core Concepts](#core-concepts)
- [Usage](#usage)
- [Notification Channel](#notification-channel)
- [Webhooks &amp; Events](#webhooks--events)
- [Multi-Device Management](#multi-device-management)
- [Facade](#facade)
- [Testing](#testing)
- [License](#license)

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11 or 12
- A running [WuzAPI](https://github.com/asternic/wuzapi) instance

Installation
------------

[](#installation)

```
composer require jordanmiguel/laravel-whatsapp-wuz
```

Publish the config and migrations, then run them:

```
php artisan vendor:publish --tag="laravel-whatsapp-wuz-config"
php artisan vendor:publish --tag="laravel-whatsapp-wuz-migrations"
php artisan migrate
```

Configuration
-------------

[](#configuration)

Add these variables to your `.env` file:

```
WUZ_ENABLED=true
WUZ_API_URL=http://localhost:8080
WUZ_ADMIN_TOKEN=your-admin-token
WUZ_DEFAULT_COUNTRY_CODE=55
WUZ_DOWNLOAD_MEDIA=false
WUZ_DEBUG=false
WUZ_DEBUG_TO=
```

VariableDescription`WUZ_ENABLED`Enable or disable the package globally`WUZ_API_URL`URL of your WuzAPI instance`WUZ_ADMIN_TOKEN`Admin token for managing devices via the WuzAPI`WUZ_DEFAULT_COUNTRY_CODE`Default country code for phone number normalization`WUZ_DOWNLOAD_MEDIA`Automatically download media from incoming messages`WUZ_DEBUG`Enable debug mode — redirects or skips all outgoing messages`WUZ_DEBUG_TO`Phone number to redirect all messages to (leave empty to log-only)See `config/wuz.php` for additional options like custom table names, webhook path, and middleware.

Debug Mode
----------

[](#debug-mode)

When `WUZ_DEBUG=true`, all outgoing messages are intercepted before sending. This lets you test the full pipeline in development/staging without messaging real users.

- **With `WUZ_DEBUG_TO` set**: All messages are redirected to that phone number, going through the same validation and sending pipeline.
- **With `WUZ_DEBUG_TO` empty**: Messages are logged via `Log::info()` and skipped entirely — no API call, no database record.

Quick Start
-----------

[](#quick-start)

**1. Add the trait and interface to your owner model** (any Eloquent model that owns WhatsApp devices):

```
use JordanMiguel\Wuz\Contracts\HasWuzDevices as HasWuzDevicesContract;
use JordanMiguel\Wuz\Traits\HasWuzDevices;

class Clinic extends Model implements HasWuzDevicesContract
{
    use HasWuzDevices;
}
```

**2. Create a device:**

```
use JordanMiguel\Wuz\Actions\StoreDeviceAction;
use JordanMiguel\Wuz\Data\StoreDeviceData;

$device = app(StoreDeviceAction::class)->handle(
    owner: $clinic,
    data: new StoreDeviceData(name: 'Reception Phone'),
    createdBy: auth()->id(),
);
```

**3. Get the QR code and scan it with WhatsApp:**

```
use JordanMiguel\Wuz\Actions\GetDeviceStatusAction;

$status = app(GetDeviceStatusAction::class)->handle($device);
// $status->status   => 'connected' | 'qr' | 'disconnected'
// $status->qr_code  => base64 QR data (when status is 'qr')
```

**4. Send a message:**

```
use JordanMiguel\Wuz\Actions\SendMessageAction;
use JordanMiguel\Wuz\Data\SendMessageData;

app(SendMessageAction::class)->handle($device, new SendMessageData(
    phone: '5511999999999',
    type: 'text',
    message: 'Hello from Laravel!',
));
```

Core Concepts
-------------

[](#core-concepts)

### Owners &amp; Devices

[](#owners--devices)

Any Eloquent model can own WhatsApp devices by implementing the `HasWuzDevices` interface. This uses a polymorphic relationship, so a `Clinic`, `Organization`, `Team`, or `User` model can all own devices independently.

Each owner can have multiple devices. One device per owner is always marked as the **default** — this is the device used when sending notifications.

### Device Lifecycle

[](#device-lifecycle)

```
Create → Connect → Scan QR → Connected → Send/Receive Messages

```

1. **Create** — Registers a new device with WuzAPI and stores it in your database
2. **Connect** — Initiates the connection (happens automatically on create)
3. **Scan QR** — Use `GetDeviceStatusAction` to retrieve the QR code for the user to scan with their WhatsApp mobile app
4. **Connected** — Once scanned, the device is connected and ready to send/receive messages
5. **Send/Receive** — Send messages via `SendMessageAction`, receive via webhooks

Usage
-----

[](#usage)

### Managing Devices

[](#managing-devices)

#### Create a Device

[](#create-a-device)

```
use JordanMiguel\Wuz\Actions\StoreDeviceAction;
use JordanMiguel\Wuz\Data\StoreDeviceData;

$device = app(StoreDeviceAction::class)->handle(
    owner: $clinic,
    data: new StoreDeviceData(name: 'Reception Phone'),
    createdBy: auth()->id(),
);
```

The first device per owner is automatically set as default.

#### Check Device Status / Get QR Code

[](#check-device-status--get-qr-code)

```
use JordanMiguel\Wuz\Actions\GetDeviceStatusAction;

$status = app(GetDeviceStatusAction::class)->handle($device);
// $status->status   => 'connected' | 'qr' | 'disconnected'
// $status->qr_code  => base64 QR data (when status is 'qr')
```

#### Disconnect a Device

[](#disconnect-a-device)

```
use JordanMiguel\Wuz\Actions\DisconnectDeviceAction;

app(DisconnectDeviceAction::class)->handle($device);
```

#### Delete a Device

[](#delete-a-device)

```
use JordanMiguel\Wuz\Actions\DeleteDeviceAction;

app(DeleteDeviceAction::class)->handle($device);
```

When you delete the default device, the next oldest device is automatically promoted to default.

### Sending Messages

[](#sending-messages)

```
use JordanMiguel\Wuz\Actions\SendMessageAction;
use JordanMiguel\Wuz\Data\SendMessageData;

$message = app(SendMessageAction::class)->handle($device, new SendMessageData(
    phone: '5511999999999',
    type: 'text',
    message: 'Hello from Laravel!',
));
```

Supported message types: `text`, `image`, `video`, `document`, `button`.

Notification Channel
--------------------

[](#notification-channel)

Send WhatsApp messages through Laravel's notification system.

### Define a Notification

[](#define-a-notification)

```
use JordanMiguel\Wuz\Notifications\WuzMessage;

class AppointmentReminder extends Notification
{
    public function via($notifiable): array
    {
        return ['wuz'];
    }

    public function toWuz($notifiable): WuzMessage
    {
        return WuzMessage::create('Your appointment is tomorrow at 10am.');
    }
}
```

### Set Up the Notifiable Model

[](#set-up-the-notifiable-model)

The notifiable model needs the `InteractsWithWuz` trait to resolve which device should send the message:

```
use JordanMiguel\Wuz\Traits\InteractsWithWuz;

class ClientProfile extends Model
{
    use InteractsWithWuz, Notifiable;

    public function routeNotificationForWhatsapp(): ?string
    {
        return $this->phone;
    }

    public function resolveWuzOwner(): mixed
    {
        return $this->clinic;
    }
}
```

The channel resolves the device by calling `resolveWuzOwner()` on the notifiable, then uses that owner's default device to send the message.

Webhooks &amp; Events
---------------------

[](#webhooks--events)

Incoming WhatsApp events are received at `POST /api/wuz/webhook/{token}` (configurable in `config/wuz.php`).

### Handled Events

[](#handled-events)

Webhook EventWhat HappensEvent Dispatched**Message**Stores the incoming message in `wuz_device_messages``MessageReceived`**Disconnected**Updates the device's connected state`DeviceDisconnected`**LoggedOut**Clears the device's JID and marks as disconnected`DeviceDisconnected`All callbacks also dispatch a `WebhookReceived` event and are logged in the `wuz_callback_logs` table.

### Listening to Events

[](#listening-to-events)

Register listeners in your `EventServiceProvider` or use Laravel's event discovery:

```
use JordanMiguel\Wuz\Events\MessageReceived;

class HandleIncomingMessage
{
    public function handle(MessageReceived $event): void
    {
        $device = $event->device;
        $message = $event->message;
        // Process incoming message...
    }
}
```

Multi-Device Management
-----------------------

[](#multi-device-management)

Each owner can have multiple WhatsApp devices. The package enforces that exactly one device per owner is the default.

RuleBehaviorMultiple devices per ownerSupported via polymorphic relationshipOne default per ownerEnforced via `is_default` flagFirst device auto-defaultHandled by `StoreDeviceAction`Delete promotes nextHandled by `DeleteDeviceAction`Explicit switch`$owner->setDefaultWuzDevice($device)`Notification routing`WuzChannel` uses the owner's default deviceFacade
------

[](#facade)

```
use JordanMiguel\Wuz\Facades\Wuz;

$service = Wuz::make($device); // device-scoped WuzService
$admin   = Wuz::admin();       // admin-scoped WuzService
```

Testing
-------

[](#testing)

Mock the WuzAPI in your application tests using Laravel's HTTP fakes:

```
Http::fake([
    '*/session/status' => Http::response(['data' => ['loggedIn' => true]], 200),
    '*/chat/send/text' => Http::response(['data' => ['sent' => true]], 200),
]);
```

Run the package tests:

```
composer test
```

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance84

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

83d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8248858?v=4)[Jordan Miguel](/maintainers/JordanMiguel)[@jordanmiguel](https://github.com/jordanmiguel)

---

Top Contributors

[![jordanmiguel](https://avatars.githubusercontent.com/u/8248858?v=4)](https://github.com/jordanmiguel "jordanmiguel (12 commits)")

---

Tags

laravelnotificationswhatsappmulti-ownerwuzapi

###  Code Quality

TestsPest

Static AnalysisPHPStan

### Embed Badge

![Health badge](/badges/jordanmiguel-laravel-whatsapp-wuz/health.svg)

```
[![Health](https://phpackages.com/badges/jordanmiguel-laravel-whatsapp-wuz/health.svg)](https://phpackages.com/packages/jordanmiguel-laravel-whatsapp-wuz)
```

###  Alternatives

[spatie/laravel-prometheus

Export Laravel metrics to Prometheus

2651.3M6](/packages/spatie-laravel-prometheus)[ralphjsmit/laravel-glide

Auto-magically generate responsive images from static image files.

4719.6k5](/packages/ralphjsmit-laravel-glide)[simplestats-io/laravel-client

Client for SimpleStats!

4515.5k](/packages/simplestats-io-laravel-client)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)[musahmusah/laravel-multipayment-gateways

A Laravel Package that makes implementation of multiple payment Gateways endpoints and webhooks seamless

852.2k1](/packages/musahmusah-laravel-multipayment-gateways)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
