Send a WhatsApp message from PHP.

Sending a WhatsApp message from PHP takes one HTTP request to the TextBot API: no SDK, no Meta approval and no template. These examples send a text, a PDF, reply buttons and “typing…”, and receive the replies.

Updated 3 November 2026

In short: link your WhatsApp number to a TextBot key, then call https://api.textbot.cc/send.php with the recipient, your key and the text. Use /api/send with JSON for files, and give the key a webhook address to receive replies.

Before you start

  1. Get a key. Create an account on the pricing page; your first API key is ready when the payment clears.
  2. Link your number. Open the key in your portal, choose Connect WhatsApp and scan the QR code with the phone that holds the number, or use a pairing code.
  3. Copy the key. It goes in the apikey parameter of each request.

Send a text

One GET request with the number, your key and the text. Add json=yes to get the answer as JSON.

<?php
// Send a WhatsApp text from your own number.
$query = http_build_query([
    'recipient' => '27825550199',          // international format, no leading 0
    'apikey'    => 'YOUR_KEY',
    'text'      => 'Your order #1042 has shipped.',
    'json'      => 'yes',                  // answer in JSON
]);

$answer = json_decode(file_get_contents('https://api.textbot.cc/send.php?' . $query), true);

echo $answer['status'] ?? 'no answer';    // "success" when it was sent
echo ' ', $answer['comment'] ?? '';       // what happened, in words

Send a PDF or an image

POST JSON to /api/send with a public link to the file in file. The text becomes its caption.

<?php
// Send a PDF with a caption: POST JSON to /api/send.
$payload = json_encode([
    'recipient' => '+27825550199',
    'apikey'    => 'YOUR_KEY',
    'text'      => 'Your invoice is attached.',
    'file'      => 'https://example.com/invoices/1042.pdf',
]);

$ch = curl_init('https://api.textbot.cc/api/send');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => $payload,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, ' ', $body;

Ask a question with reply buttons

Add button1, button2 and so on. When the customer taps one, the reply arrives on your webhook like any other message. typing=3 shows “typing…” for three seconds before the message arrives; typing=yes times it from the length of the text.

<?php
// A question with two reply buttons; the tap arrives on your webhook.
$query = http_build_query([
    'recipient' => '27825550199',
    'apikey'    => 'YOUR_KEY',
    'text'      => 'Can we deliver tomorrow between 9 and 12?',
    'button1'   => 'Yes',
    'button2'   => 'Another day',
    'typing'    => 3,                      // show “typing…” for 3 seconds first
    'json'      => 'yes',
]);
$answer = json_decode(file_get_contents('https://api.textbot.cc/send.php?' . $query), true);

Receive replies on a webhook

Give your key a webhook address in the portal. Each incoming message, button tap and file is posted to it as JSON with the type, from, from_name, message and file.

<?php
// webhook.php: TextBot posts each incoming message here as JSON.
$event = json_decode(file_get_contents('php://input'), true);
if (!is_array($event)) {
    http_response_code(400);
    exit;
}

$from    = $event['from'] ?? '';           // e.g. 27825550199
$name    = $event['from_name'] ?? '';
$message = trim($event['message'] ?? '');
$file    = $event['file'] ?? null;         // a link, when they sent a file

if (strcasecmp($message, 'stop') === 0) {
    // take $from off your list
}

http_response_code(200);                   // answer quickly; do slow work later

Good habits

  • Keep the key on the server. Never put it in JavaScript or an app that customers can download.
  • Send in the background. For many messages, queue them and send from a worker or cron job rather than while a page loads.
  • Check the answer. A message that did not send says why, and the message log keeps the reason.
  • Message people who expect it. Order updates and replies to customers, not cold lists. Our guide to linked numbers explains why.

The API reference lists all endpoints, including typing.php and the original send.php, status.php and webhook.php paths.

Questions, answered.

How do I write a South African number?

In international format: drop the leading 0 and put 27 in front, so 082 555 0199 becomes 27825550199. A plus sign in front is fine too.

Do I need a library or a Composer package?

No. The API is plain HTTP, so file_get_contents or cURL is all PHP needs. The same calls work from Laravel, Symfony, WordPress or a cron script.

Can I send from WordPress without code?

Yes. The TextBot plugin sends WooCommerce order updates, abandoned-cart reminders and booking messages from the WordPress admin.

Why did a message not send?

The answer says why, and the message log in your portal keeps the reason beside the message — for example, “Recipient is not on WhatsApp”.

Your number. Your API.

Connect your WhatsApp number in under a minute. Annual plans, with no per-message fees.

Create your account

  1. Plan
  2. Account
  3. Payment

Choose a plan first.

Your account and API key are created as soon as PayFast confirms the payment. Nothing is charged until you complete the checkout.

Terms and conditions

Loading…

Reset your password

Enter the email address of your account and we will send you a link to choose a new password.

Choose a new password

Your reset link is ready. Enter a new password to continue to the portal.