Skip to main content
Webhooks provide real-time notifications when events occur in your Lettr account. Instead of polling the API for updates, webhooks push event data to your server the moment something happens—whether an email is delivered, a recipient clicks a link, or an inbound email arrives.

How Webhooks Work

When an event occurs, Lettr sends an HTTP POST request to your configured endpoint with a JSON payload describing the event. Your server processes the event and responds with a success status code.
1

Event Occurs

An email is sent, delivered, bounced, opened, or received on your inbound domain.
2

Lettr Sends Webhook

An authenticated POST request is sent to your endpoint with the event payload (using your configured auth method).
3

You Verify & Process

Your server verifies authentication, processes the event, and responds with a 2xx status.
4

Lettr Confirms Receipt

Upon receiving a success response, Lettr marks the delivery as complete.

Use Cases

Webhooks enable powerful real-time integrations:
Event TypeUse Case
message.deliveryUpdate your database when emails are successfully delivered
message.bounceRemove invalid addresses from your mailing list
engagament.openTrack engagement metrics and trigger follow-up sequences
engagament.clickMeasure link performance and user interest
message.spam_complaintImmediately suppress users who mark emails as spam
relay.relay_deliveryProcess inbound emails, create support tickets, track replies

Managing Webhooks

Webhooks are created and managed through the Lettr dashboard. The API provides read-only access to list and view your configured webhooks.

Creating a Webhook

1

Open Webhook Settings

Navigate to Webhooks in the sidebar.
2

Click Create Webhook

Click the Create Webhook button.
3

Enter Your Endpoint URL

Provide the HTTPS URL where Lettr should send event notifications. This must be a publicly accessible endpoint.
4

Select Events

Choose which events to receive. You can subscribe to all events or select specific event types from the five categories (Message, Engagement, Generation, Unsubscribe, Relay).
5

Configure Authentication

Optionally set up authentication for webhook deliveries. Lettr supports:
  • None — No authentication (not recommended for production)
  • Basic Auth — HTTP Basic Authentication with a username and password
  • OAuth2 — OAuth 2.0 client credentials with client ID, client secret, and token URL
6

Save

Click Save to create the webhook. Lettr will begin sending events to your endpoint immediately.

Editing a Webhook

To update a webhook’s URL, events, or authentication:
  1. Go to Webhooks
  2. Click on the webhook you want to edit
  3. Make your changes
  4. Click Save

Enabling and Disabling Webhooks

You can temporarily disable a webhook without deleting it. This is useful during maintenance or when debugging your endpoint:
  1. Go to Webhooks
  2. Find the webhook you want to toggle
  3. Click Enable or Disable
Disabled webhooks stop receiving events but retain their configuration. Re-enabling resumes event delivery.

Deleting a Webhook

To permanently remove a webhook:
  1. Go to Webhooks
  2. Find the webhook you want to delete
  3. Click Delete and confirm
Deleting a webhook is permanent. Any events that occur while no webhook is configured will not be delivered. If you’re troubleshooting, consider disabling the webhook instead.
You can create up to 5 webhooks per account. Webhook management (create, update, enable/disable, delete) is only available through the dashboard. The API provides read-only access for listing and viewing webhook configurations.

Handling Webhooks

Here’s a basic example of a webhook handler in Node.js with Express:
import express from 'express';

const app = express();

app.post('/webhooks/lettr', express.json(), async (req, res) => {
  try {
    const events = req.body; // Array of event objects

    for (const event of events) {
      const eventType = event.msys ? Object.keys(event.msys)[0] : null;
      const data = eventType ? event.msys[eventType] : null;

      if (!data) continue;

      switch (data.type) {
        case 'delivery':
          await handleDelivery(data);
          break;

        case 'bounce':
          await handleBounce(data);
          break;

        case 'open':
        case 'initial_open':
          await handleOpen(data);
          break;

        case 'click':
          await handleClick(data);
          break;

        case 'spam_complaint':
          await handleSpamComplaint(data);
          break;

        default:
          console.log(`Unhandled event type: ${data.type}`);
      }
    }

    // Always respond with 200 to acknowledge receipt
    res.sendStatus(200);
  } catch (err) {
    console.error('Webhook error:', err.message);
    res.sendStatus(400);
  }
});

async function handleDelivery(data) {
  console.log(`Email delivered to ${data.rcpt_to}`);
  await db.emails.update(data.message_id, { status: 'delivered' });
}

async function handleBounce(data) {
  console.log(`Email bounced: ${data.rcpt_to} - ${data.raw_reason}`);
  await db.suppressions.add(data.rcpt_to, 'bounce');
}

app.listen(3000);

Event Categories

Lettr webhooks are organized into five categories:

Message Events

Events tracking the delivery lifecycle of emails you send:
  • message.injection - Email accepted by Lettr and queued for delivery
  • message.delivery - Email delivered to recipient’s mail server
  • message.bounce - Email bounced (hard or soft)
  • message.delay - Email delivery temporarily delayed
  • message.out_of_band - Out-of-band bounce after initial acceptance
  • message.spam_complaint - Recipient marked email as spam
  • message.policy_rejection - Email rejected by policy

Engagement Events

Events tracking recipient interaction with your emails:
  • engagament.open - Recipient opened the email
  • engagament.initial_open - First open of the email
  • engagament.click - Recipient clicked a link
  • engagament.amp_open - Recipient opened an AMP email
  • engagament.amp_initial_open - First open of an AMP email
  • engagament.amp_click - Recipient clicked a link in an AMP email

Generation Events

Events for message generation failures:
  • generation.generation_failure - Message failed during generation
  • generation.generation_rejection - Message rejected during generation

Unsubscribe Events

Events for recipient opt-outs:
  • unsubscribe.list_unsubscribe - Recipient unsubscribed via List-Unsubscribe header
  • unsubscribe.link_unsubscribe - Recipient unsubscribed via a link in the email

Relay Events

Events for inbound email processing:
  • relay.relay_injection - Inbound email received and queued
  • relay.relay_delivery - Inbound email delivered to your endpoint
  • relay.relay_rejection - Inbound email rejected
  • relay.relay_tempfail - Inbound email delivery temporarily failed
  • relay.relay_permfail - Inbound email delivery permanently failed
Subscribe only to the events you need. This reduces unnecessary traffic and processing on your server.

Subscribing to Events

When creating a webhook in the dashboard, you choose which events to receive. You can subscribe to all events or select specific event types from the five categories listed above.

Viewing Webhooks via API

The API provides read-only access to your webhooks. You can list all webhooks and view details for a specific webhook:
# List all webhooks
curl -X GET "https://app.lettr.com/api/webhooks" \
  -H "Authorization: Bearer lttr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Get a specific webhook
curl -X GET "https://app.lettr.com/api/webhooks/{webhookId}" \
  -H "Authorization: Bearer lttr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
The response includes the webhook configuration and its current status:
{
  "message": "Webhook retrieved successfully.",
  "data": {
    "id": "webhook-abc123",
    "name": "Order Notifications",
    "url": "https://example.com/webhook",
    "enabled": true,
    "event_types": ["message.delivery", "message.bounce"],
    "auth_type": "basic",
    "has_auth_credentials": true,
    "last_successful_at": "2024-01-15T10:30:00+00:00",
    "last_failure_at": null,
    "last_status": "success"
  }
}
To create, update, enable/disable, or delete webhooks, use the Lettr dashboard. The API is read-only for webhook management.

Best Practices

Return a 200 response as soon as possible. If processing takes time, acknowledge receipt immediately and process asynchronously. Lettr waits up to 30 seconds for a response before marking the delivery as failed.
Always verify the webhook authentication before processing. Configure Basic Auth or OAuth 2.0 on your webhook and validate credentials in your handler to ensure the request came from Lettr.
Implement idempotency in your handler. Due to retries, you may receive the same event multiple times. Use the event id to detect and skip duplicates.
Always use HTTPS endpoints. Lettr will not send webhooks to insecure HTTP URLs in production.
Set up alerting for webhook failures. The dashboard shows delivery status and recent failures for each webhook.

Learn More