# Scheduled emails

Emails with a scheduled_at that you reschedule or cancel, bounded by the simulator's clock rather than yours.

A scheduled email is a record that waits for a send time the simulator never reaches by itself: it stays `scheduled` until you reschedule or cancel it. Reload the scenario so the ids below start at 1, then send one, move it and cancel it:

```bash
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"design_studio"}'
curl -s "$RYSTIC_URL/emails" -H 'Authorization: Bearer re_placeholder' -H 'Content-Type: application/json' -d '{"from":"Acme <onboarding@resend.dev>","to":["delivered@resend.dev"],"subject":"Reminder","html":"<p>Due soon</p>","scheduled_at":"2026-03-05T09:00:00Z"}'
# -> {"id":"28c9b732-cf71-466d-8000-000000000001"}
curl -s "$RYSTIC_URL/emails/28c9b732-cf71-466d-8000-000000000001" -H 'Authorization: Bearer re_placeholder' | jq -c '{last_event, scheduled_at}'
# -> {"last_event":"scheduled","scheduled_at":"2026-03-05 09:00:00.000000+00"}
curl -s -X PATCH "$RYSTIC_URL/emails/28c9b732-cf71-466d-8000-000000000001" -H 'Authorization: Bearer re_placeholder' -H 'Content-Type: application/json' -d '{"scheduled_at":"2026-03-08T09:00:00Z"}'
# -> {"id":"28c9b732-cf71-466d-8000-000000000001","object":"email"}
curl -s "$RYSTIC_URL/emails/28c9b732-cf71-466d-8000-000000000001" -H 'Authorization: Bearer re_placeholder' | jq -c '{last_event, scheduled_at}'
# -> {"last_event":"scheduled","scheduled_at":"2026-03-08 09:00:00.000000+00"}
curl -s -X POST "$RYSTIC_URL/emails/28c9b732-cf71-466d-8000-000000000001/cancel" -H 'Authorization: Bearer re_placeholder'
# -> {"id":"28c9b732-cf71-466d-8000-000000000001","object":"email"}
curl -s "$RYSTIC_URL/emails/28c9b732-cf71-466d-8000-000000000001" -H 'Authorization: Bearer re_placeholder' | jq -c '{last_event}'
# -> {"last_event":"canceled"}
curl -s -X POST "$RYSTIC_URL/emails/28c9b732-cf71-466d-8000-000000000001/cancel" -H 'Authorization: Bearer re_placeholder' | jq -c '{name, message}'
# -> {"name":"validation_error","message":"You can only cancel scheduled emails."}
```

### The clock decides what is in the past

The simulator checks `scheduled_at` against its own clock, when sending an email and when rescheduling one:

| `scheduled_at` | The simulator returns |
|---|---|
| at or before the clock | 422 `validation_error`, ``The `scheduled_at` field must be a future date`` |
| more than 30 days ahead of the clock | 422 `validation_error`, ``The `scheduled_at` field must be within 30 days`` |

Loading `design_studio` sets the clock to `2026-03-01T00:00:00Z`. A boot under `rystic run --clock` starts the clock at the pinned instant instead, even with `--scenario design_studio`, but a later scenario load still sets the clock to `2026-03-01T00:00:00Z`. The clock moves one millisecond whenever a request samples it, including some reads.

Pin the clock with `POST /_rystic/clock` before you choose dates from your wall clock, and choose a date later than the clock and no more than 30 days ahead of it. `GET /_rystic/version` reports `initial_clock`, the empty-boot epoch (`2026-01-01T00:00:00Z` by default), not the scenario's clock. Never derive a date from it: it can sit before or after the scenario's clock.

### Forms of `scheduled_at`

The simulator accepts an ISO 8601 timestamp and the natural-language forms measured on Resend, which count hours, days and weeks from the clock (`in 2 days`). How Resend treats a date without a time or time zone is unconfirmed: it has not been checked against Resend.

**Differs from Resend:** the simulator does not accept every phrase Resend does.

### Nothing fires

The send time never arrives by itself, and moving the clock does not send the email. A scheduled send records an `email.scheduled` event and no SMTP handoff, since Resend hands the mail to SMTP only at the scheduled time ([Webhooks](https://www.rystic.ai/docs/simulators/resend.md#webhooks) lists the events). A newly scheduled email reads `scheduled` at once, so an edit made right away never races.

**Differs from Resend:** a change made right after scheduling an email can race Resend's readiness. Resend returned 422 to a cancel sent that soon.

---

Source: https://www.rystic.ai/docs/simulators/resend/features/scheduled-emails · Markdown: https://www.rystic.ai/docs/simulators/resend/features/scheduled-emails.md
