PHP tutorial

Send a WhatsApp Message with PHP

Send WhatsApp messages from PHP with cURL: text, images and documents, error handling and delivery status. Copy-paste code, no SDK needed.

Updated 6 October 2026 ยท by BriskBrain Technologies

In this tutorial you'll send a WhatsApp message from PHP using cURL, which comes with almost every PHP install, so there's no SDK or Composer package to add. By the end you'll have one small function that can send text, images and documents, report errors clearly, and check whether your message was delivered and read.

It works with plain PHP 7.4 or newer, and drops straight into Laravel, WordPress or any framework.

Before you start

You need three things from your InstaMessage dashboard. It takes about five minutes:

  1. A free account. Sign up here — no card needed.
  2. A connected instance. Create an instance and scan its QR code with WhatsApp on your phone (Settings → Linked devices → Link a device), until its status shows Connected.
  3. Your instance_id and access_token. On the instance's page, generate an API credential. The token is shown only once, so copy it somewhere safe straight away.

Keep both out of your code: store them as environment variables, so they never end up in Git. On macOS or Linux:

Terminal (macOS / Linux)
export INSTAMESSAGE_INSTANCE_ID="your-instance-id"
export INSTAMESSAGE_TOKEN="your-access-token"

On Windows (PowerShell):

PowerShell (Windows)
$env:INSTAMESSAGE_INSTANCE_ID = "your-instance-id"
$env:INSTAMESSAGE_TOKEN = "your-access-token"
Phone number format: country code first, digits only — no +, spaces or leading 0. For example +91 98765 43210 becomes 919876543210.

Step 1: Write one small helper function

Every InstaMessage request has the same shape: a URL, your access token in the Authorization header, and a JSON body. So we'll write that once. Save this as instamessage.php:

instamessage.php
<?php

/**
 * Calls the InstaMessage API and returns the decoded JSON.
 * Throws an exception with a readable message if anything goes wrong.
 */
function instamessage(string $method, string $path, ?array $body = null): array
{
    $curl = curl_init('https://instamessage.in/api/v1' . $path);

    $options = [
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 60, // media downloads can take a few seconds
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('INSTAMESSAGE_TOKEN'),
            'Content-Type: application/json',
            'Accept: application/json',
        ],
    ];

    if ($body !== null) {
        $options[CURLOPT_POSTFIELDS] = json_encode($body);
    }

    curl_setopt_array($curl, $options);

    $response = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $error = curl_error($curl);
    curl_close($curl);

    if ($response === false) {
        throw new RuntimeException("Could not reach the API: $error");
    }

    $data = json_decode($response, true) ?? [];

    if ($status !== 200 || empty($data['success'])) {
        throw new RuntimeException($data['error'] ?? "Request failed with HTTP $status");
    }

    return $data;
}

The function treats anything other than 200 with "success": true as a failure, and uses the API's own error text when there is one, so you see exactly what went wrong.

Step 2: Send your first text message

Create send.php next to it. Replace the number with your own WhatsApp number to test:

send.php
<?php

require __DIR__ . '/instamessage.php';

$result = instamessage('POST', '/messages/send', [
    'instance_id' => getenv('INSTAMESSAGE_INSTANCE_ID'),
    'to' => '919876543210',
    'message' => 'Hello from PHP! ๐Ÿ‘‹',
]);

echo 'Sent! Message ID: ' . $result['message_id'] . PHP_EOL;

Run it from the terminal:

Terminal
php send.php

A successful call prints the message ID, and the message arrives on the phone within a second or two. The API's full reply looks like this:

Response ยท JSON
{
    "success": true,
    "message_id": "3EB0A1B2C3D4E5F6",
    "sent_via": "device",
    "fallback_status": null
}

Step 3: Handle errors

Wrap the call in try / catch so one failed message doesn't stop your script:

PHP
try {
    $result = instamessage('POST', '/messages/send', [
        'instance_id' => getenv('INSTAMESSAGE_INSTANCE_ID'),
        'to' => '919876543210',
        'message' => 'Your order #1042 has shipped.',
    ]);
} catch (RuntimeException $e) {
    error_log('WhatsApp message failed: ' . $e->getMessage());
}

The errors you're most likely to meet:

  • HTTP 401 — the access token is missing, wrong or revoked.
  • "Instance is not connected" — open your dashboard and reconnect the instance.
  • "instance_id does not match this token" — the token belongs to a different instance.
  • "You've reached your plan's monthly message limit" — upgrade, or wait for next month.
  • HTTP 429 — too many requests; sending is limited to 30 per minute per token.

Step 4: Send an image or a PDF

Add a type and a public media_url. InstaMessage downloads the file, checks it and sends it. The message becomes an optional caption:

PHP
// An image with a caption (JPG, PNG or WebP, up to 5 MB)
instamessage('POST', '/messages/send', [
    'instance_id' => getenv('INSTAMESSAGE_INSTANCE_ID'),
    'to' => '919876543210',
    'type' => 'image',
    'media_url' => 'https://example.com/images/new-arrival.jpg',
    'message' => 'Just in: our new collection',
]);

// A PDF document, with the file name the recipient will see
instamessage('POST', '/messages/send', [
    'instance_id' => getenv('INSTAMESSAGE_INSTANCE_ID'),
    'to' => '919876543210',
    'type' => 'document',
    'media_url' => 'https://example.com/invoices/42.pdf',
    'file_name' => 'Invoice-42.pdf',
    'message' => 'Here is your invoice.',
]);

Video, audio and voice notes work the same way — see the media rules for every type and size limit.

Step 5: Check if it was delivered and read

Use the message_id from step 2 to look up the message's status at any time:

PHP
$status = instamessage('GET', '/messages/' . $result['message_id']);

echo $status['message']['status'] . PHP_EOL; // pending, sent, delivered, read or failed

read only appears if the recipient has read receipts turned on. To be told the moment a message is delivered or read, instead of asking, set a webhook on your instance.

Protect your WhatsApp number

WhatsApp can restrict or ban a number that looks like it's sending spam. Only message people who expect to hear from you, keep your volume steady, and avoid sending the same text to large lists. Read the full do's and don'ts before you go live.

Next steps

More guides