SNDR
Send transactional email through the SNDR HTTP API with createMailer.
Use SNDR when you want an HTTP email API for receipts, sign-in mail, and other app-triggered messages.
Wire SndrTransport into createMailer — do not call the vendor SDK from application code.
The one rule
Import from sently/transports/sndr, pass the transport to await createMailer(...), and send
with the mailer — keep delivery on the email channel.
Quick start
Configure
import { createMailer } from "sently/mailer";
import { SndrTransport } from "sently/transports/sndr";
const mailer = await createMailer({
transport: new SndrTransport({
apiKey: process.env.SNDR_API_KEY!,
}),
});Send
const result = await mailer.send({
from: "hello@yourdomain.com",
to: "customer@example.com",
subject: "Welcome aboard",
html: "<p>Thanks for joining us.</p>",
});See the result
console.log(result.messageId); // e.g. em_…
console.log(result.response); // e.g. queuedfrom must use a domain verified in the SNDR dashboard.
Configuration
| Option | Type | Default | Meaning |
|---|---|---|---|
apiKey | string | required | Bearer key (sndr_live_… / sndr_test_…). |
baseUrl | string | https://api.sndr.sh | API origin (no trailing slash needed). |
defaultTemplateId | string | — | Default SNDR template_id when not set per message. |
Message mapping
| Mail option | SNDR field | Notes |
|---|---|---|
from | from | MIME form Name <addr> when a display name is present. |
to / cc / bcc | to / cc / bcc | Arrays of email addresses. |
replyTo | reply_to | First address only. |
subject | subject | Required. |
html / text | html / text | Optional body fields. |
headers | headers | Custom headers; template header is stripped. |
idempotencyKey / messageId | Idempotency-Key | Sent when present. |
data | variables | Only when a template id is set. |
Templates
Set a template with the x-sndr-template-id header (or defaultTemplateId on the transport).
Pass template variables through data.
import { SNDR_TEMPLATE_ID_HEADER } from "sently/transports/sndr";
await mailer.send({
from: "hello@yourdomain.com",
to: "customer@example.com",
subject: "Welcome",
headers: { [SNDR_TEMPLATE_ID_HEADER]: "tpl_welcome" },
data: { name: "Ada" },
});Verify and errors
verify() calls GET /v1/domains with the same Bearer key.
Failed HTTP responses throw SndrError (SentlyError) with the API error.message when present.
Troubleshooting
SNDR rejects sends from unverified domains. Verify DNS in the SNDR dashboard, then retry with that domain in from.
No. Use sently/transports/sndr. The main sently package does not re-export HTTP provider transports.
No. Use createMailer plus SndrTransport. Keep vendor extras off the shared email contract.
Learn more
- Email channel — mailer options and send pipeline
- Webhooks — SNDR delivery events and signature verification
- Bundle size — why subpath imports stay small