Unitpost
Inbound

Receive email, not just send it

Point MX at Unitpost and turn any address on your verified domain into a structured webhook. Parse, thread, and reply — all on the same pipeline, domain auth, and dashboard you already send with.

email.received
{
  "type": "email.received",
  "created_at": "2026-01-14T09:12:04.000Z",
  "data": {
    "email_id": "received_email_9f2c…",
    "from": "Ada <customer@acme.com>",
    "to": ["support@yourdomain.com"],
    "cc": [],
    "message_id": "<CA+123@mail.acme.com>",
    "subject": "Re: your invoice",
    "attachments": [
      {
        "id": "att_1a2b…",
        "filename": "receipt.pdf",
        "content_type": "application/pdf"
      }
    ]
  }
}

How it works

Sending, in reverse

Inbound mirrors the send pipeline: mail lands, we parse and persist it, then fan it out as a signed webhook you already know how to consume.

01

Point one MX record

Add a single MX record to a domain you already send from. No new domain, no separate account — you reuse the auth you've verified.

02

We parse the MIME

Every message is parsed — headers, text, HTML, and attachments — persisted, then routed on the to field. Catch-all: every address @your-domain lands.

03

You get one signed event

We POST an email.received event to your endpoint — same signing, retries, and delivery log as the webhooks you already consume.

One event, one handler

It's just another webhook

Inbound doesn't add a new mechanism to learn. A received message becomes an email.received event — the same signed, retried envelope as every other webhook, carrying metadata only so bodies and attachments never bloat your payloads.

  • Reuses your webhook endpoint

    Subscribe an existing endpoint to email.received — same signing secret, same retries.

  • Threads correctly

    The message_id and headers are captured so replies thread in the recipient's client.

POST https://acme.com/api/webhooksEnabled
Listening foremail.*Signing keywhsec_••••••••Attemptsauto-retry ×5
  • email.delivered
    1s200
  • email.opened
    2h200
  • email.bounced
    5h429
  • email.clicked
    8h200

Safe by default

Scanned, verified, and never in your payload

Every message is scanned and the verdicts ride along on the event. Bodies and attachments stay out of the webhook — fetch them over signed, expiring URLs when you need them. Confirmed viruses are rejected at ingest.

  • Spam & virus verdicts

    SES verdicts are flagged on every message; confirmed viruses are rejected before they land.

  • Attachments via signed URLs

    The event carries metadata only — fetch bytes over expiring REST download links.

  • SPF · DKIM · DMARC

    Authentication results are attached, so you can decide how much to trust a sender.

Message scan
  • Spam

    Flagged, never silently dropped

    spam_verdict
  • Virus

    Confirmed viruses rejected at ingest

    virus_verdict
  • SPF

    Sender-policy alignment

    spf_verdict
  • DKIM

    Signature validation

    dkim_verdict
  • DMARC

    Policy evaluation

    dmarc_verdict

Developer-first

Fetch the full message on demand

When you need more than metadata, read the parsed message over the same REST API and scoped keys you send with. Text and HTML come inlined; attachments come back as signed, expiring download URLs.

  • Parsed & structured

    Headers, text, HTML, and attachment metadata — already extracted from the MIME.

  • Signed downloads

    Attachment URLs expire in minutes, so links can't leak or be replayed.

Read a received email
import { Unitpost } from "unitpost";

const unitpost = new Unitpost(process.env.UNITPOST_API_KEY);

// The webhook carries metadata — fetch the parsed message on demand.
const email = await unitpost.emails.received.get("received_email_9f2c…");
console.log(email.subject, email.text, email.spam_verdict);

// Attachments come back as signed, expiring download URLs.
const file = await unitpost.emails.received.attachment(
  email.id,
  email.attachments[0].id,
);
console.log(file.url); // expires in 5 minutes

What you can build

Turn inbound mail into product

Once every message is a structured event, an inbox becomes an integration point.

Support inboxes

Turn support@ into structured events that open tickets in your helpdesk automatically.

Reply handling

Let users reply to notifications by email and thread their responses back into your app.

Parse & extract

Receive forwarded receipts, orders, or forms and pull structured data out of the MIME.

Email-to-action

Trigger a workflow — create a task, log an expense, kick off a build — from an inbound message.

Attachment intake

Collect documents by email and fetch them over signed URLs, never touching raw bytes.

Conversation history

Store the full thread alongside what you sent, in one activity view per contact.

Start free

Send and receive on your domain

$0/ mo

  • Inbound included on every paid plan
  • Reuses your verified domain auth
  • Signed email.received webhooks
  • Parsed bodies & attachments over REST