Use a subdomain for inbound
Receiving on reply.acme.com leaves the MX records of your main mailbox domain untouched.
Point a domain’s MX records at Sendix and every message sent to it is parsed — headers, text, html and attachments — and handed to your app through a signed webhook and the receiving API.
import crypto from "node:crypto";
export async function POST(req: Request) {
const raw = await req.text(); // verify before parsing
const sig = Object.fromEntries(
(req.headers.get("x-sendix-signature") ?? "")
.split(",").map((part) => part.split("=")),
);
const expected = crypto
.createHmac("sha256", process.env.SENDIX_WEBHOOK_SECRET!)
.update(sig.t + "." + raw)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(sig.t)) < 300;
const valid = fresh && sig.v1?.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected));
if (!valid) return new Response("invalid signature", { status: 401 });
const event = JSON.parse(raw);
if (event.type === "email.received") await routeInbound(event);
return new Response("ok");
}Enable receiving on a verified domain, publish the MX records Sendix shows, and subscribe a webhook to email.received. Each message is then available as parsed data through GET /v1/emails/receiving/{id} (attachments under /attachments), can be forwarded by rules created with POST /v1/emails/receiving/forwarding, and can be answered with POST /v1/emails/receiving/{id}/reply.
What your code does, what Sendix does, and where to look when something goes wrong.
Turn on receiving for a verified domain — ideally a subdomain such as reply.acme.com.
Add the MX records from the domain page; Sendix checks them and reports receiving health.
Create a webhook, verify X-Sendix-Signature on every delivery, then fetch the parsed message and attachments.
Attach the message to a ticket or thread, forward it with a rule, or answer it through the reply endpoint.
Habits that protect deliverability and your users, whichever provider you use.
Receiving on reply.acme.com leaves the MX records of your main mailbox domain untouched.
Check the HMAC-SHA256 signature over t + "." + raw body in constant time and reject timestamps older than five minutes.
Match replies to conversations with the Message-ID, In-Reply-To and References headers of the parsed message.
Acknowledge the webhook quickly, then download attachments from the receiving API in a background job.
Webhook deliveries can be retried or replayed; store the event id before doing slow work.
GET /v1/emails/receiving/health shows whether inbound is configured and flowing for your domains.
Sendix signs each webhook with X-Sendix-Signature and keeps the same events on the message at GET /v1/emails/{id}/events.
| Event | What to do with it |
|---|---|
| email.received | What to do with itA message arrived on a receiving-enabled domain. |
Short answers to the questions teams ask while wiring this up.
No. Enable receiving on a subdomain (for example reply.acme.com) and publish MX records only there; mail to your main domain keeps flowing to your existing mailbox provider.
Yes. Forwarding rules are managed through /v1/emails/receiving/forwarding, so messages you don’t process in code can still reach a person.
Yes. POST /v1/emails/receiving/{id}/reply sends a reply to the original message from your verified domain.
Yes. List them with GET /v1/emails/receiving/{id}/attachments and download each file by its attachment id.
The free plan includes 1,000 emails per month. Paid plans change volume and limits, not your API calls or SMTP settings.
1,000 emails free every month. No credit card required. Upgrade only when you outgrow the free tier — and we will let you know when that time comes.
Managed SaaS platform · Native SMTP engine · SOC 2 in progress