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.
  • 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": "[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",
    "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",
    "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",
    "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",
    "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",
    "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",
    "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",
    "recipient": "[email protected]",
    "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": "[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",
    "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...",
        "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 “[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 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