IntegrationsIntegrations

How to Test Resend Webhooks Locally

What Webhooks Does Resend Send?

Resend is a modern email API for developers, and its webhook system notifies you about email delivery events. Events include email.sent (email accepted and sent), email.delivered (email delivered to recipient's mailbox), email.delivery_delayed (temporary delivery issue), email.bounced (email bounced), email.complained (recipient marked as spam), email.opened (email opened), and email.clicked (link clicked).

Each webhook payload follows a consistent structure with a type field for the event name, created_at timestamp, and a data object containing the email details including email_id, from, to, subject, and event-specific fields. Resend uses Svix for webhook delivery, so you get the standard svix-id, svix-timestamp, and svix-signature headers.

Resend's clean API and webhook design makes it straightforward to implement email tracking in your application. The challenge during development is having a publicly accessible URL — which ReqPour solves.

Setting Up Resend Webhooks

In the Resend Dashboard, navigate to Webhooks and click "Add Webhook." Enter your ReqPour URL and select the events you want to receive. Resend shows a signing secret for the webhook — save this for verification.

Send a test email using the Resend API or SDK:

javascript
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

await resend.emails.send({ from: 'onboarding@yourdomain.com', to: 'user@example.com', subject: 'Welcome!', html: '<p>Welcome to our app!</p>', }); ```

After sending, watch the ReqPour dashboard for webhook events. You should see email.sent first, followed by email.delivered (or email.bounced). If you are sending to a real address and the email is opened, you will also see email.opened and any email.clicked events.

Handling Resend Webhooks in Code

Here is a handler using the Svix library for verification:

typescript
import { Webhook } from 'svix';

app.post('/api/webhooks/resend', express.json(), (req, res) => { const wh = new Webhook(process.env.RESEND_WEBHOOK_SECRET);

try { const event = wh.verify(JSON.stringify(req.body), { 'svix-id': req.headers['svix-id'], 'svix-timestamp': req.headers['svix-timestamp'], 'svix-signature': req.headers['svix-signature'], });

switch (event.type) { case 'email.delivered': console.log(Email delivered: ${event.data.email_id}); updateEmailStatus(event.data.email_id, 'delivered'); break; case 'email.bounced': console.log(Email bounced: ${event.data.to}); handleBounce(event.data.to, event.data.email_id); break; case 'email.opened': console.log(Email opened: ${event.data.email_id}); trackOpen(event.data.email_id); break; case 'email.complained': console.log(Spam complaint: ${event.data.to}); suppressRecipient(event.data.to); break; } } catch (err) { console.error('Webhook verification failed:', err); return res.status(400).send('Invalid signature'); }

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

The Svix verification ensures the webhook came from Resend and has not been tampered with. During development, you can skip verification temporarily and rely on the ReqPour dashboard to inspect payloads.

Tracking Email Delivery with ReqPour

Building an email delivery dashboard requires handling multiple event types and correlating them by email ID. ReqPour helps by letting you see the complete event sequence for each email — from email.sent through email.delivered to email.opened and email.clicked.

Use ReqPour's search to filter by email ID and see all events for a specific email. This helps you understand the timing between events and build accurate delivery status tracking. For example, the delay between email.sent and email.delivered tells you about delivery latency, while the delay between email.delivered and email.opened shows engagement timing.

The replay feature is particularly useful for testing bounce handling. Capture a email.bounced event, then replay it while developing your bounce suppression logic. This is much easier than triggering real bounces by sending to invalid addresses.

Resend Webhook Best Practices

Handle email.complained events promptly by suppressing the recipient from future emails. Continuing to email users who have reported spam damages your sender reputation and can get your domain blocked.

Implement idempotent handlers using the event ID. Svix may deliver the same event more than once, and double-counting opens or deliveries skews your analytics. Store processed event IDs and check for duplicates before processing.

For production email systems, track delivery rates using webhook data. Calculate your bounce rate (bounced / sent), complaint rate (complained / delivered), and open rate (opened / delivered). During development with ReqPour, you can prototype these analytics by reviewing captured webhook data in the dashboard and testing your aggregation logic with replayed events.

Get started with ReqPour

Catch, inspect, and relay webhooks to localhost. Free to start, $3/mo for Pro.