craftivelabs / laravel-syncraft
Laravel package for Syncraft WhatsApp Gateway API
Requires
- php: >=7.4
- guzzlehttp/guzzle: ^7.0
- illuminate/support: ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0
Requires (Dev)
- mockery/mockery: ^1.0
- orchestra/testbench: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0
- phpunit/phpunit: ^9.0 || ^10.0
This package is not auto-updated.
Last update: 2026-07-26 13:31:49 UTC
README
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.