Symfony bundle for WasenderAPI – send WhatsApp messages, manage contacts, groups, sessions, and handle webhooks with Symfony best practices.
Requires PHP >= 7.3 | Compatible with Symfony 4.4, 5.x, 6.x, 7.x
composer require wasenderapi/wasenderapi-symfony
If your application does not use Symfony Flex, add the bundle to config/bundles.php:
return [
// ...
WasenderApi\SymfonyBundle\WasenderApiBundle::class => ['all' => true],
];
Create config/packages/wasenderapi.yaml:
wasenderapi:
api_key: '%env(WASENDERAPI_API_KEY)%'
personal_access_token: '%env(WASENDERAPI_PERSONAL_ACCESS_TOKEN)%'
base_url: 'https://www.wasenderapi.com/api'
webhook:
secret: '%env(WASENDERAPI_WEBHOOK_SECRET)%'
path: '/wasender/webhook'
signature_header: 'x-webhook-signature'
Add to your .env file:
WASENDERAPI_API_KEY=your_api_key_here
WASENDERAPI_PERSONAL_ACCESS_TOKEN=your_personal_token_here
WASENDERAPI_WEBHOOK_SECRET=your_webhook_secret_here
Add to config/routes.yaml:
wasenderapi_webhook:
resource: '@WasenderApiBundle/Resources/config/routing.xml'
use WasenderApi\SymfonyBundle\Client\WasenderApiClient;
class WhatsAppController
{
private $wasender;
public function __construct(WasenderApiClient $wasender)
{
$this->wasender = $wasender;
}
public function send()
{
$this->wasender->sendText('1234567890', 'Hello from Symfony!');
}
}
Useful for managing multiple sessions with different API keys:
use WasenderApi\SymfonyBundle\Client\WasenderApiClient;
$client = new WasenderApiClient('your_api_key_here');
$client->sendText('1234567890', 'Hello!');
All message methods support both direct parameters and DTOs. All return an associative array.
use WasenderApi\SymfonyBundle\DTO\SendTextMessageData;
$client->sendText('123', 'Hello!');
// or with DTO
$client->sendText(new SendTextMessageData('123', 'Hello!'));
use WasenderApi\SymfonyBundle\DTO\SendImageMessageData;
$client->sendImage('123', 'https://example.com/image.png', 'Caption');
// or
$client->sendImage(new SendImageMessageData('123', 'https://example.com/image.png', 'Caption'));
$client->sendVideo('123', 'https://example.com/video.mp4', 'Watch this');
$client->sendDocument('123', 'https://example.com/file.pdf', 'My caption', 'file.pdf');
$client->sendAudio('123', 'https://example.com/audio.mp3');
$client->sendSticker('123', 'https://example.com/sticker.webp');
$client->sendContact('123', 'John Doe', '+1234567890');
$client->sendLocation('123', 48.8566, 2.3522, 'Paris', '1 Rue de Rivoli');
$client->sendQuotedMessage('123', 42, 'Replying to your message');
$client->sendMessageWithMentions('group@g.us', 'Hello @user', ['user@s.whatsapp.net']);
$client->editMessage(123, 'Updated text');
$client->deleteMessage(123);
$client->getMessageInfo(123);
Use RetryConfig on send-message methods to automatically retry on HTTP 429:
use WasenderApi\SymfonyBundle\DTO\RetryConfig;
$retry = new RetryConfig(true, 3);
$client->sendText('123', 'Hello!', [], $retry);
$client->getContacts();
$client->getContactInfo('1234567890');
$client->getContactProfilePicture('1234567890');
$client->blockContact('1234567890');
$client->unblockContact('1234567890');
$client->checkIfOnWhatsapp('+1234567890');
$client->createGroup('My Group', ['user1@s.whatsapp.net']);
$client->getGroups();
$client->getGroupMetadata('group-jid');
$client->getGroupParticipants('group-jid');
$client->addGroupParticipants('group-jid', ['user@s.whatsapp.net']);
$client->removeGroupParticipants('group-jid', ['user@s.whatsapp.net']);
$client->updateGroupParticipants('group-jid', 'promote', ['user@s.whatsapp.net']);
$client->updateGroupSettings('group-jid', ['setting' => 'value']);
$client->getGroupInviteInfo('invite-code');
$client->leaveGroup('group-jid');
$client->acceptGroupInvite('invite-code');
$client->getGroupInviteLink('group-jid');
$client->getGroupProfilePicture('group-jid');
These endpoints require a personal access token.
$client->getAllWhatsAppSessions();
$client->createWhatsAppSession(['name' => 'My Session']);
$client->getWhatsAppSessionDetails(1);
$client->updateWhatsAppSession(1, ['name' => 'Renamed']);
$client->deleteWhatsAppSession(1);
$client->connectWhatsAppSession(1);
$client->getWhatsAppSessionQrCode(1);
$client->disconnectWhatsAppSession(1);
$client->regenerateApiKey(1);
$client->getSessionStatus('1');
$client->getSessionUserInfo();
// Upload from base64
$client->uploadMediaFile('data:image/png;base64,AAA...', 'image/png');
// Upload from file path
$client->uploadMediaFile('/path/to/image.png');
// Decrypt media
$client->decryptMediaFile($encryptedPayload);
$client->sendPresenceUpdate('user@s.whatsapp.net', 'composing');
$client->sendPresenceUpdate('user@s.whatsapp.net', 'recording', 2000);
The bundle automatically registers a webhook endpoint. When WasenderAPI sends a webhook, the controller verifies the signature and dispatches a Symfony event.
Create an event subscriber:
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use WasenderApi\SymfonyBundle\Event\MessagesUpserted;
use WasenderApi\SymfonyBundle\Event\MessageReceived;
use WasenderApi\SymfonyBundle\Event\CallReceived;
class WasenderEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
MessagesUpserted::class => 'onMessagesUpserted',
MessageReceived::class => 'onMessageReceived',
CallReceived::class => 'onCallReceived',
];
}
public function onMessagesUpserted(MessagesUpserted $event): void
{
$payload = $event->getPayload();
// Handle upserted messages
}
public function onMessageReceived(MessageReceived $event): void
{
$payload = $event->getPayload();
// Handle received message
}
public function onCallReceived(CallReceived $event): void
{
$payload = $event->getPayload();
// Handle incoming call
}
}
| Webhook type | Event class |
|---|---|
chats.upsert |
ChatsUpserted |
chats.update |
ChatsUpdated |
chats.delete |
ChatsDeleted |
contacts.upsert |
ContactsUpserted |
contacts.update |
ContactsUpdated |
groups.upsert |
GroupsUpserted |
groups.update |
GroupsUpdated |
group-participants.update |
GroupParticipantsUpdated |
messages.upsert |
MessagesUpserted |
messages.update |
MessagesUpdated |
messages.delete |
MessagesDeleted |
messages.reaction |
MessagesReaction |
message-receipt.update |
MessageReceiptUpdated |
message.sent |
MessageSent |
messages.received |
MessageReceived |
messages-personal.received |
PersonalMessageReceived |
messages-group.received |
GroupMessageReceived |
messages-newsletter.received |
NewsletterMessageReceived |
session.status |
SessionStatus |
qrcode.updated |
QrCodeUpdated |
call.received |
CallReceived |
poll.results |
PollResults |
Unmapped event types dispatch WasenderWebhookEvent with getEventName() and getPayload().
All API errors throw WasenderApiException:
use WasenderApi\SymfonyBundle\Exception\WasenderApiException;
try {
$client->sendText('123', 'Hello');
} catch (WasenderApiException $e) {
$e->getMessage(); // Error description
$e->getCode(); // HTTP status code
$e->getResponse(); // Parsed JSON response (array or null)
}
composer install
vendor/bin/phpunit
MIT
How can I help you explore Laravel packages today?