Inbound Webhooks
Inbound Webhooks
Postscale can parse incoming emails and deliver them to your application via webhooks. This enables powerful use cases like support ticket systems, reply detection, and email-based workflows.
Setup
- Configure your domain's MX records to point to Postscale.
- From the dashboard, open Webhooks, click Add Webhook, point it at
your endpoint URL, and check
email.received(any other events you want are also fine — one webhook can subscribe to many). - Copy the signing secret (
whsec_…) shown in the dialog. It is only displayed once; save it in your secrets manager.
You can also create the webhook via API:
curl -X POST https://api.postscale.io/v1/webhooks \
-H "Authorization: Bearer ps_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/postscale-inbound",
"events": ["email.received"]
}'
The response body contains the webhook record and the plaintext secret.
Save it then — GET /v1/webhooks will not return it again.
Webhook Payload
When an email arrives, Postscale POSTs a JSON body like this to your endpoint:
{
"event": "email.received",
"timestamp": "2026-04-25T10:30:00Z",
"email_id": "0c1f2a3b-…",
"message_id": "<unique-id@example.com>",
"from": "customer@example.com",
"to": "support@yourapp.com",
"subject": "Help with my order",
"text": "Hi, I need help with order #12345...",
"html": "<p>Hi, I need help with order #12345...</p>",
"headers": [
{ "name": "Message-ID", "value": "<unique-id@example.com>" },
{ "name": "In-Reply-To", "value": "<previous-id@yourapp.com>" }
],
"attachments": [
{
"filename": "screenshot.png",
"content_type": "image/png",
"size": 45678,
"url": "https://files.postscale.io/..."
}
],
"spf": "pass",
"dkim": "pass"
}
Each request also carries metadata headers:
X-Postscale-Event: email.received
X-Postscale-Delivery-ID: <uuid> (unique per attempt — use for dedup)
X-Postscale-Attempt: 1 (1-indexed; bumps on retry)
X-Postscale-Signature: t=…,v1=… (verification — see below)
Verifying Webhooks
Every request signed by Postscale carries an X-Postscale-Signature header
of the form t=<unix>,v1=<hex_hmac_sha256>. Verify it on every request to
ensure the delivery came from Postscale and was not tampered with or
replayed.
The full algorithm, t= / v1= format details, dual-signature handling
during a rotation grace window,
and Node + Python reference verifiers live in the main
Webhooks doc — that page is shared
across inbound and outbound webhooks because the verification protocol is
identical.
Use the In-Reply-To and References headers to match replies to
original messages and maintain conversation threads.
Each attachment exposes a presigned url valid for 24 hours. Download
it within that window if you need to keep a copy — Postscale doesn't
re-issue URLs on demand.