Inbound Email
Receive and process incoming emails on your verified domains. PostStack parses inbound messages and forwards them to your webhook endpoint or stores them for API retrieval.
Enabling Inbound Email
Enable inbound email on a verified domain by updating its settings. You will also need to add an MX record pointing to PostStack:
// Enable inbound email on a domain
const domain = await poststack.domains.update('dom_abc123def456', {
inbound_enabled: true,
});Add the following MX record to your DNS to receive inbound emails:
| Type | Name | Value | Priority |
|---|---|---|---|
| MX | yourdomain.com | inbound.poststack.dev | 10 |
Inbound email IDs are numeric (e.g. 7), and the base path is /inbound. Each message carries the sender as fromAddress (bare address) plus fromName (display name, or null), and the body as htmlBody / textBody.
/inboundList received inbound emails for the team, newest first. Supports page / per_page pagination and an optional domain filter (by domain name).
{
"data": [
{
"id": 7,
"domainId": 12,
"fromAddress": "sender@external.com",
"fromName": "Jane Sender",
"toAddress": "support+invoice-42@yourdomain.com",
"messageId": "<abc123@external.com>",
"subject": "Need help with my account",
"htmlBody": "<p>Hi, I need help resetting my password...</p>",
"textBody": "Hi, I need help resetting my password...",
"headers": { "date": "Mon, 23 Mar 2026 10:00:00 +0000" },
"createdAt": "2026-03-23T10:00:00.000Z",
"mailboxHash": "invoice-42",
"spamScore": 1.8,
"spamVerdict": "clean",
"strippedReply": "Thanks, that worked!"
}
],
"meta": {
"page": 1,
"perPage": 20,
"total": 48,
"totalPages": 3
}
}/inbound/:idRetrieve a single inbound email with full content. The response is wrapped in an inboundEmail key.
{
"inboundEmail": {
"id": 7,
"domainId": 12,
"fromAddress": "sender@external.com",
"fromName": "Jane Sender",
"toAddress": "support@yourdomain.com",
"messageId": "<abc123@external.com>",
"subject": "Need help with my account",
"htmlBody": "<p>Hi, I need help resetting my password...</p>",
"textBody": "Hi, I need help resetting my password...",
"headers": {
"date": "Mon, 23 Mar 2026 10:00:00 +0000"
},
"createdAt": "2026-03-23T10:00:00.000Z",
"mailboxHash": null,
"spamScore": 1.8,
"spamVerdict": "clean",
"strippedReply": "Hi, I need help resetting my password..."
}
}/inbound/:id/attachmentsList all attachments for an inbound email.
{
"attachments": [
{
"id": 1,
"filename": "screenshot.png",
"contentType": "image/png",
"size": 24576,
"createdAt": "2026-03-23T10:00:00.000Z"
}
]
}/inbound/:id/attachments/:aidDownload a specific attachment. Returns the raw file content with the appropriate Content-Type header. The SDK returns the bytes as a Uint8Array.
const bytes = await poststack.inboundEmails.downloadAttachment(7, 1);
await Bun.write('screenshot.png', bytes);/inbound/:id/replyReply to an inbound email. The reply is sent as a new outbound email with proper In-Reply-To headers.
{
"from": "Support <support@yourdomain.com>",
"html": "<p>Hi, I've reset your password. Please check your email.</p>",
"text": "Hi, I've reset your password. Please check your email.",
"cc": ["team@yourdomain.com"]
}/inbound/:id/forwardForward an inbound email (including its attachments) to one or more recipients.
{
"from": "Support <support@yourdomain.com>",
"to": ["escalation@yourdomain.com"],
"message": "Please take a look at this support request."
}Inbound Webhooks
Subscribe to the email.inbound webhook event to receive real-time notifications when inbound emails arrive:
// Create a webhook for inbound email events
await poststack.webhooks.create({
url: 'https://yourdomain.com/webhooks/inbound',
events: ['email.inbound'],
});Webhook Payload
The inbound webhook payload includes the parsed email summary plus three convenience fields so you don't have to re-parse the raw MIME. Fetch the full body and attachments with GET /inbound/:id.
{
"type": "email.inbound",
"created_at": "2026-03-23T10:00:00.000Z",
"data": {
"id": 12345,
"from": "sender@external.com",
"from_name": "Jane Sender",
"to": "support+invoice-42@yourdomain.com",
"subject": "Re: Need help with my account",
"domain": "yourdomain.com",
"mailbox_hash": "invoice-42",
"spam_score": 1.8,
"spam_verdict": "clean",
"stripped_reply": "Thanks, that worked!",
"received_at": "2026-03-23T10:00:00.000Z"
}
}Three fields save you a round of MIME parsing:
mailbox_hash— the plus-address tag of the recipient (support+invoice-42@ → invoice-42), for per-thread or per-user routing; null when the address has no tag.spam_scoreandspam_verdict("clean" or "spam") — the score our inbound spam filter assigned; both null if unavailable.stripped_reply— for replies, the new message text with the quoted history removed; null when there is no text body.