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. Spaces,
+,-,., brackets and a leading00are removed for you, so+91 98765-43210works. Spreadsheet values such as919876543210.0and9.19876543210E+11are read as their digits, but a rounded one such as9.19877E+11is refused, because digits are missing. Send the number either with its country code (919876543210) or without it (9876543210) together withcountry_code. A local number written with its leading0works too:09876543210withcountry_code91goes to919876543210, and0612345678with39(Italy, where the0is part of the number) goes to390612345678. A number written with+or00carries its country code:country_codeisn't added to it, and a bracketed(0)after the code is dropped, so+44 (0)20 7946 0018goes to442079460018.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 or is written with+or00. 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, fails, is cancelled or expires. 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 work in capitals or lower case (IST or ist). 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 be a number of 6–17 digits. Letters and other symbols aren't allowed, and neither is a rounded spreadsheet value such as 9.19877E+11. |
Invalid Contact Number "…" | With the country code added, the number must be 7–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. |
Scheduled date & time is not in valid format: date DD/MM/YYYY and time HH:MM (24-hour) | date or time is in another format (for example 2026-12-24 or 09:00:00) or isn't a real date (31/02/2026). |
Unknown timezone "…": … | timezone isn't a timezone name or one of the abbreviations above. Offsets such as GMT+5:30 aren't accepted. |
Invalid msg_type: use 0 (text), 1 (image) or 2 (file) | Send msg_type as 0, 1 or 2. |
Invalid whatsapp client … | whatsapp_client is missing or isn't one of your numbers. Use the ID shown for a connected number on your dashboard. |
Server error: the message was not scheduled. Please try again. | Something failed on our side. Returned with HTTP 500; nothing was scheduled, so try again. |
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(refused as not in valid format), 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.
