laravel-syncraft maintained by craftivelabs
laravel-syncraft
Laravel package for Syncraft WhatsApp Gateway API.
Compatible with PHP 7.4 through PHP 8.4+ and supports Laravel 8, 9, 10, 11, and 12+.
Features
- ⚡ Full Syncraft API support: Connections (QR & Phone Pairing), Messages (Text, Media, Group, Channel), Broadcasts, Group/Channel metadata, and Number checks.
- 🚀 Laravel Facade & Auto-Discovery: Clean syntax via
Syncraft::sendText(...). - 💉 Dependency Injection Ready: Auto-wired
SyncraftClientsingleton in Laravel's container. - 🔔 Event-driven Webhooks: Built-in
WebhookControllerthat automatically dispatches native Laravel events (MessageReceived,MessageSent,DeviceConnected,DeviceDisconnected). - 🛡️ Typed DTOs & Custom Exceptions: Strongly typed responses and exception handling.
Installation
Install the package via Composer:
composer require craftivelabs/laravel-syncraft
The package will automatically register its Service Provider (SyncraftServiceProvider) and Facade (Syncraft).
Publish Configuration
Publish the syncraft.php configuration file:
php artisan vendor:publish --tag=syncraft-config
This creates config/syncraft.php in your application:
return [
'api_key' => env('SYNCRAFT_API_KEY', ''),
'base_url' => env('SYNCRAFT_BASE_URL', 'https://api.getsyncraft.com/v1/public'),
];
Environment Variables
Add your Syncraft API key to your .env file:
SYNCRAFT_API_KEY=your_api_key_here
SYNCRAFT_BASE_URL=https://api.getsyncraft.com/v1/public
Usage
💡 For full copy-pasteable examples of every single Syncraft API function, see EXAMPLES.md.
Using the Facade
use CraftiveLabs\Syncraft\Laravel\Facades\Syncraft;
// Send plain text message
$result = Syncraft::sendText('6281234567890', 'Hello from Laravel!');
echo $result->messageId;
// Send media message (file upload)
$result = Syncraft::sendMedia(
'6281234567890',
'image',
'Check out this photo!',
storage_path('app/public/photo.jpg')
);
// Send media message with custom filename
$result = Syncraft::sendMedia(
'6281234567890',
'document',
'Invoice #1001',
storage_path('app/public/invoice.pdf'),
'invoice-1001.pdf'
);
// Send message to WhatsApp Group
$result = Syncraft::sendGroupText('1203632123456789@g.us', 'Hello group!');
// Send message to WhatsApp Newsletter Channel
$result = Syncraft::sendChannelText('12036302394829302@newsletter', 'New announcement!');
Using Dependency Injection
namespace App\Http\Controllers;
use CraftiveLabs\Syncraft\SyncraftClient;
class NotificationController extends Controller
{
public function notify(SyncraftClient $syncraft)
{
$status = $syncraft->getStatus();
if ($status->isConnected) {
$syncraft->sendText('6281234567890', 'System status normal');
}
}
}
Connection & Session Management
use CraftiveLabs\Syncraft\Laravel\Facades\Syncraft;
// Get QR Code for scanning
$qr = Syncraft::connectQr();
echo $qr->qrCode; // base64 PNG data string
// Get 8-character pairing code
$code = Syncraft::connectPhone('6281234567890');
echo $code->pairingCode; // e.g. ABCD-1234
// Temporary disconnect
Syncraft::disconnect();
// Permanent logout
Syncraft::logout();
// Get status
$status = Syncraft::getStatus();
echo $status->isConnected ? 'Connected' : 'Disconnected';
Broadcast Campaigns
use CraftiveLabs\Syncraft\Laravel\Facades\Syncraft;
// Create broadcast campaign
$broadcast = Syncraft::createBroadcast('Promo July', 'text', 'Hello valued customer!', [
['phone_number' => '62812345678'],
['phone_number' => '62898765432', 'message' => 'Custom message for Budi!'],
]);
echo $broadcast->id; // e.g. 42
// Get campaign status
$detail = Syncraft::getBroadcast(42);
echo "Sent: {$detail->sentCount}, Failed: {$detail->failedCount}";
// Cancel broadcast campaign
Syncraft::cancelBroadcast(42);
Metadata & Number Check
use CraftiveLabs\Syncraft\Laravel\Facades\Syncraft;
// Check single WhatsApp number
$check = Syncraft::checkNumber('6281234567890');
if ($check->isRegistered) {
echo "Registered JID: {$check->jid}";
}
// Bulk check WhatsApp numbers
$bulk = Syncraft::checkNumbers(['6281234567890', '6289876543210']);
// Get joined groups
$groups = Syncraft::getGroups();
// Get newsletter channels
$channels = Syncraft::getChannels();
Webhook Integration
Syncraft sends HTTP callbacks for events: message.received, message.sent, device.connected, and device.disconnected.
Option A: Native Laravel Webhook Controller & Events
Register the built-in route in your routes/api.php or routes/web.php:
use CraftiveLabs\Syncraft\Laravel\Controllers\WebhookController;
Route::post('/syncraft/webhook', WebhookController::class)->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);
WebhookController automatically parses incoming webhooks and fires native Laravel events:
CraftiveLabs\Syncraft\Laravel\Events\MessageReceivedCraftiveLabs\Syncraft\Laravel\Events\MessageSentCraftiveLabs\Syncraft\Laravel\Events\DeviceConnectedCraftiveLabs\Syncraft\Laravel\Events\DeviceDisconnectedCraftiveLabs\Syncraft\Laravel\Events\WebhookReceived
Register Event Listener in EventServiceProvider
use CraftiveLabs\Syncraft\Laravel\Events\MessageReceived;
use App\Listeners\HandleIncomingWhatsAppMessage;
protected $listen = [
MessageReceived::class => [
HandleIncomingWhatsAppMessage::class,
],
];
Event Listener Implementation
namespace App\Listeners;
use CraftiveLabs\Syncraft\Laravel\Events\MessageReceived;
use Illuminate\Support\Facades\Log;
class HandleIncomingWhatsAppMessage
{
public function handle(MessageReceived $event): void
{
$message = $event->message;
Log::info("Received WhatsApp message from {$message->from}: {$message->content}");
}
}
Option B: Custom Class with Handler Interface
If you prefer custom webhook routing without Laravel Events:
use CraftiveLabs\Syncraft\Webhook\Handler;
use CraftiveLabs\Syncraft\Webhook\WebhookTrait;
class WhatsAppWebhookHandler implements Handler
{
use WebhookTrait;
public function handle(array $payload): void
{
$event = $this->parseEvent($payload);
if ($event->isMessageReceived()) {
$msg = $event->toMessageData();
// Process message...
}
}
}
Response DTO Reference
| DTO | Description | Properties |
|---|---|---|
QRCode |
Base64 QR code string | qrCode |
PairingCode |
8-character phone pairing code | pairingCode |
ConnectionStatus |
Connection status response | deviceId, isConnected, jid, status |
SentMessage |
Sent message confirmation | messageId, status, to |
BroadcastResult |
Created broadcast campaign summary | id, name, status, totalCount, createdAt |
BroadcastDetail |
Full broadcast campaign details | id, name, status, totalCount, sentCount, failedCount, recipients |
GroupList |
List of joined groups | groups (array of Group), total |
Group |
Group metadata | jid, name, topic, ownerJid, isLocked, isAnnounce, participants |
ChannelList |
List of channels | channels (array of Channel), total |
Channel |
Channel metadata | jid, name, description |
NumberCheck |
Number registration check | isRegistered, jid |
BulkNumberCheck |
Bulk number registration check | results (array of NumberCheck) |
WebhookEvent |
Raw webhook callback event | event, deviceId, timestamp, data |
MessageData |
Webhook message payload | messageId, from, messageType, content, timestamp, isGroup, isFromMe |
DeviceData |
Webhook device state payload | jid, status |
Requirements
- PHP:
>= 7.4(Compatible with PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4+) - Laravel:
^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 - Guzzle:
^7.0
Testing
Run tests with PHPUnit:
vendor/bin/phpunit
License
The MIT License (MIT). See LICENSE for details.