support@yourcompany.com, each message reaches your application as a ticket, and agents’ answers go back into the same conversation. Inbound email posts each message to your application as JSON and the send API sends the reply, so there is no mail server to run and no IMAP mailbox to poll.
How the Flow Works
Step 1: Pick an Address Layout
Use a dedicated subdomain for the support inbox, such assupport.example.com. Mail to any address at an inbound domain goes to the same forwarding URL, so help@, billing@ and anything@ all arrive at one endpoint and are routed in code.
A subdomain also keeps your root domain’s MX records pointing at your regular mailbox provider (Google Workspace, Microsoft 365), so staff email is unaffected.
Step 2: Build the Receiving Endpoint First
The forwarding URL is required. When you create the inbound domain, Lettr tests it with aPOST request and refuses to create the domain unless your endpoint answers with a 2xx status. The endpoint therefore has to exist and be publicly reachable before the domain is created in the dashboard.
Start with an endpoint that verifies the auth token and acknowledges the request:
An endpoint behind a firewall or WAF that challenges unknown clients (a Cloudflare
403, for example) fails the test: the dashboard shows the status your endpoint returned and the domain is not created. Allow server-to-server POST requests on that path. Lettr’s mail infrastructure publishes no fixed source IP addresses, so rely on the auth token rather than an IP allowlist. See Security.Step 3: Create the Inbound Domain and MX Records
1
Create the inbound domain
In the dashboard, go to Domains → Inbound and click Create Inbound Domain. Enter the Domain Name (
support.example.com), your Forwarding URL (https://yourapp.com/webhooks/inbound) and an Auth token. The token is sent to your endpoint in the X-MessageSystems-Webhook-Token header.2
Add the MX records
Add the three MX records the dashboard shows to your DNS. For a subdomain, set the host to
support.All three are required.
3
Verify
Click Verify MX Records on the domain’s page. When both the MX records and the forwarding URL are in place, the page shows This domain is receiving mail.
Step 4: Turn a Relay Message into a Ticket
Each request body is a JSON array. Every element carries one message inmsys.relay_message:
There is no attachments array. Attachments live only inside
email_rfc822, so parse it with a MIME library such as mailparser when you need them. See Attachments.
Reply-To header, then the address in friendly_from, with msg_from only as a last fallback. Store each inbound Message-ID, because Step 6 needs it to reply in-thread. Lettr’s send API returns a request_id, not the Message-ID of the email it sent, so the stored IDs come from the customer’s messages. For the complete field list see Email Parsing.
Step 5: Filter Spam in Your Handler
A public support address receives spam, bounce notices and auto-replies, and all of it reaches the handler. Three rules keep the queue clean:- Always answer
2xx, including for messages you drop. The mail was already accepted by the time it reaches you, so an error status cannot reject it back to the sender. It only makes the delivery to your endpoint look failed. - Treat sender fields as claims.
msg_fromandfriendly_fromare set by whoever sent the message. When the receiving server added anAuthentication-Resultsheader, admarc=failis a strong signal. A missing header means “unknown”, not “pass”. - Skip automatic mail. Don’t open tickets for auto-replies, and never auto-reply to them, or two autoresponders can loop.
Step 6: Reply with the Send API
Replies written in your ticket UI go out throughPOST /emails. Three details make the reply land in the customer’s existing conversation:
frommust be an address on a verified sending domain. The inbound domain is for receiving. Sending is configured separately under sending domains.reply_tois the support address on your inbound domain, so the customer’s next message comes back to your endpoint. To tie the reply to a ticket, put the ticket ID in it with a plus-style address such assupport+t-4821@support.example.com, then read it fromrcpt_to. Use lowercase letters, digits and hyphens in the ID.headerscan carryIn-Reply-ToandReferences. The send API allows both: it blocks only a fixed list of headers it manages itself (such asFrom,To,Subject,Message-ID,Reply-ToandList-Unsubscribe) and accepts up to 10 custom headers, each a string up to 998 characters. SetIn-Reply-Toto the customer’s lastMessage-IDandReferencesto theirReferencesvalue followed by thatMessage-ID.
Idempotency-Key header means a retry after a network error doesn’t email the customer twice. Keep the Re: prefix and the original subject too: some clients thread by subject when headers are missing or rewritten.
Threading with
In-Reply-To and References depends on the customer’s mail client. Most honor it, but Lettr can’t guarantee how a given client groups messages. The reply address and subject are the reliable parts. Don’t depend on custom headers such as X-Ticket-ID for matching: clients don’t copy them into replies.from address will receive customer replies too, don’t send replies from no-reply@. Use a monitored address, and set reply_to so answers reach the inbox you built.
Common Problems
The domain won't create: 'Your forwarding URL answered SparkPost with HTTP 403'
The domain won't create: 'Your forwarding URL answered SparkPost with HTTP 403'
A firewall or WAF is blocking the test
POST. Allow server-to-server requests on the forwarding URL’s path and try again. The domain is created only after your endpoint answers 2xx.MX records verify, but no tickets appear
MX records verify, but no tickets appear
Check the domain’s status. No forwarding URL means mail is accepted and discarded. Open the Mail Forwarding card and add one. Also confirm your handler returns
2xx and doesn’t throw on messages with only an HTML part.Mail to the domain goes to the wrong server
Mail to the domain goes to the wrong server
A domain without MX records falls back to its A record, so mail lands on your web host. Add all three MX records and re-run Verify MX Records. Allow time for DNS propagation.
Replies start new tickets instead of joining the thread
Replies start new tickets instead of joining the thread
Match on more than one signal: the ticket ID in the
reply_to address first, then In-Reply-To and References against stored Message-ID values, then a subject token. Customers edit subjects and some clients drop headers.Related Topics
Inbound Email Setup
Create the inbound domain, MX records and forwarding URL
Reply Tracking
Match replies to the emails you sent
Spam Filtering
Build spam handling into your forwarding URL
Inbound Security
Verify the auth token and validate content