Skip to content

Lightweight PHP wrapper for Meta's WhatsApp Cloud API. Zero dependencies.

License

Notifications You must be signed in to change notification settings

renzojohnson/whatsapp-cloud-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WhatsApp Cloud API for PHP

Latest Version PHP Version License

Lightweight PHP wrapper for Meta's WhatsApp Cloud API. Zero dependencies.

Send text, template, image, document, video, audio, location, contact, and sticker messages. Receive and verify webhooks.

Author: Renzo Johnson

Requirements

  • PHP 8.4+
  • ext-curl
  • ext-json

Installation

composer require renzojohnson/whatsapp-cloud-api

Quick Start

use RenzoJohnson\WhatsApp\WhatsApp;

$wa = new WhatsApp('YOUR_PHONE_NUMBER_ID', 'YOUR_ACCESS_TOKEN');

// Send a text message
$wa->sendText('14155551234', 'Hello from PHP!');

Sending Messages

Text

$wa->sendText('14155551234', 'Hello World');

// With link preview
$wa->sendText('14155551234', 'Check https://example.com', previewUrl: true);

Template

// Simple template (no parameters)
$wa->sendTemplate('14155551234', 'hello_world', 'en_US');

// Template with parameters
$wa->sendTemplate('14155551234', 'order_update', 'en_US', [
    [
        'type' => 'body',
        'parameters' => [
            ['type' => 'text', 'text' => 'John'],
            ['type' => 'text', 'text' => 'ORD-12345'],
        ],
    ],
]);

Image

// By URL
$wa->sendImage('14155551234', link: 'https://example.com/photo.jpg', caption: 'A photo');

// By media ID (uploaded via uploadMedia)
$wa->sendImage('14155551234', mediaId: 'media_123');

Document

$wa->sendDocument(
    '14155551234',
    link: 'https://example.com/invoice.pdf',
    caption: 'Your invoice',
    filename: 'invoice-2026.pdf',
);

Video

$wa->sendVideo('14155551234', link: 'https://example.com/clip.mp4', caption: 'Watch this');

Audio

$wa->sendAudio('14155551234', link: 'https://example.com/audio.mp3');

Location

$wa->sendLocation(
    '14155551234',
    latitude: 28.5383,
    longitude: -81.3792,
    name: 'Orlando Office',
    address: '123 Main St, Orlando, FL',
);

Contact

$wa->sendContact(
    '14155551234',
    name: ['first_name' => 'Jane', 'last_name' => 'Doe'],
    phones: [['phone' => '+14155559999', 'type' => 'CELL']],
);

Sticker

$wa->sendSticker('14155551234', link: 'https://example.com/sticker.webp');

Media

Upload

$response = $wa->uploadMedia('/path/to/file.jpg', 'image/jpeg');
$mediaId = $response['id'];

Get Media URL

$media = $wa->getMedia('media_123');
$url = $media['url'];

Delete

$wa->deleteMedia('media_123');

Mark as Read

$wa->markAsRead('wamid.abc123');

Webhooks

Verification (GET request from Meta)

use RenzoJohnson\WhatsApp\Webhook\Listener;

// Responds to Meta's verification challenge
Listener::verify('YOUR_VERIFY_TOKEN');

Receiving Messages (POST from Meta)

use RenzoJohnson\WhatsApp\Webhook\Listener;
use RenzoJohnson\WhatsApp\Webhook\Notification;

Listener::listen('YOUR_APP_SECRET', function (Notification $notification, array $raw) {
    if ($notification->isText()) {
        echo 'From: ' . $notification->from . "\n";
        echo 'Text: ' . $notification->text . "\n";
    }

    if ($notification->isImage()) {
        echo 'Image ID: ' . $notification->image['id'] . "\n";
    }
});

The listener validates the X-Hub-Signature-256 header using HMAC-SHA256 before processing. Invalid signatures return 401.

Notification Properties

Property Type Description
from string Sender's phone number
type string Message type (text, image, document, etc.)
timestamp string Unix timestamp
messageId ?string WhatsApp message ID
text ?string Text body (when type is text)
image ?array Image data (id, mime_type, sha256)
document ?array Document data
video ?array Video data
audio ?array Audio data
location ?array Location data (latitude, longitude)
sticker ?array Sticker data
contacts ?array Contact cards
interactive ?array Interactive response data
context ?array Reply context (quoted message)

Type Checks

$notification->isText();
$notification->isImage();
$notification->isDocument();
$notification->isVideo();
$notification->isAudio();
$notification->isLocation();
$notification->isSticker();
$notification->isInteractive();

Error Handling

use RenzoJohnson\WhatsApp\Exception\AuthenticationException;
use RenzoJohnson\WhatsApp\Exception\RateLimitException;
use RenzoJohnson\WhatsApp\Exception\WhatsAppException;

try {
    $wa->sendText('14155551234', 'Hello');
} catch (AuthenticationException $e) {
    // Invalid or expired access token (401)
} catch (RateLimitException $e) {
    // Too many requests (429)
} catch (WhatsAppException $e) {
    // Other API errors (400, 500, etc.)
    $errorData = $e->getErrorData();
}

Testing

composer install
vendor/bin/phpunit

Links

License

MIT License. Copyright (c) 2026 Renzo Johnson.

About

Lightweight PHP wrapper for Meta's WhatsApp Cloud API. Zero dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages