Skip to content
  • Transactional email
  • Resend-compatible API
  • Hosted in EU data centres
Transactional email · Resend-compatible API · Hosted in EU data centres

Your products.
One post office.

Send, receive, and follow every message from one calm workspace. Letterpier answers the Resend HTTP API for the endpoints it covers, so the Resend Node SDK works with a Letterpier key and one extra option: baseUrl.

Already have access? Sign in

Developer preview · Access by request only · Tested with resend@6.30.0 · See what’s covered

How a message moves through Letterpier (simulation)

Simulation of the message lifecycle. Outbound: your code calls POST /emails; the message is queued, handed to Postal, sent, and delivered when the recipient’s server accepts it; a signed email.delivered webhook follows. Messages can also be delayed, which Postal retries, or bounced, which adds the address to the suppression list. Inbound: mail to any address on a verified domain with receiving on arrives at Letterpier’s MX, is stored encrypted, triggers an email.received webhook, and your app fetches it with a full-access live key. This is an illustration, not live traffic.

LifecycleSimulated in your browser · not live traffic
  • Outbound
  • Inbound
send.ts
const mail = new Resend(process.env.LETTERPIER_API_KEY, {  baseUrl: 'https://app.letterpier.com',});await mail.emails.send({ from, to, subject, text });

200 · queued, not delivered

  1. +1.1 s submitting handing it to Postal
  2. +1.9 s email.sent Postal accepted it
  3. +2.6 s email.delivered the recipient’s server accepted it
  4. +3.0 s webhook 200 · attempt 1 of 8 · signed

Select a station to see what happens there.

Developer preview

Letterpier carries mail for its operator’s own products today. Other teams can request access; each request is reviewed by hand. Request access

01 · Send

Keep your code. Change one line.

Letterpier implements the parts of the Resend HTTP API that transactional products rely on. Point the unmodified Resend Node SDK at Letterpier and your send calls keep their shape.

The one line that changes. Everything else is the SDK you already use.
A key from your project. Keys starting with lp_test_ capture messages in the sandbox; keys starting with lp_live_ deliver.
Send from a domain you’ve verified in the same project.
Retry safely for 24 hours. Reusing a key with a different payload returns 409.
A 200 means queued, not delivered. Follow the rest in your logs or webhooks.
send.ts
import { Resend } from 'resend';const mail = new Resend(process.env.LETTERPIER_API_KEY, {  baseUrl: 'https://app.letterpier.com',});const { data, error } = await mail.emails.send({  from: 'My product <hello@your-verified-domain.com>',  to: 'customer@example.com',  subject: 'Welcome',  text: 'Your account is ready.',}, { idempotencyKey: 'welcome/customer-123' });

Also supported: batches of up to 100 messages, accepted all together or not at all · scheduling up to 30 days ahead, with reschedule and cancel while a message is queued · 50 recipients and 20 attachments per message · about 10 MB of attachments per request.

Tested with resend@6.30.0 for sending, receiving, domains, API keys and webhooks. Templates, contacts, broadcasts, audiences and other marketing APIs aren’t part of Letterpier; calls to them return an explicit error. See the compatibility table. Letterpier is not affiliated with Resend.

Rehearse without sending a thing.

Every project has sandbox and live keys. Sandbox messages are captured and never delivered, and your webhooks still receive synthetic events marked sandbox: true, so you can build the whole flow first. Live keys hand mail to Letterpier’s own Postal server for delivery.

Simulated in your browser · not live traffic

With a sandbox key

Sandbox

Keylp_test_…

With a live key

Live

Keylp_live_…

API key types
Key typeSending onlyFull access
SandboxSend, batch and schedule. Captured, never delivered.Also read, reschedule and cancel messages, and manage domains, keys and webhooks.
LiveSend, batch and schedule. Delivered through Postal.Also read, reschedule and cancel messages, read attachments, retrieve received mail, and manage domains, keys and webhooks.

Keys are stored as hashes and shown exactly once.

02 · Receive

Every address on your domain has somewhere to go.

Once a domain is verified with receiving on, mail to any address on it (support@, invoices@, anything@) lands in that domain’s project. Your app gets an email.received webhook, then fetches the body, the attachments and the original .eml with a full-access live key.

  • Routing uses the SMTP envelope recipient, not the visible To header.
  • Signed download links expire after 15 minutes.
  • Previews never run scripts, forms or remote content.
Simulated in your browser · not live traffic
@your-domain.example

TypeScript
const { data: email } = await mail.emails.receiving.get(event.data.email_id);
03 · Domains

DNS you can watch resolve.

Add a domain or a subdomain and Letterpier generates what it needs: an ownership TXT record, a 2048-bit RSA DKIM key, an SPF include, a return-path CNAME and a DMARC record, plus an MX record if the domain also receives mail. Then it checks them, and keeps checking.

Simulated in your browser · not live traffic

Example domain · simulated

Example DNS records for example.com, with receiving on
PurposeTypeNameValueStatus
OwnershipTXT
_letterpier-verification.example.com
letterpier-verification=4kR2PXsAcYYZpDKIYxqo6Nmc4VlFoEvAEYAhb_2ce8M
Verified
DKIMTXT
lp-mun3p042._domainkey.example.com
v=DKIM1; t=s; h=sha256; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB…
Show full keyv=DKIM1; t=s; h=sha256; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1eyP4OlEy30qwWLHT22UhA+2z8NWS/doZyomjiSsd72RXjVfRGAqhgoqzsfGZidYZ7Du4WfukcKCLNKB4tNaSkjJLdecHjdkBj3PE6JF9WThHGrKiQeIoN7EUmn9TwFU3nhn+VhudEoQ5H0UZd/WOqtTDUyCwMCj9OlD3bSjYRoUgI8TIJBkV8d6+zFThtWLHkmmfA9hkqDmZLTHa7dRcoPqiXXcNtKLxMiUXo1xQyFW6Ez9Aag7ZAxv5PJ43LX26iGoiaglZDW3703bIouvRTo/Pa7kvCiBhmFY3UaPooPswiwVFID7b0urlSmwkmvooNnOs2S9gEX5dCxJzcaaNQIDAQAB;
Verified
SPFTXT
example.com
v=spf1 include:spf.letterpier.com -all
Verified
Return pathCNAME
psrp.example.com
rp.letterpier.com
Verified
ReceivingMX
example.com
10 mail.letterpier.com
Verified
DMARCTXT
_dmarc.example.com
v=DMARC1; p=none;
Verified

6 of 6 records verified

  • Live sending needs a successful check from the last 24 hours.
  • Already have an SPF record? Merge the include into it and publish only one. Keep your existing DMARC policy.
  • Authentication helps receiving servers trust your mail. It can’t promise the inbox, and nothing can.
04 · Logs

Every message, every state, one log.

Search by recipient, sender or subject. Open any message to read its body, download its attachments and see what happened to it, in order.

Message statuses

Select a status to read what it means.

DeliveredSettled

The recipient’s mail server accepted it. That isn’t a promise of the inbox, and a bounce can still follow.

Solid: settled.

Dashed: the story isn’t over. Solid: settled. Hatched: not real mail.

Unknown is a state, not a shrug.

If a hand-off to Postal is interrupted, Letterpier never resends blindly. Check Postal acceptance looks the message up and reconciles it.

Permanent failures are remembered.

Addresses that bounce or fail permanently join the project’s suppression list, so the next send doesn’t repeat the mistake. You decide when to allow them again.

Example data
Recipient / subject / status
Outbound · 2 min agoada@example.comYour sign-in codeDelivered
Inbound · 5 min agosupport@your-domain.exampleQuestion about an invoiceReceived
Outbound · 12 min agograce@example.orgReceipt 1042Unknown
Outbound · 20 min agotest@example.comHello from the sandboxSandbox

Delivered means a receiving server accepted the message. It isn’t a promise of the inbox, and a bounce can still follow.

05 · Webhooks

Signed, retried, replayable.

Events carry Svix-format signatures (svix-id, svix-timestamp, svix-signature), so the Resend SDK’s webhooks.verify checks them unchanged. If your endpoint doesn’t answer, Letterpier tries again after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours: eight attempts over about 27½ hours. After that, replay any delivery from the dashboard while it’s retained.

Events

  • email.sent
  • email.delivered
  • email.delivery_delayed
  • email.bounced
  • email.failed
  • email.received
  • email.complained1
Example deliverySimulated in your browser · not live traffic
Retry schedule
AttemptWaits before itTime since the first (rounded)
1–0
25 s5 s
35 min5 min
430 min35 min
52 h2 h 35 min
65 h7 h 35 min
710 h17 h 35 min
810 h27 h 35 min

Headers of attempt 4 of 8

200 · delivered
svix-id:
msg_2Lh7cQ9
same on every attempt
svix-timestamp:
1790002105
changes on every attempt
svix-signature:
v1,Gm9s…
changes on every attempt

Delivery is at-least-once: deduplicate on svix-id.

  • Endpoints must be public HTTPS on port 443. Private addresses and redirects are refused.
  • Note 1: Complaint events can be tested in the sandbox today. No mailbox-provider feedback loop is connected yet.
06 · Projects

Each product gets a room of its own.

Organisations hold projects, and each project holds its own messages, domains, API keys, webhooks and suppressions. Nothing crosses between them, and each project gets its own Postal server credentials.

Organisation
  • Letterpier

    Project
    • Messages
    • Domains
    • API keys
    • Webhooks
    • Suppressions
  • Shinra Metrics

    Project
    • Messages
    • Domains
    • API keys
    • Webhooks
    • Suppressions
  • Reichweitenamt

    Project
    • Messages
    • Domains
    • API keys
    • Webhooks
    • Suppressions
Letterpier started as the post office for three of its operator’s own products.

API keys are stored as hashes and shown exactly once. Each key is sandbox or live, and sending-only or full access.

07 · Privacy

What we encrypt, and what we don’t.

We’d rather be exact than impressive.

Sample message
What you send
From
billing@example.com
To
grace@example.org
Subject
Receipt 1042
  • Hi Grace,
  • Thanks for your payment of €48.00.
  • Your receipt is attached. Its number is 1042.
  • The billing team

receipt-1042.pdf

What we store
From
billing@example.com
Plaintext · searchable
To
grace@example.org
Plaintext · searchable
Subject
Receipt 1042
Plaintext · searchable
  • Hi Grace,
  • Thanks for your payment of €48.00.
  • Your receipt is attached. Its number is 1042.Encrypted at rest
  • The billing team

receipt-1042.pdf

This is encryption at rest with keys the application manages. It is not end-to-end encryption.

Data at rest
DataAt restWhy
Message bodies and outbound attachmentsEncrypted, with keys the application manages
Received attachments and original .eml filesEncrypted, on a private volume
DKIM private keys (Letterpier’s copy)EncryptedPostal keeps its own copy in plaintext to sign mail.
Webhook signing secretsEncryptedShown once.
API keysStored as SHA-256 hashesShown once.
Subjects, addresses, event metadataPlaintextSo you can search your logs and we can route mail.
Mail inside Postal, our mail serverPlaintext, in its private databasePostal needs it to queue, sign and deliver. Raw mail is kept 7 days, metadata 30 days.

Data at rest

  • Message bodies and outbound attachments

    At rest
    Encrypted, with keys the application manages
  • Received attachments and original .eml files

    At rest
    Encrypted, on a private volume
  • DKIM private keys (Letterpier’s copy)

    At rest
    Encrypted
    Why
    Postal keeps its own copy in plaintext to sign mail.
  • Webhook signing secrets

    At rest
    Encrypted
    Why
    Shown once.
  • API keys

    At rest
    Stored as SHA-256 hashes
    Why
    Shown once.
  • Subjects, addresses, event metadata

    At rest
    Plaintext
    Why
    So you can search your logs and we can route mail.
  • Mail inside Postal, our mail server

    At rest
    Plaintext, in its private database
    Why
    Postal needs it to queue, sign and deliver. Raw mail is kept 7 days, metadata 30 days.
  • Retention 1–90 days per project, 30 by default
  • Deleting a message removes our copy and Postal’s
  • No open or click tracking
  • No newsletters, contacts or campaigns
  • Sign-in with six-letter email codes: 10 minutes, five attempts

Read the security overview

08 · Hosting

Where your mail lives.

The web app, the worker, Postal, its database and the encrypted attachment volume run on one OVH server in OVH’s Limburg, Germany data centre in the EU. The application database is Neon PostgreSQL on AWS in Frankfurt (eu-central-1). Vercel only registers our domain and serves its DNS.

Where a message goes
Providers
ProviderWhat it does for LetterpierWhereHeadquarters
OVHServer for the web app, worker, Postal, MariaDB and the encrypted attachment volumeEU data centre (Limburg, Germany)France
Neon (Databricks, Inc.)Application PostgreSQL databaseAWS eu-central-1, FrankfurtUSA
VercelDomain registration and DNS for letterpier.com; no message dataNoneUSA
Cloudflare R2Supported, not in useNoneUSA

Providers

  • OVH

    What it does for Letterpier
    Server for the web app, worker, Postal, MariaDB and the encrypted attachment volume
    Where
    EU data centre (Limburg, Germany)
    Headquarters
    France
  • Neon (Databricks, Inc.)

    What it does for Letterpier
    Application PostgreSQL database
    Where
    AWS eu-central-1, Frankfurt
    Headquarters
    USA
  • Vercel

    What it does for Letterpier
    Domain registration and DNS for letterpier.com; no message data
    Where
    None
    Headquarters
    USA
  • Cloudflare R2

    What it does for Letterpier
    Supported, not in use
    Where
    None
    Headquarters
    USA

Neon and Vercel are US-headquartered companies. Data is stored in EU data centres, but EU hosting on its own doesn’t mean EU-only access.

Mail you send travels to your recipients’ mail servers, wherever they are.

What we don’t claim

  • No uptime percentage or SLA.
  • No certifications and no independent security audit yet.
  • No guaranteed inbox placement. Nobody can promise the inbox.
  • EU hosting on its own doesn't make anything GDPR compliant, and we don't claim it does.

Deliberately small.

  • Not A newsletter tool: no contacts, lists or campaigns.

  • Not A tracker: no open or click tracking.

  • Not Open to everyone: access is by request only.

  • Not The whole Resend product: only the endpoints listed in the compatibility table.

Built for thoughtful sending.

Letterpier is run by Michael Ketzer in Germany for a small number of products. If yours sends transactional email and needs a calm place for it, tell us about it.

Letterpier is offered to businesses only.