Skip to main content
POST
Schedule Email
Schedule a transactional email for future delivery, up to 30 days ahead. Accepts the same payload as POST /emails, including custom headers, with an additional required scheduled_at field. The response returns a Lettr ID that starts with sch_. Use it to get or cancel the email. transmission_id stays null until the email is actually sent, so don’t read it from the scheduling response. A scheduled email counts against your quota on the day it is sent, not the day you schedule it. The Idempotency-Key header is ignored on this endpoint.

Authorizations

Authorization
string
header
required

API key for authentication

Body

application/json

Schedule email request. Extends the standard send email request with a required scheduled_at field.

from
string<email>
required

Sender email address

Maximum string length: 255
Example:

"sender@example.com"

to
string<email>[]
required

Recipient email addresses

Required array length: 1 - 50 elements
Maximum string length: 255
Example:
scheduled_at
string<date-time>
required

The UTC date/time when the email should be sent. Must be at least 5 minutes in the future and within 30 days.

Example:

"2024-01-16T10:00:00Z"

from_name
string | null

Sender display name

Maximum string length: 255
Example:

"Sender Name"

subject
string | null

Email subject line. Required when not using a template. When using template_slug, defaults to the template's subject (or template name as fallback). If provided alongside a template, overrides the template subject.

Maximum string length: 998
Example:

"Welcome to Lettr"

cc
string<email>[]

Carbon copy recipient email addresses

Maximum string length: 255
Example:
bcc
string<email>[]

Blind carbon copy recipient email addresses

Maximum string length: 255
Example:
reply_to
string<email> | null

Reply-To email address

Maximum string length: 255
Example:

"reply@example.com"

reply_to_name
string | null

Reply-To display name

Maximum string length: 255
Example:

"Reply Name"

html
string | null

HTML content of the email. At least one of html or text is required, but providing both is recommended for best compatibility across email clients.

Example:

"<h1>Hello</h1><p>Welcome!</p>"

text
string | null

Plain text content of the email. At least one of html or text is required, but providing both is recommended for best compatibility across email clients.

Example:

"Hello\n\nWelcome!"

amp_html
string | null

AMP HTML content for supported email clients

project_id
integer | null

Project ID containing the template. If not provided when using template_slug, the team's default project will be used.

Example:

123

template_slug
string | null

Template slug to use for email content. When provided, the template's HTML will be used instead of the html field.

Maximum string length: 255
Example:

"welcome-email"

template_version
integer | null

Specific template version to use. If not provided, the active version will be used.

Required range: x >= 1
Example:

1

tag
string

Tag for tracking and analytics. Automatically set from template_slug if not provided.

Maximum string length: 64
Example:

"welcome-series-2024"

metadata
object

Custom metadata attached to the email for tracking purposes

Example:
headers
object

Custom email headers. Up to 10 headers allowed. Standard envelope headers (From, To, Subject, etc.), SparkPost internal headers (X-MSYS-API), and List-Unsubscribe and List-Unsubscribe-Post headers are managed by the system and cannot be set manually.

Example:
substitution_data
object

Variables for template substitution in email content

Example:
options
object

Email delivery options

attachments
object[]

File attachments. When provided, each attachment must include name, type, and data.

Response

Email scheduled for delivery. Free tier teams receive quota headers indicating their usage and limits.

message
string
required
Example:

"Email scheduled for delivery."

data
object
required

A scheduled email held by Lettr. This is the data object of POST /emails/scheduled, GET /emails/scheduled/{transmissionId} and DELETE /emails/scheduled/{transmissionId}, and each entry of scheduled_emails in GET /emails/scheduled.

Breaking change. Scheduled emails are no longer parked inside SparkPost with options.start_time — SparkPost retired its per-transmission GET and DELETE endpoints. Lettr now holds the email in its own store and injects it into SparkPost when it is due, so request_id is Lettr's own sch_... id, transmission_id is a separate field that stays null until injection, and state values are Lettr's own rather than SparkPost's pass-through states.