Skip to content

Webhook Payloads

When MXHook routes an email to your application, it delivers a structured JSON payload via HTTP POST.

Payload Format

json
{
  "message_id": "<abc123@example.com>",
  "from": "sender@example.com",
  "to": ["recipient@yourdomain.com"],
  "subject": "Hello from MXHook",
  "text_body": "Plain text content of the email.",
  "html_body": "<p>HTML content of the email.</p>",
  "headers": {
    "From": "sender@example.com",
    "To": "recipient@yourdomain.com",
    "Subject": "Hello from MXHook",
    "Date": "Wed, 19 Mar 2025 12:00:00 +0000",
    "Message-ID": "<abc123@example.com>",
    "MIME-Version": "1.0",
    "Content-Type": "multipart/mixed"
  },
  "attachments": [
    {
      "filename": "report.pdf",
      "content_type": "application/pdf",
      "size": 24680,
      "content": "base64-encoded-content..."
    }
  ]
}

Fields

FieldTypeDescription
message_idstringThe email's Message-ID header
fromstringSender's email address
tostring[]List of recipient addresses
subjectstringEmail subject line
text_bodystringPlain text body (may be empty)
html_bodystringHTML body (may be empty)
headersobjectAll email headers as key-value pairs
attachmentsarrayList of attachments (see Attachments)

HTTP Request

MXHook sends the payload as:

http
POST /your-webhook-path HTTP/1.1
Host: yourapp.com
Content-Type: application/json
X-MXHook-Signature: sha256=abc123...

Headers

HeaderDescription
Content-TypeAlways application/json
X-MXHook-SignatureHMAC-SHA256 signature (present if webhook secret is configured)

Expected Response

MXHook considers delivery successful when your endpoint returns a 2xx status code. Any other status code triggers a retry.

ResponseBehavior
200-299Delivery marked as successful
400-499Retried (may be a transient issue)
500-599Retried with exponential backoff
TimeoutRetried (default timeout: 30 seconds)

Retry Behavior

Failed deliveries are retried with exponential backoff:

AttemptDelay
1st retry~1 minute
2nd retry~5 minutes
3rd retry~15 minutes

After all retry attempts are exhausted (default: 3), the message is moved to the dead letter queue.

Released under the Apache 2.0 License.