WABA API Developer Reference
Send template messages, custom messages, and files via WhatsApp channel through the iSMS platform. Viber and Messenger coming soon.
Table of Contents
📡 Base URLs
Three endpoint URLs are provided. We recommend using Resource URL 2 or 3 for optimal performance and reliability in production.
https://ww3.isms.com.my/isms_send_waba.phphttps://smtpapi.vocotext.com/isms_send_waba.phpRecommendedhttps://smtpapi2.vocotext.com/isms_send_waba.phpRecommendedContent-Type: application/json header in every request.📱 Supported Channels
💬 Message Types
The Send Message API supports three message types. Template messages (Marketing, Utility, Authentication/OTP) are charged per message and can be sent anytime. Custom/free-text messages and files are only available within an active 24-hour user-initiated window — this is the Service message category, charged per session (not per message).
Send pre-approved Meta message templates with dynamic variable substitution.
✓ Available anytimeSend custom free-text messages to users who have recently messaged your WABA number.
⏱ Within 24-hour windowSend images, PDFs, documents, and other files via a direct publicly accessible URL.
⏱ Within 24-hour window📋 Request Parameters
Complete parameter reference for the Send Message API. Required parameters must be in every request. Conditional parameters depend on message type.
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
| AppId | String | Required | Application ID from iSMS console | 8671971xxx |
| AppSecret | String | Required | Application secret from iSMS console | 0b34b7cc... |
| un | String | Required | Your iSMS account username | iSMS |
| pwd | String | Required | Your iSMS account password | iSMS123 |
| agreedterm | String | Required | Must be set to "YES" — confirms acceptance of iSMS Terms | YES |
| ChannelType | String | Required | Message channel. Currently supported: whatsapp. Viber and Messenger coming soon. | whatsapp |
| Type | String | Required | Message type: template, message, or file | template |
| From | String | Required | Sender phone number — must be registered WABA number | 6391XXXXXXXX |
| To | String | Required | Recipient phone number in international format | 6018222xxxx |
| TemplateCode | String | Conditional | Template code — required when Type = template | 744c4b5c... |
| Language | String | Conditional | Template language code — required when Type = template | en |
| TemplateParams | Object | Conditional | Template variable values as JSON — when Type = template | {"param1":"val"} |
| Content | String | Conditional | Message text body — required when Type = message | Hello World |
| fileUrl | String | Conditional | Direct public URL to file — required when Type = file | https://... |
| fileName | String | Conditional | Display name for the file — required when Type = file | invoice.pdf |
📤 Send Template Message
Template messages (Marketing, Utility, Authentication/OTP) are pre-approved by WhatsApp and can be sent anytime — ideal for notifications, OTP, reminders, and transactional alerts. These are charged per message regardless of session status.
JSON Request Body
{
"AppId": "8671971xxxxxxx",
"AppSecret": "0b34b7cc0cbxxxxxc",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"Type": "template",
"TemplateCode": "90934259xxxxxx",
"TemplateParams": {
"param1": "your value here"
},
"Language": "en",
"From": "6391XXXXXXXX",
"To": "639XXXXXXXXX"
}PHP Example
<?php $url = "https://smtpapi.vocotext.com/isms_send_waba.php"; $data = [ "AppId" => "your_app_id", "AppSecret" => "your_app_secret", "un" => "your_username", "pwd" => "your_password", "agreedterm" => "YES", "Type" => "template", "TemplateCode" => "your_template_code", "TemplateParams" => ["param1" => date("Y-m-d H:i:s")], "Language" => "en", "From" => "your_waba_number", "To" => "recipient_number" ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); $response = curl_exec($ch); if (curl_errno($ch)) { echo "cURL error: " . curl_error($ch); } else { $result = json_decode($response, true); echo "Status: " . $result['statusCode']; echo " | MessageId: " . $result['messageId']; } curl_close($ch); ?>
✉️ Send Custom Message
Send free-form text messages. Only available within the active 24-hour Service session — triggered when a user messages your WABA number first. This session type is charged per 24-hour window, not per individual message.
{
"AppId": "867197xxxx",
"AppSecret": "0b34b7ccxxxx",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"Type": "message",
"Content": "Hello! Your appointment is confirmed for tomorrow at 10am.",
"From": "6391XXXXXXXX",
"To": "639XXXXXXXXX"
}<?php $url = "https://smtpapi.vocotext.com/isms_send_waba.php"; $data = [ "AppId" => "your_app_id", "AppSecret" => "your_app_secret", "un" => "your_username", "pwd" => "your_password", "agreedterm" => "YES", "Type" => "message", "Content" => "Hello! Your appointment is confirmed for tomorrow at 10am.", "From" => "your_waba_number", "To" => "recipient_number" ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); $response = curl_exec($ch); echo $response; curl_close($ch); ?>
📎 Send File
Send images, PDFs, and other documents via a direct public URL. The file must be accessible by our servers without authentication.
{
"AppId": "8671971xxxxx",
"AppSecret": "0b34b7cc0cbxxxxx",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"Type": "file",
"fileUrl": "https://www.bulksms.com.sg/marketing.png",
"fileName": "marketing_brochure",
"From": "6391XXXXXXXX",
"To": "639XXXXXXXXX"
}<?php $url = "https://smtpapi.vocotext.com/isms_send_waba.php"; $data = [ "AppId" => "your_app_id", "AppSecret" => "your_app_secret", "un" => "your_username", "pwd" => "your_password", "agreedterm" => "YES", "Type" => "file", "fileUrl" => "https://www.bulksms.com.sg/marketing.png", "fileName" => "marketing_brochure", "From" => "your_waba_number", "To" => "recipient_number" ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); $response = curl_exec($ch); echo $response; curl_close($ch); ?>
✅ Response Format
Success Response
| Parameter | Type | Description |
|---|---|---|
| requestId | String | Unique identifier for the API request — use for support enquiries |
| statusCode | String | OK or 0 = success. Any other value indicates failure. See Error Codes. |
| messageId | String | Unique identifier for the sent message — use for delivery status tracking |
❌ Error Codes
General Errors
| Code | Description |
|---|---|
| 0 / OK | Request successful |
| -1 | The system is busy — retry after a short delay |
| 1000 | Unknown error |
| 1001 | Authentication failed — check username and password |
| 1002 | Account suspended or expired |
| 1003 | IP address not allowed |
| 1004 | Insufficient credits |
| 1008 | Missing required parameter |
WABA-Specific Errors
| Code | Description |
|---|---|
| 50500 | Invalid destination phone number |
| 70500 | Invalid WABA account |
| 70501 | Invalid WABA API key |
| 70502 | Insufficient WABA credits |
Application & Session Errors
| Code | Description |
|---|---|
| 40001 | Invalid AppSecret or AccessToken |
| 40008 | Invalid message type |
| 41000 | Required parameter not specified |
| 42001 | Access token expired |
| 45001 | API call limit exceeded |
| 45010 | Reply time limit exceeded (outside 24h window) |
| 47001 | JSON parsing error — check request body format |
| 48001 | Not authorized to call this API |
Template Errors
| Code | Description |
|---|---|
| 60005 | templateCode parameter not specified |
| 60006 | Template code does not exist |
| 60012 | Invalid parameter format |
| 70001 | Scenario sending policy not configured |
📥 Inbound Messages (Webhook)
When a WhatsApp user sends a message to your WABA number, iSMS will immediately forward it to your registered webhook URL via an HTTPS POST request. The entire payload is delivered as a single response parameter encoded in base64.
Webhook Method & URL Format
| Parameter | Location | Type | Description |
|---|---|---|---|
| response | Query String | String | The full inbound message payload encoded as base64_encode(). Decode this value to retrieve the JSON object containing all message fields. |
Decoded Payload Fields
After decoding the response parameter with base64_decode(), you will receive a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| MessageId | String | Yes | The message ID. |
| From | String | Yes | The phone number of the message sender. |
| To | String | Yes | The phone number of the message receiver. |
| Timestamp | Long | Yes | The timestamp is a Unix timestamp in milliseconds. |
| DisplayName | String | Yes | The display name of the message sender. |
| Type | String | Yes |
The type of the media resources that are included in the message. Valid values:
|
| Message | String | Yes |
The content of the message.
|
| Name | String | Yes | The name of the end user. |
Parameters that specify a location (Type = LOCATION)
When Type is LOCATION, the Message field is a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| latitude | Float | Yes | The latitude of the location. |
| longitude | Float | Yes | The longitude of the location. |
| name | String | No | The name of the location. |
| address | String | No | The address of the location. |
Parameters that specify an image (Type = IMAGE)
When Type is IMAGE, the Message field is a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | String | Yes | The URL of the image file. |
| caption | String | No | The caption of the image. |
Parameters that specify a video file (Type = VIDEO)
When Type is VIDEO, the Message field is a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | String | Yes | The URL of the video file. |
| caption | String | No | The caption of the video. |
Parameters that specify an audio file (Type = AUDIO)
When Type is AUDIO, the Message field is a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | String | Yes | The URL of the audio file. |
Parameters that specify a document (Type = DOCUMENT)
When Type is DOCUMENT, the Message field is a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | String | Yes | The URL of the document file. |
| filename | String | No | The file name of the document as displayed to the recipient. |
| caption | String | No | The caption of the document. |
Parameters that specify a reply button (Type = REPLY)
When Type is REPLY, the Message field is a JSON object with the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
| replyMessageId | String | Yes | The MessageId of the original message the user is replying to. |
| text | String | Yes | The text content of the reply. |
Sample Decoded Payload (JSON)
This is what you get after base64_decode($response) and json_decode():
PHP Webhook Receiver Example
Save this as your webhook endpoint file on your server. Register its URL with BulkSMS support.
<?php /** * waba_inbound_webhook.php * Bulk SMS Philippines will POST to: https://yoursite.com/waba_inbound_webhook.php?response=xxxxx * The ?response= param is base64 encoded JSON. */ // 1. Read the raw base64-encoded response from query string $encoded = $_POST['response'] ?? $_GET['response'] ?? ''; if (empty($encoded)) { http_response_code(400); echo 'Missing response parameter'; exit; } // 2. Decode the base64 payload $json = base64_decode($encoded); if ($json === false) { http_response_code(400); echo 'Invalid base64 encoding'; exit; } // 3. Parse JSON into array $msg = json_decode($json, true); if (!$msg || !isset($msg['MessageId'])) { http_response_code(400); echo 'Invalid payload'; exit; } // 4. Extract fields $messageId = $msg['MessageId'] ?? ''; $from = $msg['From'] ?? ''; $to = $msg['To'] ?? ''; $timestamp = $msg['Timestamp'] ?? 0; $displayName = $msg['DisplayName'] ?? ''; $name = $msg['Name'] ?? ''; $type = $msg['Type'] ?? 'TEXT'; $message = $msg['Message'] ?? ''; // 5. Convert timestamp (milliseconds) to readable datetime $datetime = date('Y-m-d H:i:s', $timestamp / 1000); // 6. Your business logic here — e.g. save to DB, trigger auto-reply, etc. // Example: log to file $log = sprintf( "[%s] From:%s To:%s Type:%s Msg:%s\n", $datetime, $from, $to, $type, $message ); file_put_contents('inbound_log.txt', $log, FILE_APPEND | LOCK_EX); // 7. Always respond 200 OK — Bulk SMS Philippines will retry if it receives non-200 http_response_code(200); echo 'OK'; ?>
200 OK immediately and process the payload asynchronously if needed.MessageId field to deduplicate messages in case of retries — store processed IDs in your database and skip any that have already been handled.📬 Delivery Status (Webhook)
Receive real-time delivery status updates via webhook. WhatsApp Business API provides true handset-level delivery tracking — unlike SMS which only confirms Telco SMSC receipt, WABA reports actual message status at the recipient's device.
Unique identifier for the sent message
Sender phone number (your WABA number)
Recipient phone number
Message status: Sent (submitted to WhatsApp), Delivered (confirmed received at recipient's handset), or Read (recipient opened the message). Unlike SMS DLR, WhatsApp delivery status reflects true handset-level confirmation.
Error description if message failed to deliver
📄 Template List API
https://smtpapi.vocotext.com/api_waba_list_template.phpFetch all WhatsApp message templates associated with your account — including type, name, approval status, language, and components. The component field is base64 encoded.
| Parameter | Type | Required | Description |
|---|---|---|---|
| un | String | Required | Your iSMS account username |
| pwd | String | Required | Your iSMS account password |
Success Response
component field is base64 encoded. Use a base64 decoder (or PHP's base64_decode()) to read template component data.PHP Example (POST)
<?php $url = "https://smtpapi.vocotext.com/api_waba_list_template.php"; $data = json_encode(["un" => "your_username", "pwd" => "your_password"]); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $response = curl_exec($ch); $templates = json_decode($response, true); if ($templates['status'] === 'success') { foreach ($templates['data'] as $tpl) { echo $tpl['name'] . " — " . $tpl['auditStatus'] . "\n"; } } curl_close($ch); ?>
💰 Balance API
https://smtpapi.vocotext.com/api_waba_balance.phpCheck your WABA account credit balance. Each WABA account may have multiple phone numbers — the balance for each registered number is returned separately.
Success Response
<?php $url = "https://smtpapi.vocotext.com/api_waba_balance.php"; $data = json_encode(["un" => "your_username", "pwd" => "your_password"]); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $response = curl_exec($ch); $result = json_decode($response, true); if ($result['status'] === 'success') { foreach ($result['data'] as $acct) { echo $acct['waba_number'] . ": USD " . $acct['waba_credit_balance']; } } curl_close($ch); ?>
Need API Access or Integration Help?
Contact our developer support team — we'll get your AppId, AppSecret, and WABA number configured.
💬 Contact Developer Support →📧 sales@mobiweb.com.my · 📞 +6016 450 2380