Skip to main content

What are Webhooks?

Webhooks allow you to receive real-time notifications when email events occur, such as:
  • email.sent - Email was sent
  • email.delivered - Email was delivered to recipient
  • email.opened - Recipient opened the email
  • email.clicked - Recipient clicked a link
  • email.bounced - Email bounced
  • email.complained - Recipient marked as spam

Setting Up Webhooks

1

Create an Endpoint

Create an HTTPS endpoint on your server to receive webhook events
2

Add Webhook in Dashboard

Go to SettingsWebhooksAdd Webhook
3

Enter URL and Select Events

Enter your endpoint URL and choose which events to receive
4

Test Your Webhook

Use the test button to send a sample payload

Webhook Payload

Example webhook payload:
{
  "event": "email.delivered",
  "timestamp": "2025-01-10T14:23:45Z",
  "data": {
    "id": "email_abc123",
    "to": "user@example.com",
    "from": "hello@yourdomain.com",
    "subject": "Welcome!",
    "status": "delivered",
    "deliveredAt": "2025-01-10T14:23:45Z"
  }
}

Handling Webhooks

import express from 'express';
import { TransmitClient } from '@transmit.dev/sdk';

const app = express();
app.use(express.json());

app.post('/webhooks/transmit', async (req, res) => {
  const { event, data } = req.body;

  switch (event) {
    case 'email.delivered':
      console.log(`Email ${data.id} delivered to ${data.to}`);
      break;
    case 'email.bounced':
      console.log(`Email ${data.id} bounced: ${data.bounceReason}`);
      break;
    case 'email.opened':
      console.log(`Email ${data.id} opened by ${data.to}`);
      break;
  }

  res.status(200).send('OK');
});

app.listen(3000);

Verifying Webhooks

Transmit signs all webhook requests. Verify the signature to ensure authenticity:
import crypto from 'crypto';

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

app.post('/webhooks/transmit', (req, res) => {
  const signature = req.headers['x-transmit-signature'];
  const secret = process.env.TRANSMIT_WEBHOOK_SECRET;

  if (!verifyWebhookSignature(req.body, signature, secret)) {
    return res.status(401).send('Invalid signature');
  }

  // Process webhook...
  res.status(200).send('OK');
});

Retries

Transmit will retry failed webhooks:
  • Initial retry: after 1 minute
  • Second retry: after 5 minutes
  • Third retry: after 30 minutes
  • Final retry: after 2 hours
Your endpoint must return a 2xx status code within 30 seconds to be considered successful.

Best Practices

Return 200 Quickly

Process webhooks asynchronously. Return 200 immediately, then process in background.

Verify Signatures

Always verify webhook signatures to prevent spoofing

Handle Duplicates

Webhooks may be delivered more than once. Use idempotency keys.

Log Everything

Log all webhook events for debugging and auditing
I