Documentation
MAIL / INBOUND

Receive mail and read threads

Work with incoming messages, labels, complete threads, and real-time notifications.

How receiving starts

Incoming mail reaches Startup Mail after the domain’s MX record is verified and a matching mailbox exists. You can optionally configure a domain catch-all mailbox, which receives mail sent to unconfigured addresses at that domain. The delivered message retains its original recipient address; catch-all does not create a new sending identity.

Configure it from Settings → Domains → Catch-all routing, or with an organization-scoped key:

EXAMPLE
await mail.setDomainCatchAll("dom_123", "mbx_support");
// Pass null to turn the route off.

List threads

Use GET /v1/threads or mail.listThreads(). Omit mailboxId for a combined inbox across every mailbox the credential can read, or filter with a mailbox ID. Use one of these labels: inbox, starred, sent, important, archive, spam, or trash. Search runs across stored sender, recipient, subject, snippet, and plain-text message content.

EXAMPLE
const page = await mail.listThreads({
  mailboxId: "mbx_123",
  label: "inbox",
  search: "quarterly plan",
});

const next = page.nextCursor
  ? await mail.listThreads({ mailboxId: "mbx_123", cursor: page.nextCursor })
  : null;

A page contains up to 50 thread summaries and a nextCursor when older results remain. A thread summary includes its mailbox and delivered-to address as well as subject, snippet, sender, last-message time, unread and message counts, starred state, and whether any message in the thread has attachments.

Read a complete thread

Use GET /v1/threads/:id or mail.getThread(threadId). The response contains messages in the conversation, including direction, delivery status, Reply-To and recipient addresses, authentication results, plain and cleaned HTML bodies, timestamps, failure details, and attachment metadata.

Access is checked when the thread is requested. Knowing a thread ID does not bypass private mailbox permissions.

React without polling

Subscribe to message.received with a signed webhook. Its payload identifies the mailbox, thread, and message so your worker can fetch the complete thread using mail:read scope.