ThreadCamp
Start free
Inbound email

Receive and parse inbound email programmatically

Create an inbox, point your domain's MX at ThreadCamp, and read inbound mail via HMAC-signed webhooks or polling. Messages are parsed and threaded for you; Routes can forward or trigger code.

Start free - no cardRead the docs

Three steps: inbox, MX, consume

Receiving mail programmatically comes down to three things: a place for the mail to land, a way for the internet to route mail there, and a way for your code to read it. In ThreadCamp that is an inbox, your domain's MX records pointed at us, and either a webhook or a poll. You do not run an SMTP server, parse MIME by hand, or manage a mailbox on disk.

# 1. Create an inbox
curl https://threadcamp.vercel.app/v1/inboxes \
  -H "Authorization: Bearer sk_live_..." \
  -d '{ "domain": "acme-agents.email", "display_name": "Support" }'
# -> { "id": "inbox_...", "address": "support@acme-agents.email" }

# 2. Point your domain's MX at ThreadCamp (from POST /v1/domains), then verify.
# 3. Inbound mail now arrives as a signed webhook:
#    POST https://your-app.com/hooks/threadcamp
#    { "type": "message.received",
#      "data": { "inbox_id": "inbox_...", "thread_id": "thr_...",
#                "from": "customer@example.com", "subject": "Help",
#                "text": "...", "attachments": [ ... ] } }

Messages are parsed and threaded

Every inbound message is decoded for you: headers, plain text, HTML, and attachments become first-class fields, and the message is attached to a thread so a reply from the same correspondent lands in the same conversation. That matters for agents, which need conversation state to reply coherently rather than treating each email as an isolated event.

Verify the webhook signature

Inbound webhooks are HMAC-signed. Before you trust a payload, recompute the signature over the exact raw bytes you received and compare it in constant time - never parse the JSON first and never use a plain string equality check that can leak timing. Reject anything that does not match, so a forged POST to your endpoint cannot inject a fake inbound email.

import crypto from "node:crypto";

// Verify the HMAC signature on an inbound ThreadCamp webhook
export function isValid(rawBody: string, signature: string, secret: string) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody, "utf8")
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

Or wait for one specific message

For short-lived jobs - an agent completing a signup, a test asserting that a notification arrived - polling is simpler than standing up a webhook endpoint. wait_for_message blocks until a message matching your filter (sender, subject) arrives or a timeout elapses, which is the clean primitive for retrieving an OTP mid-task.

Related

Keep reading

One email API

Send, receive and forward behind one key.

OTP retrieval agent

Retrieve one-time passcodes mid-task.

SRS email forwarding

Keep SPF and DMARC on a forward.

Questions

How do I receive email programmatically?

Create an inbox with POST /v1/inboxes, point your domain's MX records at ThreadCamp, and consume inbound mail either by subscribing to the message.received webhook or by polling the messages endpoint. Each message is parsed into headers, text, HTML and attachments and attached to a thread.

Webhooks or polling - which should I use?

Webhooks are the default: message.received is delivered as an HMAC-signed POST within moments of the mail landing, which suits event-driven agents. Polling suits short-lived tasks and tests - list the inbox's messages, or use wait_for_message to block until a specific email arrives.

How do I verify an inbound webhook is genuine?

Each webhook carries an HMAC signature over the raw body using your endpoint's signing secret. Recompute the HMAC on the bytes you received and compare in constant time before trusting the payload. Reject anything that does not match.

Start reading inbound mail today.

No credit card. Full API, MCP and webhooks on the free tier.

Start freeRead the docs