Schedule a message
Send an SMS later with scheduledAt: time format, the 72 hour window, validation errors, how to list pending sends and what happens offline.
Updated
To send a message later, add scheduledAt to the request. The value is an ISO 8601 time with a timezone, in the future, up to 72 hours ahead. textbee stores the message as pending and pushes it to the phone at that time.
Where scheduledAt goes
| Endpoint | Where to put scheduledAt |
|---|---|
POST /gateway/send-sms | At the top level of the body. It applies to every recipient. |
POST /gateway/send-bulk-sms | On each item in messages. Each item can have its own time, or none. |
Time format
Write the time in ISO 8601 with an explicit timezone. Both of these forms work:
| Form | Example | Meaning |
|---|---|---|
| UTC | 2026-10-01T14:00:00Z | 14:00 UTC |
| Offset | 2026-10-01T09:00:00-05:00 | 09:00 at UTC-5, which is also 14:00 UTC |
Always include Z or an offset. A time without a timezone, such as 2026-10-01T09:00:00, is read in the server's timezone and can send hours early or late.
The time must be in the future. Schedule up to 72 hours ahead. For a later send, keep the job in your own scheduler and call textbee closer to the time.
Schedule a message
This request sends one reminder at 14:00 UTC on 1 October 2026:
curl -X POST https://api.textbee.dev/api/v1/gateway/send-sms \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": ["+12015550123"],
"message": "Reminder: your appointment is at 3pm today.",
"scheduledAt": "2026-10-01T14:00:00Z"
}'toISOString() in JavaScript and isoformat() on a timezone-aware datetime in Python both include the timezone. The JavaScript SDK also accepts a Date object for scheduledAt.
The response is the same as for an immediate send: 200 with an smsBatchId. The plan limit check happens at request time, so a 429 comes back now, not at the scheduled time.
Schedule items in a bulk request
In a bulk request, set scheduledAt per item. This body sends one item now and one item later:
{
"messages": [
{ "recipients": ["+12015550123"], "message": "Your order is confirmed." },
{ "recipients": ["+12015550123"], "message": "Your order ships today.", "scheduledAt": "2026-10-01T14:00:00Z" }
]
}Items with the same time go out together, paced by the phone's Send Delay.
Validation errors
The API checks scheduledAt when you send the request. It returns 400 for these cases:
| Case | error in the response body |
|---|---|
| The value is not a valid date | Invalid scheduledAt format. Must be a valid ISO 8601 date string. |
| The time is in the past | scheduledAt must be a future date |
In a bulk request, one bad item rejects the whole request.
What happens until the scheduled time
The message is stored with status: "pending" and a dispatchDueAt field that holds the scheduled time. It stays pending until then. At that time, textbee pushes it to the phone and the normal states follow: dispatched, then sent, then delivered if the carrier reports it. See Delivery status and message states.
List pending scheduled sends
This call lists your sends that are still pending:
curl "https://api.textbee.dev/api/v1/gateway/messages?direction=sent&status=pending" \
-H "x-api-key: YOUR_API_KEY"Scheduled messages in the result have a dispatchDueAt in the future. Messages without dispatchDueAt are immediate sends that have not reached the phone yet. Message history lists the other filters.
If the phone is offline at the scheduled time
textbee pushes the message at the scheduled time whether the phone is online or not. The push service holds the message for the phone. When the phone comes back online, it gets the push and sends the message. The message then goes out late, not at the scheduled time.
While textbee waits for the phone, the status can change to unknown. It changes to sent when the phone reports. To avoid late sends, keep the phone online and allowed to run in the background. See Keep the phone online.
Cancel a scheduled message
There is no endpoint to cancel or edit a scheduled message today. After textbee accepts the request, the message goes out at its time.
If your plans can change, schedule close to the send time. Keep the job in your own system until shortly before the time, then call textbee. You can then cancel the job in your own system as long as you need to.
Frequently asked questions
Which timezone does textbee use?
The one in your scheduledAt value. textbee compares the time as an absolute moment. The phone's own timezone does not matter.
Can I schedule a message for next week?
Not with textbee alone. Schedule up to 72 hours ahead. Keep longer-term jobs in your own scheduler.
Does a scheduled message count against my plan when I send the request?
Yes. The limit check runs when you make the request. Each recipient counts as one message.
Does scheduling work on a self-hosted instance?
Yes, when the instance runs with its Redis queue on. Without the queue, a request with scheduledAt returns 400 with SMS scheduling requires queue to be enabled. See Self-hosting.