🚀 Overview
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 windowTemplate messages (Marketing, Utility, Authentication/OTP) 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. All four categories are charged per message.
Supported channels
🔗 API Endpoint
https://www.isms.com.my/isms_send_waba.phpRecommendedhttps://smtpapi.vocotext.com/isms_send_waba.phphttps://smtpapi2.vocotext.com/isms_send_waba.php| Setting | Value |
|---|---|
| Content-Type | application/json |
| Method | POST only |
| Encoding | UTF-8 JSON |
Content-Type: application/json header in every request.🔐 Authentication
🧩 Request Parameters
| 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. For Facebook Messenger, use the separate Messenger API. | whatsapp |
| Type | String | Required | Message type: template, message, or file | template |
| From | String | Required | Sender phone number — must be registered WABA number | 604642xxxx |
| 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
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": "604xxxxxxx",
"To": "601X-XXXXXXX"
}PHP Example
<?php $url = "https://www.isms.com.my/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
{
"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": "604xxxxxxx",
"To": "601X-XXXXXXX"
}<?php $url = "https://www.isms.com.my/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
{
"AppId": "8671971xxxxx",
"AppSecret": "0b34b7cc0cbxxxxx",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"Type": "file",
"fileUrl": "https://example.com/files/marketing.png",
"fileName": "marketing_brochure",
"From": "604xxxxxxx",
"To": "601X-XXXXXXX"
}<?php $url = "https://www.isms.com.my/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://example.com/files/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
{
"requestId": "C9122953-C329-3D9A-9191-7EB5D70D54FC",
"statusCode": "OK",
"messageId": "202311882856605014114304"
}| 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
statusCode other than 0 / OK means the request was not accepted.General Errors
WABA-Specific Errors
Application & Session Errors
Template Errors
📥 Inbound Messages (Webhook)
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:TEXT LOCATION DOCUMENT VIDEO AUDIO REPLY IMAGE CONTACTS |
| Message | String | Yes | The content of the message. If Type is TEXT, the message content is text. For every other type, Message is a JSON object — see Message Payload by Type. |
| Name | String | Yes | The name of the end user. |
Sample Decoded Payload (JSON)
This is what you get after base64_decode($response) and json_decode():
{
"MessageId": "C9122953-C329-3D9A-9191-7EB5D70D54FC",
"From": "60123456789",
"To": "604642XXXXX",
"Timestamp": 1712390400000,
"DisplayName": "Ahmad Razif",
"Name": "Ahmad Razif",
"Type": "TEXT",
"Message": "Hello, I would like to know more about your services."
}🗂 Message Payload by Type
Type is not TEXT, the Message field is a JSON object with the fields below.latitudeFloatRequiredThe latitude of the location.
longitudeFloatRequiredThe longitude of the location.
nameStringOptionalThe name of the location.
addressStringOptionalThe address of the location.
{
"latitude": 3.1478,
"longitude": 101.6953,
"name": "Kuala Lumpur City Centre",
"address": "Kuala Lumpur, 50088, Malaysia"
}urlStringRequiredThe URL of the image file.
captionStringOptionalThe caption of the image.
{
"url": "https://cdn.example.com/photo.jpg",
"caption": "Check out our latest product!"
}urlStringRequiredThe URL of the video file.
captionStringOptionalThe caption of the video.
{
"url": "https://cdn.example.com/promo.mp4",
"caption": "Watch our promo video"
}urlStringRequiredThe URL of the audio file.
{
"url": "https://cdn.example.com/voicenote.ogg"
}urlStringRequiredThe URL of the document file.
filenameStringOptionalThe file name of the document as displayed to the recipient.
captionStringOptionalThe caption of the document.
{
"url": "https://cdn.example.com/invoice.pdf",
"filename": "Invoice_April2025.pdf",
"caption": "Please find your invoice attached."
}replyMessageIdStringRequiredThe MessageId of the original message the user is replying to.
textStringRequiredThe text content of the reply.
{
"replyMessageId": "C9122953-C329-3D9A-9191-7EB5D70D54FC",
"text": "Yes, I confirm my appointment."
}🐘 PHP Webhook Receiver
<?php /** * waba_inbound_webhook.php * iSMS 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 — iSMS may 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)
📄 Template List API
component field is base64 encoded.| Parameter | Type | Required | Description |
|---|---|---|---|
| un | String | Required | Your iSMS account username |
| pwd | String | Required | Your iSMS account password |
JSON Request Body
{
"un": "your_username",
"pwd": "your_password"
}Success Response
{
"status": "success",
"data": [
{
"templateType": "PROMOTIONAL",
"name": "New Year Offer",
"auditStatus": "pass",
"language": "en",
"templateCode": "1XXXXXXXXX90",
"last_updated_on": "2024-07-21T14:55:30Z",
"component": "eyJ0eXBlIjogIkJPRFki...",
"status_code": "200",
"status_message": "Approved"
}
]
}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_json.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); ?>
🔎 Template Detail API
templateCode — including its category and components. Use this before sending to confirm a template is approved and to read the variables it expects. Only templates with auditStatus = pass are returned.| Parameter | Type | Required | Description |
|---|---|---|---|
| un | String | Required | Your iSMS account username |
| pwd | String | Required | Your iSMS account password |
| templateCode | String | Required | The template code to look up (see Template List API). Send it as a string, in quotes. |
JSON Request Body
{
"un": "your_username",
"pwd": "your_password",
"templateCode": "1242381527277813760"
}Success Response
{
"status": "success",
"data": [
{
"templateType": "WHATSAPP",
"name": "order_update_01",
"auditStatus": "pass",
"language": "en",
"templateCode": "1242381527277813760",
"last_updated_on": "2026-03-21 14:55:30",
"component": "eyJ0eXBlIjogIkJPRFki...",
"category": "UTILITY",
"status_code": "OK"
}
]
}Error Response
{
"status": "error",
"message": "Invalid Data"
}Invalid Data means the template code does not exist under your account, or the template has not been approved yet. The component field is base64 encoded, the same as in the Template List API.PHP Example
<?php $url = "https://smtpapi.vocotext.com/api_waba_list_template_detail_json.php"; $data = json_encode([ "un" => "your_username", "pwd" => "your_password", "templateCode" => "1242381527277813760" ]); $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') { $tpl = $result['data'][0]; $components = json_decode(base64_decode($tpl['component']), true); echo $tpl['name'] . " (" . $tpl['category'] . ")\n"; print_r($components); } else { echo $result['message']; } curl_close($ch); ?>
➕ Create Template API
| Parameter | Type | Required | Description |
|---|---|---|---|
| un | String | Required | Your iSMS account username |
| pwd | String | Required | Your iSMS account password |
| AppId | String | Required | Your WABA App ID |
| AppSecret | String | Required | Your WABA App Secret |
| agreedterm | String | Required | Set to YES to agree with the API terms & conditions |
| From | String | Required | Your WABA business number |
| templateType | String | Optional | Template channel type. Default: WHATSAPP |
| name | String | Required | Template name — lowercase letters, numbers and underscore only, max 60 characters (e.g. order_update_01) |
| language | String | Required | Template locale code, e.g. en, ms, zh_CN, id |
| category | String | Required | UTILITY (transactional) / MARKETING (promotional) / AUTHENTICATION (OTP) |
| components | Array | Required | Template component objects — see Template Components below |
| example | Object | Conditional | Sample values for each $(variable) used — required by Meta review whenever the template contains variables |
Template Components
| Component | Required | Description |
|---|---|---|
| BODY | Required | text up to 1,024 characters. Supports $(variable) placeholders and WhatsApp formatting: *bold* _italic_ ~strike~ |
| HEADER | Optional | format: TEXT (text up to 60 chars) or IMAGE / VIDEO / DOCUMENT (url = publicly accessible sample media for Meta review; add fileName for documents) |
| FOOTER | Optional | text up to 60 characters |
| BUTTONS | Optional | buttons array — up to 3 QUICK_REPLY buttons, or up to 2 call-to-action buttons (max 2 URL, max 1 PHONE_NUMBER). Quick replies cannot be mixed with URL / call buttons. A URL may end with one $(variable) (urlType: dynamic); button text max 25 characters |
JSON Request Body — Utility / Marketing
{
"AppId": "your_app_id",
"AppSecret": "your_app_secret",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"From": "your_waba_number",
"templateType": "WHATSAPP",
"name": "order_update_01",
"language": "en",
"category": "UTILITY",
"components": [
{ "type": "BODY", "text": "Hi $(name), your order $(orderid) has been shipped." },
{ "type": "FOOTER", "text": "Reply STOP to unsubscribe" },
{ "type": "BUTTONS", "buttons": [
{ "type": "URL", "text": "Track Order", "urlType": "dynamic", "url": "https://example.com/track/$(orderid)" }
] }
],
"example": { "name": "Ali", "orderid": "INV-10023" }
}Authentication (OTP) Templates — Fixed Format
text must be an empty string — Meta generates the message wording automatically, and the verification code parameter when sending is verificationCode. Configurable options: addSecretRecommendation (security disclaimer) on BODY, codeExpirationMinutes (1–90) on FOOTER, and a COPY_CODE button (or ONE_TAP with autofillText / packageName / signatureHash for Android autofill). Submitting body text for an Authentication template is rejected with InvalidParameter.AuthenticationBodyTextMustEmpty.{
"AppId": "your_app_id",
"AppSecret": "your_app_secret",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"From": "your_waba_number",
"templateType": "WHATSAPP",
"name": "login_otp_01",
"language": "en",
"category": "AUTHENTICATION",
"components": [
{ "type": "BODY", "text": "", "addSecretRecommendation": "true" },
{ "type": "FOOTER", "codeExpirationMinutes": 10 },
{ "type": "BUTTONS", "buttons": [ { "type": "COPY_CODE", "text": "Copy code" } ] }
]
}Success Response
{
"requestId": "3876f7cb-77fd-47a1-9f34-b673xxxxxxx",
"statusCode": "OK",
"templateCode": "1242381527277813760",
"templateName": "order_update_01"
}Error Response
{
"requestId": "ec33ce8c-e871-4764-a39f-72f5xxxxxxx",
"statusCode": "InvalidParameter.TemplateTypeNotSupport",
"errorMessage": "Unsupported template type"
}Validation Error Codes
statusCode / errorMessage.PHP Example
<?php $url = "https://smtpapi.vocotext.com/api_waba_create_template.php"; $data = [ "AppId" => "your_app_id", "AppSecret" => "your_app_secret", "un" => "your_username", "pwd" => "your_password", "agreedterm" => "YES", "From" => "your_waba_number", "templateType" => "WHATSAPP", "name" => "order_update_01", "language" => "en", "category" => "UTILITY", "components" => [ ["type" => "BODY", "text" => "Hi $(name), your order has shipped."] ], "example" => ["name" => "Ali"] ]; $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, json_encode($data)); $response = curl_exec($ch); curl_close($ch); echo $response; ?>
🗑 Delete Template API
| Parameter | Type | Required | Description |
|---|---|---|---|
| un | String | Required | Your iSMS account username |
| pwd | String | Required | Your iSMS account password |
| AppId | String | Required | Your WABA App ID |
| AppSecret | String | Required | Your WABA App Secret |
| agreedterm | String | Required | Set to YES to agree with the API terms & conditions |
| From | String | Required | Your WABA business number |
| templateCode | String | Required | The template code to delete (see Template List API) |
| language | String | Required | The template's locale code, e.g. en |
| templateType | String | Optional | Template channel type. Default: WHATSAPP |
JSON Request Body
{
"AppId": "your_app_id",
"AppSecret": "your_app_secret",
"un": "your_username",
"pwd": "your_password",
"agreedterm": "YES",
"From": "your_waba_number",
"templateCode": "1242381527277813760",
"language": "en",
"templateType": "WHATSAPP"
}Success Response
{
"requestId": "ccb775bf-00dd-445d-9bb0-6e83xxxxxxx",
"statusCode": "OK",
"templateCode": "1242381527277813760",
"language": "en"
}Error Response — template not found
{
"requestId": "11aa2357-75a1-4ee5-8728-a55dxxxxxxx",
"statusCode": "ERR-OPERATION-CONFIG-028",
"errorMessage": "Template not found"
}ERR-OPERATION-CONFIG-028. The general error codes (see Error Codes) also apply.PHP Example
<?php $url = "https://smtpapi.vocotext.com/api_waba_delete_template.php"; $data = json_encode([ "AppId" => "your_app_id", "AppSecret" => "your_app_secret", "un" => "your_username", "pwd" => "your_password", "agreedterm" => "YES", "From" => "your_waba_number", "templateCode" => "1242381527277813760", "language" => "en", "templateType" => "WHATSAPP" ]); $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); curl_close($ch); echo $response; ?>
💰 Balance API
| Parameter | Type | Required | Description |
|---|---|---|---|
| un | String | Required | Your iSMS account username |
| pwd | String | Required | Your iSMS account password |
JSON Request Body
{
"un": "your_username",
"pwd": "your_password"
}Success Response
{
"status": "success",
"data": [
{
"waba_number": "601X-XXXXXXX",
"waba_status": "1",
"waba_credit_balance": "100.00",
"waba_credit_currency": "MYR",
"expiry_date": "2026-12-31"
}
]
}<?php $url = "https://smtpapi.vocotext.com/api_waba_balance_json.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'] . ": MYR " . $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 Sales / Get API Access →