Scheduling
Send a message at a future time and cancel it before it goes, with how the schedule is held and why it is always UTC.
Updated
Add scheduled_at with an ISO 8601 timestamp and we hold the message until
then.
{
"from": "Acme <hello@mail.yourdomain.com>",
"to": ["customer@example.com"],
"subject": "Your trial ends tomorrow",
"html": "<p>Renew any time.</p>",
"scheduled_at": "2026-09-15T09:00:00Z"
}The response is immediate, and the message sits in scheduled until its time:
{ "id": "169a3e78-d63a-4fd4-a977-44b02d45bab1" }A time in the past sends immediately rather than erroring - that's kinder than failing a request whose clock was slightly behind.
Scheduled messages go out within about a minute of their time.
If it can't be sent when the time comes
The checks made when you schedule a message are made again when it's due. If
by then the account is suspended or closed, the subscription has ended, or the
sending domain is no longer verified, the message isn't sent: it becomes
failed, the reason is on the message, an email.failed webhook is sent,
and the quota it reserved is returned. The same happens if the mail server
refuses it, or if - through an outage on our side - the message is more than
24 hours past its time: a message that late is not sent at all, because
arriving a day or a week after it was meant to is usually worse than not
arriving.
Cancelling
curl -X POST https://api.sendpository.com/v1/emails/{id}/cancel \
-H "Authorization: Bearer $SENDPOSITORY_API_KEY"{ "id": "169a3e78-...", "status": "cancelled" }Cancelling returns the reserved quota. A cancel that succeeds is final - the message will not go, even if its time is seconds away.
Only while it's still scheduled
Once a message has been handed to the provider it's gone - no API can recall
it. Cancelling a sent message returns a validation_error rather than
pretending to succeed.
Quota timing
Quota is reserved when you schedule, not when the message sends. So a scheduled message can't fail later because you ran out mid-month - the allowance is already set aside. Cancelling gives it back, and so does a message that fails at its send time; either way it goes back to the month it was reserved from.
Attachments can't be scheduled
See Attachments - the file bytes aren't retained, so the combination is refused.
Self-hosting
Scheduled sends are dispatched by a worker endpoint. If you run Sendpository yourself, point a cron at it every minute:
* * * * * curl -sS -X POST https://your-app/api/cron/scheduled-sends \
-H "Authorization: Bearer $CRON_SECRET"