Back to blog
FeaturesProduct

Scheduled Messaging: Send SMS, MMS, and RCS at the Perfect Moment

Pinnacle's scheduling system lets you send individual messages or blasts at a future time, on a recurring cron schedule, with timezone support — for any message type, via API or dashboard, with full cancellation and management tools.

Ivan

·7 min read
Scheduled Messaging: Send SMS, MMS, and RCS at the Perfect Moment

Timing Is Everything in Messaging

A flash sale message sent at 3am doesn't convert. An appointment reminder that arrives the moment the appointment starts is useless. A weekly newsletter that goes out at random times loses the habit-forming rhythm that makes it valuable.

SMS open rates average 98% and 90% of messages are read within five minutes of delivery — but those numbers assume the message arrived at a moment when the recipient was receptive. Timing doesn't just affect conversion; it affects whether the message gets seen at all.

Pinnacle's scheduling system is built into every message type. Send a single SMS, an MMS campaign, an RCS blast — any of them can be scheduled for a future time, a specific timezone, or a recurring cadence. No external job queue, no EventBridge, no cron infrastructure to maintain.

Schedule any message type from the dashboard — no code required.Schedule any message type from the dashboard — no code required.

One-Time Scheduled Messages

Schedule any message type for a specific future datetime. The schedule option accepts an ISO 8601 datetime and an optional timezone:

Scheduled SMS

TypeScript
import { PinnacleClient } from "rcs-js";
const client = new PinnacleClient({ apiKey: process.env.PINNACLE_API_KEY });
 
await client.messages.sms.send({
  to: "+14155551234",
  from: "+18005550001",
  text: "Your flash sale starts in 1 hour! 🔥 yourapp.com/sale — Reply STOP to unsubscribe.",
  options: {
    schedule: {
      sendAt: "2026-04-15T08:00:00Z",
      timezone: "America/Los_Angeles", // Sends at 8am Pacific
    },
  },
});

Scheduled MMS

TypeScript
await client.messages.mms.send({
  to: "+14155551234",
  from: "+18005550001",
  text: "Your weekly picks are ready 👇",
  mediaUrls: ["https://cdn.yourapp.com/weekly-picks.jpg"],
  options: {
    schedule: {
      sendAt: "2026-04-15T10:00:00Z",
      timezone: "America/New_York",
    },
  },
});

Scheduled RCS

TypeScript
await client.messages.rcs.send({
  to: "+14155551234",
  from: "agent_your_brand",
  cards: [
    {
      title: "Your appointment tomorrow at 2pm",
      subtitle: "Dr. Martinez — 123 Main St, Suite 400",
      buttons: [
        { type: "trigger", title: "Confirm ✅", payload: "confirm" },
        { type: "trigger", title: "Reschedule", payload: "reschedule" },
      ],
    },
  ],
  quickReplies: [],
  fallback: {
    from: "+18005550001",
    text: "Reminder: Your appointment is tomorrow at 2pm. Reply CONFIRM to confirm or RESCHEDULE to reschedule.",
  },
  options: {
    schedule: {
      sendAt: "2026-04-14T17:00:00Z", // Day before at 5pm
      timezone: "America/Chicago",
    },
  },
});

The timezone field accepts any IANA timezone string (e.g., America/Los_Angeles, Europe/London, Asia/Tokyo). If omitted, the sendAt datetime is interpreted as UTC.


Recurring Scheduled Blasts

For repeating campaigns — weekly newsletters, monthly statements, daily check-ins — use a cron expression on blast sends. The recurrence field takes a standard 5-field cron expression, with an optional endDate to define when the series stops:

TypeScript
await client.messages.blast.sms({
  audienceId: "aud_abc123",
  senders: ["+18005550001", "+18005550002"],
  message: {
    text: "Your weekly update from us: yourapp.com/updates. Reply STOP to unsubscribe.",
  },
  options: {
    schedule: {
      sendAt: "2026-04-07T09:00:00Z", // First occurrence
      recurrence: "0 9 ? * MON *", // Every Monday at 9am
      timezone: "America/New_York",
      endDate: "2026-12-31T00:00:00Z", // Run through end of year
    },
  },
});

Common Cron Patterns

ExpressionMeaning
0 9 ? * MON *Every Monday at 9am
0 10 1 * ? *First of every month at 10am
0 8 ? * MON-FRI *Weekdays at 8am
0 12 ? * FRI *Every Friday at noon
0 18 * * ? *Every day at 6pm

Recurring blasts are powerful for subscription-style messaging — weekly product digests, monthly account summaries, recurring promotional windows — where the setup cost should be paid once and the campaign runs indefinitely.


Scheduled Blasts for All Message Types

The scheduling system works identically for SMS, MMS, and RCS blasts:

Scheduled RCS Blast With Fallback

TypeScript
await client.messages.blast.rcs({
  audienceId: "aud_vip_customers",
  senders: ["agent_your_brand"],
  message: {
    cards: [
      {
        title: "Your VIP offer expires at midnight",
        subtitle: "30% off — exclusive to you.",
        media: "https://cdn.yourapp.com/vip-countdown.jpg",
        buttons: [
          {
            type: "openUrl",
            title: "Claim Now",
            payload: "https://yourapp.com/vip",
          },
        ],
      },
    ],
    quickReplies: [],
  },
  fallback: {
    from: "+18005550001",
    text: "Your VIP offer expires at midnight — 30% off at yourapp.com/vip. Reply STOP to unsubscribe.",
  },
  options: {
    schedule: {
      sendAt: "2026-04-30T20:00:00Z", // 8pm — 4 hours before expiry
      timezone: "America/Los_Angeles",
    },
  },
});

Managing Scheduled Messages

Every scheduled message and blast gets a unique ID and is tracked in Pinnacle's scheduler. You can view, filter, and cancel scheduled sends before they dispatch.

Cancel a Scheduled Message

If a campaign changes or you need to pull a send before it fires:

TypeScript
await client.messages.schedule.cancel("msg_sched_abc123");

Cancellation works up until the moment the message is dispatched. Once a message has been queued for sending, it can no longer be cancelled.


Scheduling From the Dashboard

Every scheduling option available in the API is also available from the Pinnacle dashboard — no code required. When composing a message or creating a blast, set the send time, timezone, and optional recurrence from the UI.

This makes scheduled messaging accessible to non-technical team members: a marketing manager can schedule next week's campaign without an engineering ticket. A support team can set up a follow-up reminder without API access.

View and manage all scheduled messages from one place — cancel or reschedule before they fire.View and manage all scheduled messages from one place — cancel or reschedule before they fire.

The Business Case for Scheduled Messaging

The impact of timing on messaging performance is well documented. Research consistently shows that messages sent between 10am–12pm and 5pm–7pm in the recipient's local timezone significantly outperform sends during off-hours. A promotional SMS that hits at 9am Saturday morning — when people are browsing, not commuting — will out-convert the same message at 11pm.

The math compounds for recurring campaigns. A brand that sends a weekly digest consistently at 9am Tuesday builds a reading habit in its audience. Inconsistent timing erodes that habit — and with it, the open rates that make SMS marketing so effective.

Building scheduling infrastructure yourself is not trivial. An external cron system (Celery, BullMQ, Sidekiq, EventBridge), timezone-aware scheduling logic, per-schedule state management, cancellation handling, and failure retry logic — that's a multi-week engineering project. Pinnacle ships it as a parameter.


Using the MCP Server for AI-Driven Scheduling

The Pinnacle MCP server makes scheduling a natural-language operation for AI-powered workflows:

"Schedule an RCS blast to the VIP Customers audience for next Friday at 10am Pacific, with a fallback SMS, featuring our new product launch."

The MCP's blast_rcs tool handles the full schedule configuration — sendAt, timezone, recurrence — from a single natural language instruction.


Frequently Asked Questions

What's the earliest I can schedule a message?

The sendAt field must be at least 5 minutes in the future. This applies to all message types — SMS, MMS, and RCS — as well as blasts.

Can I edit a scheduled message after creating it?

Currently, editing requires cancelling the scheduled message and creating a new one with the updated content or timing.

Does timezone support handle daylight saving time automatically?

Yes. Using IANA timezone strings (e.g., America/New_York) correctly handles daylight saving time transitions. Avoid using fixed UTC offsets (e.g., UTC-5) if your use case spans DST transitions.

Can I schedule individual messages and blasts from the same account?

Yes. Individual scheduled messages (scheduleType: "MESSAGE") and scheduled blasts (scheduleType: "BLAST") are tracked in the same list and managed with the same API — just filter by scheduleType to separate them.


Key Takeaways

  • All three message types: Schedule SMS, MMS, or RCS — individual messages or blasts — with the same schedule parameter
  • Timezone-aware: IANA timezone strings handle DST correctly; recipients get your message at the right local time
  • Recurring blasts: Cron expressions with optional endDate for weekly newsletters, monthly summaries, or any repeating campaign
  • Full management: List, view, and cancel scheduled messages via API or dashboard before they fire
  • Dashboard scheduling: Non-technical team members can schedule campaigns directly from the UI
  • Opt-out safety: Opt-out status is checked at send time — recipients who unsubscribe before a scheduled send don't receive it

Get Started

Schedule your first message from the dashboard or via the API. For recurring blast setup, see the blast SMS, blast MMS, and blast RCS references.

Not yet on Pinnacle? Sign up and subscribe to a plan. Questions about scheduling for high-volume campaigns or enterprise workflows? Get in touch or email founders@pinnacle.sh.

logo

© 2025 Pinnacle Software Development, Inc.