Webhooks

Webhooks overview

The email.received webhook: its JSON payload, the request headers Inboundr sends, and how your endpoint should respond.

When mail arrives for an address, or a catch-all, routed to an endpoint, Inboundr POSTs a signed email.received event to the endpoint's URL.

Request headers#

HeaderValue
Content-Typeapplication/json
User-Agentinboundr-webhooks/1.0
X-Inboundr-Eventemail.received
X-Inboundr-Delivery-IdA unique ID for this delivery.
X-Inboundr-Signaturet=<unix>,v1=<hmac-sha256>. See verifying signatures.

These headers were originally named X-Inbound-*. Every delivery currently includes both names with the same values, so existing handlers keep working. New handlers should read X-Inboundr-*; the older names will be removed once no endpoint depends on them.

Any custom headers you configured on the endpoint are also included.

Payload#

json
{
  "event": "email.received",
  "email": {
    "id": "em_abc123",
    "threadId": "thr_xyz789",
    "messageId": "<CAEabc...@mail.gmail.com>",
    "from": "customer@example.com",
    "to": ["support@yourdomain.com"],
    "cc": [],
    "subject": "Can you help?",
    "text": "Hi there…",
    "html": "<p>Hi there…</p>",
    "attachments": [
      { "filename": "invoice.pdf", "contentType": "application/pdf", "size": 48210 }
    ],
    "verdicts": { "spam": "PASS", "spf": "PASS", "dkim": "PASS" },
    "receivedAt": "2026-07-20T10:30:00.000Z"
  }
}

eventstring

Always email.received.

email.idstring

The stored email's ID (em_…). Use it with the emails API to fetch the full message.

email.threadIdstring

The conversation's ID. Fetch the rest of the thread with GET /v1/threads/{id}.

email.attachmentsarray

Attachment metadata only: filename, contentType and size. Download the files from the attachments endpoint.

email.verdictsobject

The spam, spf and dkim check results.

Responding#

Return any 2xx status to confirm you received the event. Anything else, including a 3xx redirect or a timeout, counts as a failed attempt and is retried.

Respond quickly. Return 200 right away and do slow processing in the background, so you stay within the endpoint's timeout (10 seconds by default).