Skip to main content

Prerequisites

Before configuring WhatsApp integration, you need:
  • A Meta Business Account
  • WhatsApp Business API access
  • A verified phone number registered with WhatsApp Business
  • A publicly accessible webhook URL (HTTPS required)

Required Credentials

You’ll need the following credentials from Meta for Developers:
1

Phone Number ID

The WhatsApp Business Phone Number ID from your Meta Business account.
Example: 123456789012345
2

Access Token

A permanent access token for the WhatsApp Business API.
Never share your access token. It provides full access to your WhatsApp Business account.
3

App Secret

Your Meta app secret used for webhook signature verification.
4

Verify Token

A custom token you create for webhook verification (can be any string).

Configuration Options

Use the admin dashboard to configure WhatsApp credentials. They’ll be encrypted and stored securely.
src/Services/CredentialService.php
$credentialService->saveWhatsAppCredentials([
    'phone_number_id' => 'YOUR_PHONE_NUMBER_ID',
    'access_token' => 'YOUR_ACCESS_TOKEN',
    'app_secret' => 'YOUR_APP_SECRET',
    'verify_token' => 'YOUR_VERIFY_TOKEN'
]);

Option 2: Environment Variables

Add these variables to your .env file:
.env
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id
WHATSAPP_ACCESS_TOKEN=your_access_token
WHATSAPP_APP_SECRET=your_app_secret
WHATSAPP_VERIFY_TOKEN=your_custom_verify_token

Configuration File

The configuration is loaded from config/config.php:
config/config.php
'whatsapp' => [
    'access_token' => getenv('WHATSAPP_ACCESS_TOKEN') ?: '',
    'phone_number_id' => getenv('WHATSAPP_PHONE_NUMBER_ID') ?: '',
    'verify_token' => getenv('WHATSAPP_VERIFY_TOKEN') ?: 'your_verify_token_here',
    'app_secret' => getenv('WHATSAPP_APP_SECRET') ?: '',
    'api_version' => 'v18.0',
    'base_url' => 'https://graph.facebook.com'
],

Webhook Configuration

Webhook URL Setup

1

Get Your Webhook URL

Your webhook URL should point to the webhook.php file:
https://yourdomain.com/webhook.php
The URL must be publicly accessible and use HTTPS.
2

Configure in Meta Dashboard

  1. Go to your Meta for Developers dashboard
  2. Select your app
  3. Navigate to WhatsApp > Configuration
  4. Add your webhook URL and verify token
3

Subscribe to Webhook Events

Subscribe to the messages webhook event to receive incoming messages.

Webhook Verification

The webhook implements the verification challenge required by Meta:
webhook.php
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    $mode = $_GET['hub_mode'] ?? '';
    $token = $_GET['hub_verify_token'] ?? '';
    $challenge = $_GET['hub_challenge'] ?? '';
    
    if ($credentialService && $credentialService->hasWhatsAppCredentials()) {
        $waCreds = $credentialService->getWhatsAppCredentials();
        $verifyToken = $waCreds['verify_token'];
    } else {
        $verifyToken = Config::get('whatsapp.verify_token');
    }
    
    if ($mode === 'subscribe' && $token === $verifyToken) {
        echo $challenge;
        http_response_code(200);
        exit;
    }
    
    http_response_code(403);
    exit;
}

Webhook Security

The webhook validates incoming requests using HMAC-SHA256 signature verification:
webhook.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $rawBody = file_get_contents('php://input');
    
    if ($credentialService && $credentialService->hasWhatsAppCredentials()) {
        $waCreds = $credentialService->getWhatsAppCredentials();
        $appSecret = $waCreds['app_secret'];
    } else {
        $appSecret = Config::get('whatsapp.app_secret');
    }
    
    if ($appSecret) {
        $signature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';
        $expected = 'sha256=' . hash_hmac('sha256', $rawBody, $appSecret);
        
        if (!hash_equals($expected, $signature)) {
            http_response_code(401);
            exit('Unauthorized');
        }
    }
}
If you don’t configure an app_secret, webhook signature validation will be skipped. This is a security risk and should only be used for testing.

WhatsApp Service API

The WhatsAppService class handles all WhatsApp Business API interactions:

Sending Messages

src/Services/WhatsAppService.php
$whatsapp = new WhatsAppService(
    $accessToken,
    $phoneNumberId,
    'v18.0',
    $logger
);

// Send a text message
$messageId = $whatsapp->sendMessage($phoneNumber, 'Hello from the bot!');

Downloading Media

// Download audio, image, or other media
$mediaContent = $whatsapp->downloadMedia($mediaId);

// Save to file
file_put_contents('/path/to/file.ogg', $mediaContent);

Marking Messages as Read

$whatsapp->markAsRead($messageId);

Parsing Webhook Payload

$payload = json_decode($rawBody, true);
$messageData = $whatsapp->parseWebhookPayload($payload);

// Returns:
[
    'from' => '1234567890',
    'message_id' => 'wamid.XXX',
    'text' => 'User message',
    'type' => 'text',
    'contact_name' => 'John Doe',
    'timestamp' => 1234567890
]

API Configuration

The WhatsApp service uses the Meta Graph API:
src/Services/WhatsAppService.php
public function __construct($accessToken, $phoneNumberId, $apiVersion, Logger $logger)
{
    $this->accessToken = $accessToken;
    $this->phoneNumberId = $phoneNumberId;
    $this->apiVersion = $apiVersion;
    $this->logger = $logger;

    $this->client = new Client([
        'base_uri' => 'https://graph.facebook.com/' . $this->apiVersion . '/',
        'timeout' => 30,
        'verify' => false
    ]);
}
The default API version is v18.0. Update this in config/config.php if you need a different version.

Message Types Supported

The webhook handles different message types:

Text Messages

{
  "type": "text",
  "text": "User's text message"
}

Audio Messages

{
  "type": "audio",
  "audio_id": "media_id_here"
}
Audio messages are automatically transcribed using OpenAI’s Whisper API in AI mode. In classic mode, users are asked to send text instead.

Unsupported Types

These message types return a friendly error:
  • Images
  • Documents
  • Videos
  • Stickers
  • Contacts
  • Locations

Testing Your Configuration

1

Test Webhook Verification

Meta will send a GET request to verify your webhook. Check your server logs to confirm it’s working.
2

Send a Test Message

Send a message to your WhatsApp Business number and verify it’s received by the webhook.
3

Check Response

The bot should respond with its configured greeting message.
4

Monitor Logs

Check the logs in the logs/ directory for any errors:
tail -f logs/app.log

Troubleshooting

  • Ensure your verify_token matches what you configured in Meta
  • Check that your webhook URL is publicly accessible
  • Verify HTTPS is properly configured
  • Check webhook subscription is active in Meta dashboard
  • Verify the messages event is subscribed
  • Check server logs for errors
  • Ensure your access token hasn’t expired
  • Verify your access_token is valid
  • Check your phone_number_id is correct
  • Ensure the recipient has messaged you first (24-hour window)
  • Check WhatsApp Business API rate limits
  • Verify your app_secret is correct
  • Check that you’re using the raw request body for signature verification
  • Ensure the signature header is being received

Next Steps

OpenAI Setup

Configure AI capabilities with OpenAI

Credentials

Learn about credential encryption and storage

Build docs developers (and LLMs) love