---
title: "How to schedule email and texts from an AI agent"
description: "Let an AI agent schedule sends without timezone bugs: scheduled_at with an offset, the 90-day horizon, cancelling, batches and quiet hours for texts."
url: https://www.unitpost.com/blog/agents/schedule-email-sms-from-ai-agent
section: Blog
updated: 2026-11-02
---
# How to schedule email and texts from an AI agent

Have the agent pass scheduled_at as an ISO 8601 time with its offset, such as 2026-11-20T09:00:00-05:00, never a bare local time: Unitpost refuses a time without a zone, reads every time back in UTC, and schedules up to 90 days ahead. The agent cancels or moves a send with PATCH /email/{id}, and marketing texts also wait for the recipient's quiet hours to end.

## How to schedule email and texts from an AI agent

> Let an AI agent schedule sends without timezone bugs: scheduled_at with an offset, the 90-day horizon, cancelling, batches and quiet hours for texts.

"Send this Friday at 9" is easy for a person and ambiguous for an agent: whose Friday, and whose 9? Most scheduling bugs in agents are timezone bugs, and an email API can catch them only if it refuses what's ambiguous.

### How should the agent write the time?

As ISO 8601 with a zone: `2026-11-20T09:00:00-05:00` or `2026-11-20T14:00:00Z`. On Unitpost:

- a time without a zone (`2026-11-20T09:00:00`) is refused with `422`, and nothing is sent;
- an offset is accepted and normalized, and every read returns UTC;
- the field is `scheduled_at`. A misnamed field (`send_at`, `sendAt`) is refused with a `422` that names it, so a model's guess never turns into an immediate send.

Give the agent the recipient's timezone as data, from the contact or the request, and tell it to convert, not assume. "The customer is in America/New_York; schedule for 9:00 their time" leaves one right answer.

### What are the limits?

- Horizon: up to 90 days ahead; further is refused.
- Past times: a time in the past, or within about 30 seconds, sends at once, as if `scheduled_at` were missing. If the agent meant tomorrow and wrote today, the mail goes now, so have it read back the time before it schedules.
- Status: a scheduled send answers `status: "scheduled"` with the `scheduled_at` it will use. Have the agent read that back to the person in their timezone.

### How does the agent cancel or move a send?

One endpoint does both: `PATCH /email/{id}` with exactly one of

```bash
{ "cancel": true }
```

or

```bash
{ "scheduled_at": "2026-11-21T09:00:00-05:00" }
```

Cancel works on scheduled and queued emails. A batch scheduled with one `scheduled_at` is cancelled together with `POST /email/batches/{id}/cancel`. Over MCP the same operations are tools, so "move Friday's reminder to Monday" is a lookup and one call.

### What changes for texts?

Texts take the same `scheduled_at`. Marketing texts also respect the recipient's local quiet hours (8:00 to 21:00, narrower where a law or an operator code requires): a marketing text due outside them waits, and the `sms.scheduled` event says `quiet_hours_deferred`. Appointment reminders and other texts a person asked for aren't held (reminders from an agent (/blog/agents/ai-agent-sms-appointment-reminders)).

### Who confirms the schedule?

For one person's reminder, the agent can schedule and report. For anything one-to-many, a campaign or a batch, have it propose the time and the audience, and let a person approve before it calls send (approval before send (/blog/agents/ai-agent-approval-before-send)). A scheduled mistake is cancellable until it fires, which is a good reason to schedule big sends a little ahead rather than send them now.

## FAQ

### How far ahead can an AI agent schedule an email?

Up to 90 days. A later time is refused with 422. A time in the past, or within about 30 seconds, sends immediately, as if no time was given.

### What happens if the agent sends a time without a timezone?

Unitpost refuses it with 422 and sends nothing. A zoneless time is the most common scheduling bug in agents, because the model assumes a timezone the server can't know.

### Can a scheduled send be cancelled?

Yes. PATCH /email/{id} with {"cancel": true} cancels a scheduled or queued email, and {"scheduled_at": ...} moves a scheduled one. A batch sent with one scheduled_at is cancelled as a whole with POST /email/batches/{id}/cancel.

## Related

- [How to let an AI agent send email safely](https://www.unitpost.com/blog/agents/send-email-from-ai-agent): The concrete controls that make agent-initiated email safe: scoped credentials, a verified-domain gate, idempotency, approval before send, and an audit trail.
- [SMS deliverability: registration, consent, quiet hours and carrier filtering](https://www.unitpost.com/blog/deliverability/sms-deliverability): Why US business texts get blocked and how to avoid it: 10DLC and toll-free registration, consent and STOP handling, quiet hours, and content carriers filter.
- [How to fix an SPF record that isn't found](https://www.unitpost.com/blog/troubleshooting/spf-record-not-found): Why an SPF lookup returns nothing even after you've added the record, and how to diagnose it: propagation, wrong host, quoting, and the one-SPF-record rule.
