Developer docs

IotaBot WhatsApp API

Send and receive WhatsApp messages from your code — on every number you connected.

Get an API key

Send WhatsApp messages with PHP

Send with cURL, receive with a plain PHP endpoint — no framework needed.

  1. Create an API key (a test key never sends) and a webhook endpoint in Developers.
  2. Set IOTABOT_API_KEY and IOTABOT_WEBHOOK_SECRET (the endpoint's whsec_… secret) in your environment.
  3. Run the program below. Point the endpoint at /iotabot/webhook on your server.
iotabot.php
<?php
// iotabot.php — one function for every send.
const API = 'https://api.iotabot.com/v1';

function iotabot_send(array $body): array {
    $ch = curl_init(API . '/messages');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('IOTABOT_API_KEY'),
            'Content-Type: application/json',
            // One Idempotency-Key per message: reuse it if you retry, so it is never sent twice.
            'Idempotency-Key: ' . bin2hex(random_bytes(16)),
        ],
        CURLOPT_POSTFIELDS => json_encode($body),
    ]);
    $res = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    if ($status >= 300) throw new RuntimeException($res['error']['code'] . ': ' . $res['error']['message']);
    return $res['data'];
}
send.php
<?php
// send.php — start a conversation with an approved template (works for any number, any time).
require __DIR__ . '/iotabot.php';

$sent = iotabot_send([
    'channel'  => 'whatsapp',
    'to'       => '+919812345678',
    'template' => ['name' => 'order_update', 'language' => 'en_US', 'parameters' => ['#1042', 'Friday']],
]);
echo "queued {$sent['id']} in conversation {$sent['conversation_id']}\n";
webhook.php
<?php
// webhook.php — receive messages and reply within the 24-hour window.
require __DIR__ . '/iotabot.php';

function iotabot_verified(string $raw, string $header, string $secret): bool {
    $t = 0; $sigs = [];
    foreach (explode(',', $header) as $part) {
        [$k, $v] = array_pad(explode('=', $part, 2), 2, '');
        if ($k === 't') $t = (int) $v;
        if ($k === 'v1') $sigs[] = $v;
    }
    if (abs(time() - $t) > 300) return false;          // older than 5 minutes
    $expected = hash_hmac('sha256', $t . '.' . $raw, $secret);
    foreach ($sigs as $sig) if (hash_equals($expected, $sig)) return true;
    return false;
}

$raw = file_get_contents('php://input');
$event = json_decode($raw, true);

if ($event['type'] === 'endpoint.verification') {    // sent once, when you add the endpoint
    header('Content-Type: application/json');
    echo json_encode(['challenge' => $event['data']['challenge']]);
    exit;
}
if (!iotabot_verified($raw, $_SERVER['HTTP_IOTABOT_SIGNATURE'] ?? '', getenv('IOTABOT_WEBHOOK_SECRET'))) {
    http_response_code(401);
    exit;
}
if ($event['type'] === 'message.received') {
    $conversation = $event['data']['conversation'];
    error_log($conversation['contact']['phone'] . ' wrote: ' . $event['data']['message']['text']);
    iotabot_send(['conversation_id' => $conversation['id'], 'text' => 'Thanks — we are on it!']);
}
http_response_code(200);