Recurring schedules, and a sandbox that says what it did

  • Recurring schedules: POST /v1/schedules sends a message every day, week or month at a local time in an IANA time zone, correct across daylight saving. List, retrieve, change, pause and resume (PATCH with active), delete. Each occurrence is a normal send, checked against opt-outs, quota, your spend limit and your credit balance when it fires, and a normal message with schedule_id (GET /v1/messages?schedule_id=). A schedule pauses itself after 3 opt-out skips in a row; an occurrence we reach more than an hour late is skipped, never sent late. In both SDKs (2.2.0) as schedules, and on the console's Scheduled page. See Recurring schedules.
  • Webhook events: schedule.occurrence_skipped, schedule.paused.
  • simulated: every message, and every message.sent, message.delivered and message.failed event, now says whether anything was handed to a carrier. A test-key send is simulated (true) unless it goes to your own verified phone. A simulated send to a real-looking number also answers with a notice, and test-key sends carry an X-SimpleSMS-Simulated header. Statuses are unchanged.
  • from is optional on POST /v1/messages when the account has one number for the key's mode: your sandbox number with a test key, your one live number with a live key. Otherwise the error lists the choices.
  • scheduled_message objects now carry scheduled_at, matching the request field. run_at stays as a deprecated alias. GET /v1/scheduled_messages/{id} exists (it answered 405).
  • Sign-up ends with an optional step to verify your phone. Skipping it, or a code that cannot be sent, never blocks the account.

All changes