Scheduling WhatsApp messages through the API
Meta’s Cloud API does not schedule: it sends now. How to schedule through the Joinotify API with an absolute time or a relative delay, what is re-checked at send time, and why cancellation matters more than it looks.


Written by
Equipe Joinotify
Published on
Read time
8 min read
Meta’s Cloud API has no scheduling: it sends at the moment of the call. Scheduling is a Joinotify layer feature — the same send endpoint accepts an absolute instant or a relative delay, stores the request and delivers at the right time. The response is 202 rather than 201, because nothing has been created at Meta yet.
Two ways to schedule, and why both exist
- sendAt — an absolute instant. This is the "Friday at 9am" case.
- delaySeconds — a delay from now. This is the "two hours after the cart was abandoned" case.
Converting one into the other on the client side is precisely where time zone bugs come from — which is why both exist.
# Two hours from now
curl -X POST https://api.joinotify.com/messages \
-H 'Authorization: Bearer sk_live_xxx' \
-H 'Content-Type: application/json' \
-d '{
"type": "text",
"to": "5541987111527",
"body": "Your cart is still saved 🙂",
"delaySeconds": 7200
}'The response carries the schedule identifier and the computed instant:
{
"data": {
"id": "clz3k1p9x0000",
"status": "pending",
"to": "5541987111527",
"sendAt": "2026-08-15T21:00:00.000Z",
"messageId": null
}
}The messageId is null because the message does not exist at Meta yet. It is filled in when the send actually happens — and it is the wamid that matches the delivery events.
Listing and cancelling
# What is pending
curl https://api.joinotify.com/messages/scheduled?status=pending \
-H 'Authorization: Bearer sk_live_xxx'
# Cancel
curl -X DELETE https://api.joinotify.com/messages/scheduled/clz3k1p9x0000 \
-H 'Authorization: Bearer sk_live_xxx'Cancellation works even with seconds to spare: the delivery worker re-reads the record before going out. A message already sent returns 404 — there is nothing to cancel.
Cancellation is the feature, not a detail
Scheduling is easy; the value is in being able to change your mind. The cases that show up in production are almost always cancellations:
- The cart was recovered before the two hours — cancel the recovery message.
- The order was cancelled before the payment reminder.
- The customer replied and the matter was resolved before the scheduled follow-up.
- The campaign was suspended and hundreds of sends are pending.
Store the schedule id alongside the record that created it. Without that, cancelling means listing everything and guessing which is which.
What is re-checked at send time
Three things, and none of them at scheduling time:
- Entitlement — a subscription that lapsed in between prevents the send.
- The number — it may have been disconnected between scheduling and delivery.
- The message rules — the 24-hour window is evaluated at send time, not at scheduling time.
The third catches people out most. Scheduling free-form text for 20 hours from now looks safe if the window is open today, but it may have closed by the time the message goes out. For distant scheduling, use a template.
When to schedule and when to use your own queue
- Schedule at the API when the delay belongs to the business: reminders, follow-ups, recovery, a notice the day before.
- Use your own queue when the delay is technical: retries with backoff, throughput limiting, batch ordering.
Mixing the two — scheduling a thousand messages for the same minute — swaps one problem for another: the number’s sending limit still applies at delivery time.
Frequently asked questions
Does Meta’s official API schedule messages?
No. Scheduling belongs to the provider layer; the Cloud API sends at the moment of the call.
Can I schedule a template?
You can, and it is recommended for distant schedules — free-form text depends on the 24-hour window being open at send time.
What happens if the subscription lapses before the send?
The send does not happen. Entitlement is re-checked at send time, not at scheduling time.
Can I edit a scheduled message?
The route is to cancel and reschedule — which also leaves a clearer history than a silent edit.

