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.
- created_at: 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.
- 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": "updates@acme.com",
"name": "Acme Updates"
},
"to": ["user@example.com"],
"cc": ["cc@example.com"],
"bcc": ["bcc@example.com"],
"reply_to": "help@acme.com",
"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",
"recipient": "user@example.com",
"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",
"recipient": "user@example.com",
"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",
"recipient": "user@example.com",
"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",
"recipient": "user@example.com",
"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",
"recipient": "user@example.com",
"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",
"recipient": "user@example.com",
"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",
"recipient": "user@example.com",
"reason": "hard_bounce",
"metadata": {
"X-Account-ID": "acc-xyz789"
},
"tag": "transactional"
}
}
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",
"recipient": "user@example.com",
"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",
"from": {
"email": "customer@example.com",
"name": "John Doe",
"subaddress": null
},
"to": [
{
"email": "support@acme.com",
"name": null,
"subaddress": null
}
],
"cc": [],
"recipient": "support@acme.com",
"subaddress": null,
"reply_to": "customer@example.com",
"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": "<abc123@mail.example.com>"
},
{
"name": "X-Mailer",
"value": "Apple Mail (2.3445.104.11)"
}
],
"attachments": [
{
"filename": "receipt.pdf",
"content": "JVBERi0xLjQKJeLjz9MK...",
"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
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 “user+tag@example.com”)
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 with base64-encoded content
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 handling: Attachment content is base64-encoded. Decode it before saving or processing files. See the Inbound Mail guide for code examples.
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