# Lettr (https://email-sdk.dev/docs/adapters/lettr)



## Capabilities [#capabilities]

| Repeated headers | Idempotency | Scheduling | Personalized |
| ---------------- | ----------- | ---------- | ------------ |
| No               | `none`      | Yes        | `expanded`   |

These values come from the adapter's exported `capabilities` declaration. The [field support matrix](/docs/adapters/field-support) covers normalized message fields.

The Lettr adapter calls Lettr's `POST /emails` endpoint with plain `fetch`. Scheduled messages use `POST /emails/scheduled` instead. [Lettr](https://lettr.com/?utm_source=email-sdk.dev\&utm_medium=referral\&utm_campaign=sponsor) is a European email platform for SaaS products. It authenticates with a Bearer API key.

<ProviderBadge adapter="lettr" />

## Configure [#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.

```ts title="lib/email.ts"
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! })],
});
```

<TypeTable
  type="{
  apiKey: {
    description: &#x22;Lettr API key, sent in the Authorization Bearer header.&#x22;,
    type: &#x22;string&#x22;,
    required: true,
  },
  baseUrl: {
    description: &#x22;Override the API origin, e.g. for a proxy.&#x22;,
    type: &#x22;string&#x22;,
    default: '&#x22;https://app.lettr.com/api&#x22;',
  },
  fetch: {
    description: &#x22;Custom fetch implementation for tests or special runtimes.&#x22;,
    type: &#x22;typeof fetch&#x22;,
  },
  headers: {
    description: &#x22;Extra headers merged into every request.&#x22;,
    type: &#x22;Record<string, string>&#x22;,
  },
}"
/>

## Send [#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.

```ts
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_id
```

<Callout type="warn" title="One 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.
</Callout>

<Callout title="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`.
</Callout>

## Schedule a send [#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.

```ts
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 [#verify-from-the-cli]

```bash
LETTR_API_KEY="lttr_..." npx email-sdk doctor --adapter lettr
```

```bash
LETTR_API_KEY="lttr_..." npx email-sdk send \
  --adapter lettr \
  --from "Acme <hello@acme.com>" \
  --to user@example.com \
  --subject "Lettr smoke test" \
  --text "It works" \
  --dry-run
```

Drop `--dry-run` to send for real. Use a sandbox key when you want the message delivered to your own inbox.
