Schedule a message
Schedule a WhatsApp message to be sent later from one of your 2Chat numbers, either once or on a recurring schedule. Read How scheduling works for the rules on time zones, recurrence and what stops a scheduled message.
Endpointโ
POST https://api.p.2chat.io/open/whatsapp/schedule-message
Authenticationโ
Include your API key in the X-User-API-Key header. Learn more about authentication.
API costโ
Each call to this endpoint deducts 1 API credit from your plan's API credit pool.
Parametersโ
These parameters should be sent as JSON payload in the request body.
| Field | Type | Required | Description |
|---|---|---|---|
from_number | string | Yes | Your 2Chat number the message is sent from, in international format (e.g. +17135550142). It can be a WhatsApp Web or a WhatsApp Business API (WABA) number. |
to_number | string | Yes | The recipient's phone number in international format (e.g. +447700900461). |
text | string | One of text or url | The message text. |
url | string | One of text or url | URL of a media file to attach, such as an image or a PDF. |
send_at | string | Yes | When to send it, as YYYY-MM-DD HH:MM or YYYY-MM-DD HH:MM:SS in timezone. Must be in the future. For a recurring message, this is the first send. |
timezone | string | No | IANA time zone name for send_at and ends.date (e.g. America/New_York). Defaults to your account's time zone, or UTC if it has none. |
repeat | object | No | Makes the message recurring. Leave it out to send the message once. |
repeat.unit | string | Yes, with repeat | minute, hourly, daily, weekly, monthly or yearly. |
repeat.every | integer | No | Send every this many units. Defaults to 1: "unit": "weekly", "every": 2 sends every other week. |
ends | object | Yes, with repeat | When the series stops. |
ends.type | string | Yes, with repeat | never (until you cancel it), occurrences (after a number of sends) or date (no sends after a date). |
ends.occurrences | integer | Yes, if ends.type is occurrences | Total number of sends, including the first one. |
ends.date | string | Yes, if ends.type is date | The end of the series, as YYYY-MM-DD HH:MM or YYYY-MM-DD HH:MM:SS in timezone. A send due after this moment doesn't go out: to include a whole day, use 23:59. |
- Phone numbers must be in international format (e.g.
+1XXXXXXXXXX). from_numbermust be a number connected to your 2Chat account.- Scheduling to a WhatsApp group or scheduling a WABA template is only available in the 2Chat app.
- On a WABA number, the message is only delivered if the contact's 24-hour customer service window is open when it's due. Otherwise the send is rejected and the scheduled message is stopped.
- A scheduled message can't be edited. To change it, cancel it and schedule a new one.
Invocationโ
This example sends a message once, on December 1st at 09:30 New York time.
- cURL
- Python
- JavaScript
- PHP
curl --location --request POST 'https://api.p.2chat.io/open/whatsapp/schedule-message' \
--header 'Content-Type: application/json' \
--header 'X-User-API-Key: your_api_key_here' \
--data '{
"from_number": "+17135550142",
"to_number": "+447700900461",
"text": "Hi! Just a reminder that your appointment is tomorrow at 10:00.",
"send_at": "2026-12-01 09:30",
"timezone": "America/New_York"
}'
import requests
url = "https://api.p.2chat.io/open/whatsapp/schedule-message"
headers = {
"Content-Type": "application/json",
"X-User-API-Key": "your_api_key_here"
}
payload = {
"from_number": "+17135550142",
"to_number": "+447700900461",
"text": "Hi! Just a reminder that your appointment is tomorrow at 10:00.",
"send_at": "2026-12-01 09:30",
"timezone": "America/New_York"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const axios = require('axios');
const response = await axios.post('https://api.p.2chat.io/open/whatsapp/schedule-message', {
from_number: '+17135550142',
to_number: '+447700900461',
text: 'Hi! Just a reminder that your appointment is tomorrow at 10:00.',
send_at: '2026-12-01 09:30',
timezone: 'America/New_York'
}, {
headers: {
'Content-Type': 'application/json',
'X-User-API-Key': 'your_api_key_here'
}
});
console.log(response.data);
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.p.2chat.io/open/whatsapp/schedule-message',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode([
'from_number' => '+17135550142',
'to_number' => '+447700900461',
'text' => 'Hi! Just a reminder that your appointment is tomorrow at 10:00.',
'send_at' => '2026-12-01 09:30',
'timezone' => 'America/New_York'
]),
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'X-User-API-Key: your_api_key_here'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Recurring examplesโ
Every Monday at 08:00 New York time, with an image, four times in total:
{
"from_number": "+17135550142",
"to_number": "+447700900461",
"text": "Your weekly menu is ready!",
"url": "https://example.com/menu.jpg",
"send_at": "2026-12-07 08:00",
"timezone": "America/New_York",
"repeat": { "unit": "weekly", "every": 1 },
"ends": { "type": "occurrences", "occurrences": 4 }
}
Every day at 18:00 until December 24th, including that day:
{
"from_number": "+17135550142",
"to_number": "+447700900461",
"text": "Don't forget to log today's sales.",
"send_at": "2026-12-01 18:00",
"timezone": "America/New_York",
"repeat": { "unit": "daily" },
"ends": { "type": "date", "date": "2026-12-24 23:59" }
}
Responseโ
Success (HTTP 200)โ
The scheduled message, with the fields described in The scheduled message object.
{
"data": {
"uuid": "EST6cc93513-1706-4ffc-a69e-174572d860dd",
"status": "pending",
"cancelled": false,
"next_send_at_utc": "2026-12-01 14:30:00",
"timezone": "America/New_York",
"channel_uuid": "WPNb932ad7f-250a-4ada-86a6-c1691e00a2cb",
"to_number": "+447700900461",
"text": "Hi! Just a reminder that your appointment is tomorrow at 10:00.",
"url": null,
"template": null,
"recurring": false,
"repeat": null,
"ends": null,
"sent_count": "0",
"created_at": "2026-11-20 15:04:12"
},
"success": true
}
| Field | Description |
|---|---|
success | true when the message was scheduled |
data | The scheduled message. Keep its uuid to cancel it or send it now. |
Errorโ
{
"error": true,
"error_message": "Payload is invalid: send_at must be in the future"
}
| Field | Description |
|---|---|
error | true when the request failed |
error_message | A description of what went wrong |
Common errors (HTTP 400):
error_message | Cause |
|---|---|
Payload is invalid: from_number is required | from_number is missing. Same for to_number and send_at. |
Payload is invalid: from_number does not exist on your account | from_number isn't one of your 2Chat numbers. |
Payload is invalid: text, url or template is required | The message has no content. |
Payload is invalid: send_at must be in the future | send_at is in the past in timezone. |
Payload is invalid: send_at must be 'YYYY-MM-DD HH:MM' or 'YYYY-MM-DD HH:MM:SS' | send_at has another format. |
Payload is invalid: timezone must be a valid IANA name, e.g. America/Asuncion | timezone isn't a known time zone. |
Payload is invalid: repeat.unit must be one of: daily, weekly, monthly, yearly, hourly, minute | repeat.unit is missing or invalid. |
Payload is invalid: ends.type is required with repeat and must be one of: date, never, occurrences | repeat was sent without a valid ends. |
Payload is invalid: ends.date is required when ends.type is 'date' | ends.type is date but ends.date is missing. |
Payload is invalid: Payload must be in JSON format | The body isn't valid JSON. |