Webhooks are simple HTTP POST callbacks that Lettermint sends to your URL when events happen in your project. This way you can start a process in your application in realtime without polling—think “event notifications over HTTP.”

Prerequisites

In order to get started, you will need:
  • A Lettermint account with access to a Project and Route
  • A publicly reachable HTTPS endpoint (use a tunnel like ngrok for local dev)
  • Basic familiarity with HTTP and JSON

1. Quick Start

Create a webhook on a specific Route and verify delivery with the built-in Test Webhook.

Create a webhook in the Dashboard

  1. Go to Dashboard → Your Project → Routes → select a Route → Webhooks.
An overview of your route's webhooks in the dashboard
  1. Click “Create webhook”.
The modal to create a webhook in the dashboard
  1. Now, enter the details of your webhook
  2. Save.
Webhook details in the dashboard

Send a test delivery

  • From Webhook details → click “Test Webhook”.
  • You should receive a JSON payload like below.
{
  "id": "test-<uuid>",
  "event": "webhook.test",
  "created_at": "2025-01-01T12:34:56.000Z",
  "data": {
    "message": "This is a test webhook from Lettermint",
    "webhook_id": 12345,
    "timestamp": 1733420800
  }
}
This confirms your endpoint can receive Lettermint events.

2. Webhook Details

The following details may be useful to you:

Scope

Webhooks are attached to a specific Route within a Project. This way you can subscribe to events for a specific Route without affecting other Routes, e.g. bounces for newsletters do not affect bounces for payments.

Fields

FieldDescription
NameDisplay name of your webhook
URLThe URL we make the POST call to
EventsAn array of all possible events
EnabledA boolean indicating if your webhook is enabled or disabled
SecretEach webhook has a secret you can rotate
DeliveriesA list of recent deliveries, including status, HTTP status code, duration, and attempt number
Use multiple webhooks per route to isolate consumers (e.g., analytics vs. billing).

3. Implementing a Webhook

Node.js (Express)

// server.js
const express = require('express')

const app = express()
const PORT = process.env.PORT || 3000

app.use(express.json())

app.post('/webhooks/lettermint', (req, res) => {
  try {
    const event = req.body

    console.log('Lettermint event', event.event, event.id)

    return res.status(200).send('ok')
  } catch (err) {
    console.error(err)
    return res.status(500).send('server error')
  }
})

app.listen(PORT, () => console.log(`Listening on :${PORT}`))
What this does:
  • Parses the JSON payload and logs the event
  • Returns 200 quickly so Lettermint doesn’t retry unnecessarily

Framework Integration

Next.js (Route Handler)

// app/api/webhooks/lettermint/route.js
import { NextResponse } from 'next/server'

export async function POST(req) {
  const event = await req.json()
  console.log('Lettermint event', event.event, event.id)
  return NextResponse.json({ ok: true })
}
Use the Test Webhook button in the dashboard to trigger webhook.test and confirm this logs as expected.

Delivery & Retries

Lettermint retries failed webhook deliveries with exponential backoff. We mark an attempt as failed if your endpoint responds with a non-2xx status or times out. Retry schedule (12 attempts total):
  • 1 minute
  • 2 minutes
  • 5 minutes
  • 10 minutes (2x)
  • 15 minutes
  • 30 minutes
  • 1 hour
  • 2 hours
  • 4 hours
  • 6 hours
  • 10 hours
Every attempt will be logged in the dashboard and is visible by opening the webhook details. Here you can see the status, HTTP status code, payload and response, duration, attempt number.

Troubleshooting

Webhook is disabled
  • Ensure the webhook’s Enabled toggle is on. Disabled webhooks will not send deliveries.
No deliveries appear
  • Use “Test Webhook” on the Webhook details page.
  • Confirm your endpoint returns 2xx. 4xx/5xx will be marked as failed and retried.
Need signature verification? Repeated retries
  • Your endpoint must return 200-level status quickly. Do heavy work async.
  • Implement idempotency using the event id to avoid duplicate effects.

Next Steps