Lettr
Send through Lettr's SaaS email API with CC, BCC, reply-to, headers, metadata, a single tag, attachments, and scheduled delivery.
Capabilities
| Repeated headers | Idempotency | Scheduling | Personalized |
|---|---|---|---|
| No | none | Yes | expanded |
These values come from the adapter's exported capabilities declaration. The field support matrix covers normalized message fields.
The Lettr adapter calls Lettr's POST /emails endpoint with plain fetch. Scheduled messages use POST /emails/scheduled instead. Lettr is a European email platform for SaaS products. It authenticates with a Bearer API key.
Configure
Create a Lettr API key (prefixed lttr_ or lttr_sandbox_) and verify the sending domain for live keys. Sandbox keys rewrite the sender domain to dev.uselettr.com and deliver to the key owner's inbox.
import { createEmailClient } from "@opencoredev/email-sdk";
import { lettr } from "@opencoredev/email-sdk/lettr";
export const email = createEmailClient({
adapters: [lettr({ apiKey: process.env.LETTR_API_KEY! })],
});Prop
Type
Send
Lettr accepts multiple recipients, CC, BCC, one reply-to, custom headers, metadata, one tag, and base64 attachments. Display names on from and replyTo map to from_name and reply_to_name. Recipient addresses are sent as bare emails.
const result = await email.send({
from: "Acme <hello@acme.com>",
to: "user@example.com",
subject: "Welcome to Acme",
html: "<p>Thanks for joining Acme.</p>",
text: "Thanks for joining Acme.",
});
console.log(result.id); // Lettr request_idOne tag, one reply-to, no inline images
Lettr stores a single tag string per email. The adapter sends the first tag's value and
throws if a message has more than one tag, more than one reply-to, more than 10 custom
headers, an inline attachment, or a recipient display name. Combined to, cc, and bcc
cannot exceed 50 addresses.
From a verified sending domain
Live keys require a verified sender domain. Sandbox keys skip that check and rewrite the
domain to dev.uselettr.com.
Schedule a send
Pass sendAt to use Lettr's scheduled endpoint. Lettr requires the time to be at least five minutes in the future and within three days.
await email.send({
from: "Acme <hello@acme.com>",
to: "user@example.com",
subject: "Reminder",
text: "Don't forget.",
sendAt: new Date("2026-09-01T09:00:00.000Z"),
});Verify from the CLI
LETTR_API_KEY="lttr_..." npx --package @opencoredev/email-sdk email-sdk doctor --adapter lettrLETTR_API_KEY="lttr_..." npx --package @opencoredev/email-sdk email-sdk send \
--adapter lettr \
--from "Acme <hello@acme.com>" \
--to user@example.com \
--subject "Lettr smoke test" \
--text "It works" \
--dry-runDrop --dry-run to send for real. Use a sandbox key when you want the message delivered to your own inbox.
Frequently asked questions
Does Email SDK support Lettr?
Yes. Email SDK ships a Lettr adapter imported from @opencoredev/email-sdk/lettr. You keep your Lettr account and credentials; the SDK adds message validation, typed errors, and no-network test adapters around the same send() call used for every other provider.
Which message fields does the Lettr adapter support?
Lettr supports every normalized message field: CC recipients, BCC recipients, Reply-To address, Custom headers, Attachments, Tags, Metadata, and Scheduled sending (sendAt).
Can Lettr schedule email for later with Email SDK?
Yes. Set sendAt on the message and the Lettr adapter passes the scheduled time to the provider.
Does the Lettr adapter support idempotent sends?
No. Lettr has no provider-side idempotency, so a retried send can be delivered twice. Deduplicate in your own queue before retrying.