Messaging API
Schedule WhatsApp Messages API
Schedule a WhatsApp text, image or document to go out to a phone number or group at a date and time you choose. Use it for appointment reminders, birthday wishes, follow-ups and time-sensitive offers.
https://wbiztool.com/api/v1/schedule_msg/Body: JSON or form fields
The message waits in your queue until the scheduled time and is then sent from your WhatsApp number. The response gives you a msg_id you can use to check its status or cancel it.
Quick example#
curl -X POST https://wbiztool.com/api/v1/schedule_msg/ \
-H "Content-Type: application/json" \
-d '{
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"country_code": "91",
"phone": "9876543210",
"msg": "Hi Aman, a reminder that your appointment is today at 11:30 AM.",
"date": "24/12/2026",
"time": "09:00",
"timezone": "Asia/Kolkata"
}'import requests
response = requests.post(
"https://wbiztool.com/api/v1/schedule_msg/",
json={
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"country_code": "91",
"phone": "9876543210",
"msg": "Hi Aman, a reminder that your appointment is today at 11:30 AM.",
"date": "24/12/2026",
"time": "09:00",
"timezone": "Asia/Kolkata",
},
timeout=60,
)
result = response.json() # read the body even when the HTTP code is 400
if result.get("status") == 1:
print("Scheduled with msg_id", result["msg_id"])
else:
print("Failed:", result.get("message", "no message in response"))// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v1/schedule_msg/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: 12345,
api_key: "YOUR_API_KEY",
whatsapp_client: 678,
msg_type: 0,
country_code: "91",
phone: "9876543210",
msg: "Hi Aman, a reminder that your appointment is today at 11:30 AM.",
date: "24/12/2026",
time: "09:00",
timezone: "Asia/Kolkata",
}),
});
const result = await response.json(); // read the body even when the HTTP code is 400
if (result.status === 1) {
console.log("Scheduled with msg_id", result.msg_id);
} else {
console.error("Failed:", result.message ?? "no message in response");
}<?php
$payload = [
'client_id' => 12345,
'api_key' => 'YOUR_API_KEY',
'whatsapp_client' => 678,
'msg_type' => 0,
'country_code' => '91',
'phone' => '9876543210',
'msg' => 'Hi Aman, a reminder that your appointment is today at 11:30 AM.',
'date' => '24/12/2026',
'time' => '09:00',
'timezone' => 'Asia/Kolkata',
];
$ch = curl_init('https://wbiztool.com/api/v1/schedule_msg/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($result['status'] ?? 0) === 1) {
echo 'Scheduled with msg_id ' . $result['msg_id'];
} else {
echo 'Failed: ' . ($result['message'] ?? 'no message in response');
}Replace 12345, YOUR_API_KEY and 678 with your own values. See Authentication for where to find them.
Request parameters#
Authentication
client_idintegerrequiredYour API Client ID from Settings → API keys.
api_keystringrequiredYour API key from the same page.
whatsapp_clientintegerrequiredID of the WhatsApp number to send from, from WhatsApp settings. Unlike Send message, this endpoint never picks a number for you.
Schedule
datestringrequiredDay to send the message, in
dd/mm/yyyyformat, for example24/12/2026.timestringrequiredTime to send the message, in 24-hour
HH:MMformat, for example09:00or18:45. Don't include seconds.timezonestringoptionalTimezone that
dateandtimeare in. Defaults toIST(India) if you leave it out. See Timezones.
Recipient and message
phonestringRequired unless you send group_nameThe recipient's WhatsApp number, digits only. Spaces,
+,-,.and brackets are removed for you. Send the number either with its country code (919876543210) or without it (9876543210) together withcountry_code.group_namestringRequired unless you send phoneName of a WhatsApp group your number is a member of. It's found the same way as in Send to group. Send
phoneorgroup_name, never both.country_codestringoptionalCountry calling code without
+, for example91for India or1for the USA. It's added in front ofphoneunless the number already starts with it. Exception: with91, a 10-digit number always gets the prefix. With other codes, send local numbers that start with the same digits with the country code included. Ignored for groups.msg_typeintegeroptional0text (default),1image,2file or document.msgstringRequired when msg_type is 0Message text. For images and files it's the caption and can be empty. WhatsApp formatting works:
*bold*,_italic_,~strikethrough~.messageis accepted as an alias.
Images and files
img_urlstringRequired when msg_type is 1Public
httporhttpsURL of the image.file_urlstringRequired when msg_type is 2Public
httporhttpsURL the file can be downloaded from directly.file_namestringoptionalFile name the recipient sees, such as
invoice-4821.pdf. It's sent in lower case, characters such as& : ? * $ ;are replaced with_, and it's cut to 150 characters. If you leave it out, the name comes from the URL.
Delivery options
webhookstringoptionalURL that receives a
POSTwhen the message is sent or fails. The payload is the same as for Send message.
When the message is sent#
- Wbiztool converts
date,timeandtimezoneto a single moment and sends the message once that moment has passed, as long as your WhatsApp number is connected. - A time in the past is accepted. The message is sent straight away, like a normal send. Double-check the date format (
dd/mm/yyyy, day first) so you don't send a message months early. - If your number is disconnected at the scheduled time, the message waits and goes out as soon as the number reconnects, even if that's much later than planned. This endpoint has no expiry, so cancel the message if it's no longer relevant. A message still waiting on a disconnected or deleted number 90 days after its scheduled time is deleted.
- Until it's sent, the message has status
0(Created) and can be cancelled. It also counts against your remaining credits while it waits.
Timezones#
timezone accepts either a timezone name or one of the abbreviations below.
Timezone names such as Asia/Kolkata, America/New_York, Europe/London or Australia/Sydney. Any name from the IANA timezone database works. This is the most reliable option. See the Timezone reference for a list.
Abbreviations must be in capital letters. Each one maps to a region, and that region's daylight saving time is applied automatically:
| Abbreviation | Treated as |
|---|---|
IST | Asia/Kolkata |
UTC | UTC |
GMT | GMT |
EST | US/Eastern |
CST | US/Central |
MST | US/Mountain |
PST | US/Pacific |
CET, CEST | Europe/Paris |
EET, EEST | Europe/Athens |
JST | Asia/Tokyo |
AEST, AEDT | Australia/Sydney |
For example, EST in July means New York summer time (UTC−4), not a fixed UTC−5.
Scheduling for a group#
curl -X POST https://wbiztool.com/api/v1/schedule_msg/ \
-H "Content-Type: application/json" \
-d '{
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"group_name": "Sales Team Mumbai",
"msg": "Team meeting starts in 15 minutes.",
"date": "24/12/2026",
"time": "14:45",
"timezone": "Asia/Kolkata"
}'import requests
response = requests.post(
"https://wbiztool.com/api/v1/schedule_msg/",
json={
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"group_name": "Sales Team Mumbai",
"msg": "Team meeting starts in 15 minutes.",
"date": "24/12/2026",
"time": "14:45",
"timezone": "Asia/Kolkata",
},
timeout=60,
)
print(response.json())// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v1/schedule_msg/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: 12345,
api_key: "YOUR_API_KEY",
whatsapp_client: 678,
msg_type: 0,
group_name: "Sales Team Mumbai",
msg: "Team meeting starts in 15 minutes.",
date: "24/12/2026",
time: "14:45",
timezone: "Asia/Kolkata",
}),
});
console.log(await response.json());<?php
$ch = curl_init('https://wbiztool.com/api/v1/schedule_msg/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'client_id' => 12345,
'api_key' => 'YOUR_API_KEY',
'whatsapp_client' => 678,
'msg_type' => 0,
'group_name' => 'Sales Team Mumbai',
'msg' => 'Team meeting starts in 15 minutes.',
'date' => '24/12/2026',
'time' => '14:45',
'timezone' => 'Asia/Kolkata',
]),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
curl_close($ch);Response#
A successful request returns HTTP 200:
{
"msg_id": 9817263,
"message": "Created",
"status": 1
}
| Field | Type | Description |
|---|---|---|
status | integer | 1 if the message was scheduled, 0 if the request failed. |
message | string | Created on success, otherwise the error. |
msg_id | integer | ID of the scheduled message. Save it to check the status or cancel it later. Only present on success. |
The response doesn't repeat the scheduled time or timezone, so log what you sent.
Errors#
Most errors return HTTP 200 with status set to 0, so always check status in the body:
{ "message": "Scheduled date & time is not in valid format", "status": 0 }
| Message | How to fix it |
|---|---|
Auth Error | Send both client_id and api_key. |
Invalid Client Id | Send client_id as a number. Returned with HTTP 403. |
Auth Error: invalid api key | Check the key exists, hasn't been deleted and belongs to this client_id. Returned with HTTP 400. |
Either phone or group_name parameter is required | Add phone or group_name. |
Please provide either phone OR group_name, not both | Remove one of them. |
Invalid phone number | phone must contain only digits (6–17 of them), optionally starting with +. |
Invalid Contact Number "…" | With the country code added, the number must be 6–15 digits long. |
Msg cant be null | Text messages (msg_type 0) need msg. |
Image Url Can't be null | For msg_type 1, send img_url. |
File Url Can't be null | For msg_type 2, send file_url. |
Scheduled date & time is not in valid format | date or time is missing, or timezone is an empty string. |
Not enough credits | Your plan has no messages left. |
Demo Account can not access apis | Use a regular account. |
Invalid JSON format: … | The JSON body isn't valid, or you sent form fields without client_id. |
Tips#
-
Build the date carefully: in Python use
strftime("%d/%m/%Y")andstrftime("%H:%M"). In JavaScript, format the date and time in the same timezone you send intimezone, not your server's local time:const tz = "Asia/Kolkata"; // d is the Date to send at const date = new Intl.DateTimeFormat("en-GB", { timeZone: tz, day: "2-digit", month: "2-digit", year: "numeric" }).format(d); // "24/12/2026" const time = new Intl.DateTimeFormat("en-GB", { timeZone: tz, hour: "2-digit", minute: "2-digit", hourCycle: "h23" }).format(d); // "09:00" -
Confirm the time: schedule a test message five minutes ahead and check it arrives when you expect.
-
Change of plans: to reschedule, cancel the message and schedule a new one.
-
Don't use the official clients to schedule for now: Python's
schedule_messagesends the date asYYYY-MM-DD(the response is{}), and Node'sscheduleMessagesendsschedule_time, which this endpoint doesn't read. Call the endpoint directly as shown above. -
Recurring messages: for messages that repeat, such as monthly payment reminders, see Create reminder.
