Skip to main content
Learn what events Lettermint can send and how to handle them. Subscribe to the events you need when creating a webhook.

Common envelope

All webhook events share a consistent envelope:
{
  "id": "54d7e8c9-1195-4ba0-9d3f-b9af92305add",
  "event": "message.delivered",
  "timestamp": "2025-08-08T20:14:00.000Z",
  "data": { /* event-specific object */ }
}
Fields:
  • id: Unique identifier (UUIDv4) for the specific delivery event. Useful for idempotency.
  • event: Event type.
  • timestamp: ISO timestamp when the event occurred.
  • data: Event-specific fields (documented per event below).
Common data fields:
  • message_id: The unique identifier for the message.
  • subject: The email subject line.
  • metadata: Custom metadata attached to the message (if any).
  • tag: The tag assigned to categorize the message (e.g., “newsletter”, “order-confirmation”). Will be null if no tag was assigned.

Event payloads

message.created

Message accepted for processing. Example payload:
{
  "id": "54d7e8c9-1195-4ba0-9d3f-b9af92305add",
  "event": "message.created",
  "timestamp": "2025-08-08T20:14:00.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "from": {
      "email": "[email protected]",
      "name": "Acme Updates"
    },
    "to": ["[email protected]"],
    "cc": ["[email protected]"],
    "bcc": ["[email protected]"],
    "reply_to": "[email protected]",
    "subject": "Welcome to Acme",
    "metadata": {
      "X-Campaign-ID": "welcome-2025"
    },
    "tag": "welcome"
  }
}

message.sent

Message sent to recipient server.
{
  "id": "7f9c8e2a-1b3d-4f6e-b7d2-5c9f3a7e8b0c",
  "event": "message.sent",
  "timestamp": "2025-08-08T20:15:00.000Z",
  "data": {
    "message_id": "123e4567-e89b-12d3-a456-426614174000",
    "subject": "Your weekly newsletter",
    "recipient": "[email protected]",
    "metadata": {
      "X-User-ID": "user-123"
    },
    "tag": "newsletter"
  }
}

message.delivered

Message successfully delivered.
{
  "id": "9b0c4a4e-4e29-4d8b-8b3a-3f0f3e6d2f9b",
  "event": "message.delivered",
  "timestamp": "2025-08-08T20:15:12.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Your order has shipped",
    "recipient": "[email protected]",
    "response": {
      "status_code": 250,
      "enhanced_status_code": "2.0.0",
      "content": "OK  1640705112 qp1355551phe.1 - gsmtp"
    },
    "metadata": {
      "X-Transaction-ID": "txn-456"
    },
    "tag": "order-confirmation"
  }
}

message.hard_bounced

Permanent delivery failure (e.g., user does not exist).
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "event": "message.hard_bounced",
  "timestamp": "2025-08-08T20:15:30.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Summer sale - 50% off!",
    "recipient": "[email protected]",
    "response": {
      "status_code": 250,
      "enhanced_status_code": "2.0.0",
      "content": "OK  1640705112 qp1355551phe.1 - gsmtp"
    },
    "metadata": {
      "X-Campaign-ID": "summer-sale"
    },
    "tag": "marketing"
  }
}

message.soft_bounced

Temporary delivery failure (e.g., mailbox full, transient error).
{
  "id": "9b0c4a4e-4e29-4d8b-8b3a-3f0f3e6d2f9b",
  "event": "message.soft_bounced",
  "timestamp": "2025-08-08T20:15:30.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Your order #789 update",
    "recipient": "[email protected]",
    "response": {
      "status_code": 250,
      "enhanced_status_code": "2.0.0",
      "content": "OK  1640705112 qp1355551phe.1 - gsmtp"
    },
    "metadata": {
      "X-Order-ID": "order-789"
    },
    "tag": "order-notification"
  }
}

message.spam_complaint

Recipient reported the message as spam.
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "event": "message.spam_complaint",
  "timestamp": "2025-08-08T20:16:00.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Weekly digest - August edition",
    "recipient": "[email protected]",
    "metadata": {
      "X-Newsletter-ID": "weekly-digest"
    },
    "tag": "newsletter"
  }
}

message.failed

Processing failure within Lettermint.
{
  "id": "9b0c4a4e-4e29-4d8b-8b3a-3f0f3e6d2f9b",
  "event": "message.failed",
  "timestamp": "2025-08-08T20:14:12.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Password reset request",
    "recipient": "[email protected]",
    "reason": "A network error occurred.",
    "response": {
      "status_code": 250
    },
    "metadata": {
      "X-Session-ID": "sess-abc123"
    },
    "tag": null
  }
}

message.suppressed

Message was suppressed due to previous bounce or complaint.
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "event": "message.suppressed",
  "timestamp": "2025-08-08T20:14:05.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Your account statement",
    "recipient": "[email protected]",
    "reason": "hard_bounce",
    "metadata": {
      "X-Account-ID": "acc-xyz789"
    },
    "tag": "transactional"
  }
}

message.policy_rejected

Message rejected by policy (spam or content filter). This occurs when a message’s spam score exceeds the configured threshold before delivery.
{
  "id": "c4d5e6f7-a8b9-0123-cdef-456789abcdef",
  "event": "message.policy_rejected",
  "timestamp": "2025-08-08T20:14:03.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "Limited time offer!!!",
    "reason": "Spam score threshold exceeded",
    "score": 7.5,
    "spam_symbols": [
      {
        "name": "BAYES_SPAM",
        "score": 3.5,
        "options": [],
        "description": "Bayes spam probability is very high"
      },
      {
        "name": "SUBJ_ALL_CAPS",
        "score": 1.5,
        "options": [],
        "description": "Subject is all capitals"
      }
    ],
    "metadata": {
      "X-Campaign-ID": "promo-123"
    },
    "tag": "marketing"
  }
}
Fields:
  • reason: Human-readable rejection reason (e.g., “spam content”, “policy violation”)
  • score: The spam score that triggered the rejection
  • spam_symbols: Array of spam rule matches with name, score, options, and description

message.unsubscribed

Recipient unsubscribed from the mailing list.
{
  "id": "b2c3d4e5-f6a7-8901-bcde-f01234567891",
  "event": "message.unsubscribed",
  "timestamp": "2025-08-08T20:16:30.000Z",
  "data": {
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "subject": "August newsletter highlights",
    "recipient": "[email protected]",
    "unsubscribed_at": "2025-08-08T20:16:30.000Z",
    "metadata": {
      "X-Campaign-ID": "newsletter-august"
    },
    "tag": "newsletter"
  }
}

message.inbound

Inbound email received on an inbound route. Only available for inbound route types. This event includes the complete parsed email with headers, body (text and HTML), attachments, and spam filtering results.
This event is only available for webhooks attached to inbound routes. See the Inbound Mail guide for setup instructions.
Example payload:
{
  "id": "e3d4f5a6-b7c8-9012-d3e4-f5a6b7c89012",
  "event": "message.inbound",
  "timestamp": "2025-10-02T14:30:00.000Z",
  "data": {
    "route": "support-inbox",
    "message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "envelope": {
      "remote_ip": "203.0.113.42",
      "remote_hostname": "mail.example.com",
      "helo": "smtp.example.com",
      "mail_from": "[email protected]"
    },
    "from": {
      "email": "[email protected]",
      "name": "John Doe",
      "subaddress": null
    },
    "to": [
      {
        "email": "[email protected]",
        "name": null,
        "subaddress": null
      }
    ],
    "cc": [],
    "recipient": "[email protected]",
    "subaddress": null,
    "reply_to": "[email protected]",
    "subject": "Question about my order",
    "date": "2025-10-02T14:30:00.000Z",
    "body": {
      "text": "Hi, I have a question about my recent order...",
      "html": "<p>Hi, I have a question about my recent order...</p>"
    },
    "tag": null,
    "headers": [
      {
        "name": "Message-ID",
        "value": "<[email protected]>"
      },
      {
        "name": "X-Mailer",
        "value": "Apple Mail (2.3445.104.11)"
      }
    ],
    "attachments": [
      {
        "filename": "receipt.pdf",
        "content": "JVBERi0xLjQKJeLjz9MK...",
        "url": null,
        "content_type": "application/pdf",
        "size": 45678,
        "content_id": null
      }
    ],
    "is_spam": false,
    "spam_score": 1.2,
    "spam_symbols": [
      {
        "name": "DKIM_VALID",
        "score": -0.1,
        "options": [],
        "description": "Message has valid DKIM signature"
      },
      {
        "name": "SPF_PASS",
        "score": -0.1,
        "options": [],
        "description": "SPF check passed"
      },
      {
        "name": "BAYES_HAM",
        "score": -3.0,
        "options": [],
        "description": "Bayesian classifier identified message as non-spam"
      }
    ]
  }
}
Payload fields:
  • route: Route identifier/slug
  • message_id: Unique message ID
  • envelope: SMTP envelope data from the sending server
    • remote_ip: IP address of the sending mail server
    • remote_hostname: Reverse DNS (PTR) hostname of the sending server
    • helo: HELO/EHLO domain the sender identified as
    • mail_from: Envelope sender address (MAIL FROM command, may differ from the From header)
  • from: Sender information with optional subaddress
  • to: Array of TO recipients with optional subaddresses
  • cc: Array of CC recipients with optional subaddresses
  • recipient: Primary envelope recipient
  • subaddress: Parsed subaddress from recipient (e.g., “tag” from “[email protected]”)
  • reply_to: Reply-To address if specified
  • subject: Email subject line
  • date: Email received timestamp (ISO 8601)
  • body.text: Plain text body content
  • body.html: HTML body content
  • tag: Custom tag from X-LM-Tag or X-Tag header
  • headers: All email headers excluding standard ones (From, To, Subject, etc.)
  • attachments: File attachments (see attachment delivery modes below)
  • is_spam: Whether message exceeded spam threshold
  • spam_score: Calculated spam score from Rspamd
  • spam_symbols: Array of spam rule objects, each containing name, score, options, and description fields
Attachment delivery modes: By default, attachments include base64-encoded content. You can configure your inbound route to use URL delivery mode instead, where attachments include a signed url for downloading. URLs are valid for 28 days. See the Inbound Mail guide for configuration.
Security: Always validate webhook signatures and sanitize email content before processing. Email bodies may contain malicious HTML or scripts.

webhook.test

Special event that can be triggered from the Dashboard for connectivity testing.
{
  "id": "test-7f9c8e2a-1b3d-4f6e-b7d2-5c9f3a7e8b0c",
  "event": "webhook.test",
  "timestamp": "2025-08-08T20:14:12.000Z",
  "data": {
    "message": "This is a test webhook from Lettermint",
    "webhook_id": "9f9bf19c-4a2c-45f3-a6c7-bc937224ec5a",
    "timestamp": 1754921294
  }
}

Next Steps