Email

Schedule an email

Schedule one email for an absolute future instant, then inspect or cancel it before dispatch begins.

Use a scheduled message when the recipients and content are already known and the email should send later. This is a separate resource from an immediate send. messages.send has no scheduling field.

Choose the time and content

scheduledFor must be a future absolute ISO-8601 instant with Z or a numeric offset, for example 2026-08-01T09:00:00Z or 2026-08-01T14:30:00+05:30. A local date-time without an offset is rejected.

timezone is optional validated IANA metadata for display and audit. It never converts or reinterprets scheduledFor.

Choose exactly one content source:

  • Inline email requires subject and html; text is an optional fallback.
  • Template email references exactly one published template by templateSlug or templateId, with optional templateData. Omit inline subject, html, and text.

Use the Promise SDK

schedule-email.ts
import { createClient } from "samva";

const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });
const scheduled = await samva.scheduledMessages.create({
  send: {
    to: [{ email: "ada@example.com" }],
    channel: "email",
    email: {
      subject: "Your appointment is tomorrow",
      html: "<p>We will see you at 9:00.</p>",
      text: "We will see you at 9:00.",
    },
  },
  scheduledFor: "2026-08-01T09:00:00Z",
  timezone: "America/New_York",
  idempotencyKey: "appointment-ada-2026-08-01",
});

await samva.scheduledMessages.cancel({ id: scheduled.id });

Use the Effect SDK

schedule-email-effect.ts
import { Effect } from "effect";
import * as Client from "samva/effect/client";
import * as ScheduledMessages from "samva/effect/scheduled-messages";

const program = Effect.gen(function* () {
  const scheduled = yield* ScheduledMessages.create({
    send: {
      to: [{ email: "ada@example.com" }],
      channel: "email",
      email: { subject: "Reminder", html: "<p>See you tomorrow.</p>" },
    },
    scheduledFor: new Date("2026-08-01T09:00:00Z"),
    timezone: "America/New_York",
    idempotencyKey: "reminder-ada-2026-08-01",
  });

  return yield* ScheduledMessages.get({ id: scheduled.id });
}).pipe(Effect.provide(Client.layerFetch({ apiKey: process.env.SAMVA_API_KEY! })));

await Effect.runPromise(program);

Use the REST API

curl -X POST https://api.samva.dev/v1/messages/scheduled \
  -H "X-API-Key: $SAMVA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "send": {
      "to": [{ "email": "ada@example.com" }],
      "channel": "email",
      "email": { "subject": "Reminder", "html": "<p>See you tomorrow.</p>" }
    },
    "scheduledFor": "2026-08-01T09:00:00Z",
    "timezone": "America/New_York",
    "idempotencyKey": "reminder-ada-2026-08-01"
  }'

Use GET /v1/messages/scheduled/{id} to inspect the schedule and POST /v1/messages/scheduled/{id}/cancel to cancel it. See the generated scheduled messages reference for schemas and response fields.

Use the CLI

samva scheduled-messages create --to ada@example.com \
  --subject "Reminder" --html "<p>See you tomorrow.</p>" \
  --at 2026-08-01T09:00:00Z --timezone America/New_York \
  --idempotency-key reminder-ada-2026-08-01
samva scheduled-messages get <scheduled-message-id>
samva scheduled-messages cancel <scheduled-message-id> --yes

Use --template-slug <slug> --template-data '<json>' instead of the inline content flags to send a published template. samva scheduled-messages create --dry-run validates and prints the request without calling the API.

Use MCP

Ask the agent to call samva_scheduled_messages_schedule_email with to, one valid content source, and scheduledFor. It can inspect the result with samva_scheduled_messages_get or samva_scheduled_messages_list, and cancel it with samva_scheduled_messages_cancel.

Cancellation, errors, and usage

A scheduled email can be cancelled only while its status is pending. Once dispatch begins, cancellation returns a conflict. At dispatch, it follows the normal email send path and usage semantics. Validation failures do not create a schedule; provider and delivery outcomes appear on the resulting message after dispatch. Handle authentication, validation, not-found, conflict, and usage-limit errors as described in the error reference.

On this page