PHP
WhatsApp API for PHP
wasaas/wasaas-php is a small, framework-agnostic client for the Wasaas REST API. It needs PHP ^8.1 with ext-json and nothing else — no Guzzle, no queue, no Meta Business account. Drop it into plain PHP, Symfony, WordPress or a legacy codebase.
Install
Published on Packagist as wasaas/wasaas-php (version 1.0.0).
composer require wasaas/wasaas-phpAuthenticate
The constructor takes your API key and rejects a key that is empty or not prefixed wsa_, throwing WasaasException immediately rather than at request time.
<?php
use Wasaas\WasaasClient;
$client = new WasaasClient(getenv('WASAAS_API_KEY'));
// Second argument overrides the base URL; defaults to https://wasaas.org
// $client = new WasaasClient($apiKey, 'https://wasaas.org');Send a message
Every send needs the session ID of a connected number and a recipient in international format without a leading +. Responses come back as plain associative arrays.
$result = $client->messages->sendText(
sessionId: 'customer-5-1',
to: '966501234567',
message: 'Your order has shipped.',
);
// ['success' => true, 'to' => '966501234567', 'status' => 'sent']Images and documents
Images take a URL; documents take base64 plus a filename and MIME type, so a PDF you have just generated can go straight out without being written to disk.
$client->messages->sendImage(
sessionId: 'customer-5-1',
to: '966501234567',
imageUrl: 'https://example.com/receipt.png',
caption: 'Your receipt', // optional
);
$client->messages->sendDocument(
sessionId: 'customer-5-1',
to: '966501234567',
base64: base64_encode($pdfBytes),
filename: 'invoice-1042.pdf',
mime: 'application/pdf',
);Text, images and documents are the supported types. Audio, location pins and interactive buttons are not available.
Sessions and number checks
// Connected numbers, with their session IDs and status
$sessions = $client->sessions->list();
// Does this number have WhatsApp?
$check = $client->numbers->validate('customer-5-1', '966501234567');
if ($check['has_whatsapp'] === true) {
// safe to send
}Handling errors
Failed requests throw WasaasApiException, which exposes getStatusCode() and getDetail(). It extends WasaasException, itself a RuntimeException — so an existing global handler will already catch it.
use Wasaas\Exceptions\WasaasApiException;
try {
$client->messages->sendText($sessionId, $to, $message);
} catch (WasaasApiException $e) {
// 401 invalid key · 404 session not found · 429 quota exceeded
error_log($e->getStatusCode() . ' ' . $e->getMessage() . ' ' . $e->getDetail());
}A 429 means the monthly message quota is spent; WhatsApp API pricing lists the allowance for each plan.
Using Laravel?
The same Composer package ships a Laravel service provider, a publishable config file and a container binding. See the WhatsApp API for Laravel — you do not install a second package.
Where to go next
- WhatsApp REST API documentation — the endpoints, fields and error codes behind this client
- WhatsApp API for Laravel — config, env vars and container usage for Laravel apps
- WhatsApp API pricing — message, session and API-call allowances per plan
- WhatsApp bulk messaging API — one call to many recipients, with pacing handled server-side