Check environment and feature availability before following this guide.
scheduled:write scope, reading needs
scheduled:read. Both are available to members and up.
Credits are spent when the send happens, not when you schedule it. A scheduled send costs 2 credits.
Schedule one
The response is
201 with the scheduled message:
send_at comes back normalised to UTC. template_version_id records the version that was live
when you scheduled, and it is the version that sends: activating a newer version later does not change
a message already scheduled, including recurring ones. queue_policy_id is only set on messages created through the older
policy-driven path and is null for anything you create here.
Following the live version instead
Pass"follow_live": true when you schedule, and the message is not pinned: it sends whichever
version of the template is live at send time, and each recurrence does the same.
template_version_id comes back null.
To change an existing message, PATCH /v1/scheduled-messages/{id} with "follow_live": true to
unpin it, or "follow_live": false to pin it to the version live now. Pinning a template that has
no live version answers 409 with template_not_activated. Leaving follow_live out never
changes the pin.
Retrying safely
Send anIdempotency-Key header with any unique string. Repeating the request with the same key
and body within 24 hours replays the original response, marked Idempotency-Replayed: true,
instead of scheduling a second message. The same key with a different body answers 409.
What can go wrong
Lifecycle
The last four are terminal. Delivery is checked on a roughly minute-based cadence; load, conditions, and service availability can delay it. The due time is not a guaranteed delivery deadline.
Manage it
All three changes are only possible while the status is
scheduled. Afterwards the API answers
409 with code: "invalid_state" and the current status in details.
Reschedule
PATCH takes any of data, destination, schedule, recurrence and delivery_conditions;
send only what changes. recurrence: null removes the recurrence and delivery_conditions: null
removes the conditions. The deadline max_delay_at is recomputed from the new send_at and
conditions.
Cancel
DELETE is a soft cancel: the row stays, with status: "cancelled", and the response is the
message. Cancelling a recurring message stops the later occurrences too.
Send now
send-now makes the message due immediately and removes its delivery conditions; the evaluator
attempts it on a subsequent tick. The response is 202 with the message, still
scheduled until that tick.
See what happened
Every attempt the evaluator made appears inGET /v1/queue-executions, filterable by
scheduled_message_id. A scheduled_send with result: "success" is the delivery; a
constraint_check with result: "deferred" is a tick where the conditions held the message back,
with the reasons in error_message.
In the web app
The Scheduled page at/scheduled lists your organization’s scheduled messages with a status
filter, shows each one’s destination, recurrence and conditions, and offers reschedule (a new time
and zone), cancel and send now for anything still scheduled. It also shows the create request
above as a copy-paste curl. Creating a scheduled message is an API call; the page manages what the
API created.
Manage in the app · Execution logs
