Sending

Inbound email

Receive mail on your domains — parsed and pushed to your webhook, with a pull API to back it up.

Inbound is opt-in per domain— enable it only on the domains you want to receive on. Already using another service for a domain's mail? Leave it off there and nothing changes. Sending is never affected.

Point an MX record at Sendara and every email to that domain is received, scanned, parsed into structured fields (from, to, subject, text, HTML, attachments) and delivered to you two ways: a real-time email.received webhook, and a GET /v1/inbound pull API.

Enable a domain

Receiving is enabled on a verified domain. Enabling returns the MX record to publish at your DNS provider.

An MX record routes all mail for that domain to Sendara. If you already use email (Google Workspace, etc.) on your main domain, enable a subdomain like inbound.yourdomain.com instead so your existing mail is untouched.
curl -X POST https://api.sendara.dev/v1/domains/dom_abc123/inbound \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
enabledbooleanRequired
Turn receiving on or off for the domain. Enabling returns the MX record to publish.
{ "enabled": true, "mx_record": { "type": "MX", "priority": "10", "value": "inbound-smtp.us-east-1.amazonaws.com" } }

Prefer zero setup? Every account also has a hosted test inbox at <account_id>@inbound.sendara.dev — email it from anywhere to see receiving work with no DNS changes.

The email.received webhook

Subscribe a webhook to the email.received event. Each received message is delivered as a signed POST (verified exactly like every other Sendara webhook). Like every event, it arrives wrapped in the standard envelope — top-level keys are event_id / event_type, and the inbound email lives under payload (abbreviated below; the full payload also carries cc, headers, size_bytes, thread_id, rfc_message_id, in_reply_to, references_ids, normalized_subject, and an s3_key on each attachment):

{
  "event_id": "evt_inb_9f21",
  "event_type": "email.received",
  "message_id": "inb_9f21",
  "account_id": "acct_abc123",
  "payload": {
    "id": "inb_9f21",
    "domain": "inbound.yourdomain.com",
    "recipient": "[email protected]",
    "from": "Alice <[email protected]>",
    "to": ["[email protected]"],
    "cc": [],
    "subject": "Need help with my order",
    "text": "Hi, my order hasn't arrived…",
    "html": "<p>Hi, my order hasn't arrived…</p>",
    "spf_verdict": "PASS",
    "dkim_verdict": "PASS",
    "dmarc_verdict": "PASS",
    "spam_verdict": "PASS",
    "virus_verdict": "PASS",
    "size_bytes": 84992,
    "thread_id": "thr_5c10",
    "attachments": [{ "filename": "receipt.pdf", "content_type": "application/pdf", "size": 84211, "s3_key": "inbound/acct_abc123/inb_9f21/receipt.pdf" }],
    "received_at": "2026-06-17T10:02:00Z"
  },
  "occurred_at": "2026-06-17T10:02:00Z",
  "created_at": "2026-06-17T10:02:01Z"
}
Sendara scans every inbound message — SPF, DKIM and DMARC results plus spam and virus verdicts ride along on each event, and messages flagged as a virus are dropped before they ever reach you.

Pull API

List and fetch received mail over the API — useful for backfill or if you'd rather poll than run a webhook.

# list recent inbound emails (bodies omitted)
curl https://api.sendara.dev/v1/inbound \
  -H "Authorization: Bearer sk_live_xxx"

# fetch one with full body + attachments metadata
curl https://api.sendara.dev/v1/inbound/inb_9f21 \
  -H "Authorization: Bearer sk_live_xxx"

# download an attachment by index
curl https://api.sendara.dev/v1/inbound/inb_9f21/attachments/0 \
  -H "Authorization: Bearer sk_live_xxx" -o receipt.pdf

Routing rules

By default every received message fires email.received to your subscribed webhooks. Routing rules let you also forward specific addresses to a dedicated endpoint — e.g. support@ to your ticketing system and billing@ elsewhere.

curl https://api.sendara.dev/v1/inbound/routes \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "inbound.yourdomain.com",
    "match_prefix": "support",
    "forward_url": "https://app.yourcompany.com/hooks/inbound"
  }'
domainstringRequired
A receiving domain you own.
match_prefixstringOptional
The local-part to match (e.g. support), or * for every address. Defaults to *.
forward_urlstringRequired
An https endpoint that receives the matched mail. Each POST is HMAC-signed with the route's secret (returned once on create).

The response includes a signing_secret (shown once). Each forwarded POST carries a combined Sendara-Signature: t=<ts>,v1=<hmac> header (Stripe-style): split on ,, take the t= timestamp and v1= signature, then recompute an HMAC-SHA256 over "<t>.<rawBody>" with the route's signing_secret and compare in constant time.

This route-forward signature is not the same scheme as a standard Sendara webhook. Subscribed webhooks use a bare hex signature in Sendara-Signature plus a separate Sendara-Timestamp header — so the SDK verifyWebhook helpers apply to those, not to route forwards. Verify route forwards with the combined-header steps above.