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",
});

if (scheduled.error) throw new Error("Could not schedule email");

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

Use the Effect SDK

schedule-email-effect.ts
import { Effect } from "effect";
import { FetchHttpClient } from "effect/unstable/http";
import { createClient } from "samva/effect";

const program = Effect.gen(function* () {
  const samva = yield* createClient({ apiKey: process.env.SAMVA_API_KEY! });
  const scheduled = yield* samva.scheduledMessages.create({
    payload: {
      send: {
        to: [{ email: "ada@example.com" }],
        channel: "email",
        email: { subject: "Reminder", html: "<p>See you tomorrow.</p>" },
      },
      scheduledFor: "2026-08-01T09:00:00Z",
    },
  });

  return yield* samva.scheduledMessages.get(scheduled.id);
}).pipe(Effect.provide(FetchHttpClient.layer));

await Effect.runPromise(program);

Use the REST API

curl -X POST https://api.samva.app/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 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 get <scheduled-message-id>
samva scheduled cancel <scheduled-message-id>

Use --template-slug <slug> --template-data '<json>' instead of the inline content flags to send a published template. samva scheduled 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